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.