|
Peter Marklund's Home |
Rails Recipe: Checking for Broken Links in Integration Tests
Having a way to automatically check for broken links in your application can be quite valuable and there is a simple way to do that with integration tests. Here is the DSL methods that I used for that purpose along with some sample usage:
module TestingDSL
def visits_start_page
get_with_links("/mcm") do
assert_tag :tag => 'a', :attributes => {:href => '/mcm/contacts/search_form'}
end
end
def get_with_links(*args)
request_with_links(:get, *args)
end
def post_with_links(*args)
request_with_links(:post, *args)
end
def request_with_links(method, *args)
self.send(method, *args)
yield if block_given?
assert_response :success
check_links
end
def check_links
find_all_tag(:tag => 'a').each do |anchor|
url = anchor.attributes['href']
if check_url?(url)
get(url)
assert_response_code
end
end
end
def check_url?(url)
[/mailto:/, /javascript:/, /user\/logout$/, /:\/\//, /^\#$/].each do |skip_pattern|
return false if url =~ skip_pattern
end
true
end
def assert_response_code
assert [200, 302].include?(@response.response_code),
"Invalid response code #{@response.response_code} for path #{@request.path} #{@response.body}"
end
end
I've found this approach to link checking helps me find bugs that other tests don't find. The only downside is that it can significantly increase the number of requests in your integration tests and thus the test time. There are ways to work around that though, you don't have to check links on every page request, and the link checker could be extended to not request the same URL twice.