route it, route it, route it out loud

Jared Carroll

Do you have to test your routes?

Yes.

There’s no reason you shouldn’t be automating the testing of your routes. The alternative would be to open up a browser and type in each pretty url, that’s no good. How do you test them?

There’s basically 2 ways I’ve tested routes.

1.) Create a separate test file just for routes:

In test/functional/routes_test.rb:

require File.dirname(__FILE__) + '/../test_helper'

class RoutesTest < Test::Unit::TestCase

  def test_should_route_a_user_to_the_blogs_controller
    assert_routing 'blogs', :controller => 'blogs'
                            :action => 'index'
    assert_routing 'blogs/1', :controller => 'blogs',
                              :action => 'show',
                              :id => '1'
  end

end

Here all your routes test are in one place. But you have to scan this test file to find a test for a route for a specific action, this could take time.

2.) Put the assertions in the functional test for the action the route maps to:

In test/functional/locations_controller_test.rb:

def test_should_find_the_location_record_with_the_given_id_on_GET_to_edit
  get :edit, :id => locations(:boloco).id

  assert_equal locations(:boloco), assigns(:location)
  assert_response :success
  assert_template 'edit'

  assert_recognizes({ :controller => 'admin/locations',
                      :action => 'edit',
                      :id => '1' },
                    :path => 'admin/locations/1;edit',
                    :method => :get)
end

This is nice because the route test is right along side its action’s test.

What’s assertions should I be using?

There’s 3 assertions you can use:

1.) #assert_generates - tests that something like:

'blogs'

generates:

{ :controller => 'blogs',
  :action => 'index' }

ex)

assert_generates 'blogs',
                 :controller => 'blogs',
                 :action => 'index'

2.) #assert_recognizes - tests that something like:

{ :controller => 'blogs',
  :action => 'index' }

generates:

'blogs'

ex)

 assert_recognizes({ :controller => 'blogs',
                     :action => 'index' },
                     :path => 'blogs',
                     :method => :get)

That

:method => :get

in there is specifying the HTTP verb, a GET request.

3.) #assert_routing - test that #assert_generates and #assert_recognizes pass

Will test that both:

'blogs'

generates:

{ :controller => 'blogs',
  :action => 'index' }

and

{ :controller => 'blogs',
  :action => 'index' }

generates:

'blogs'

ex.)

assert_routing 'blogs', :controller => 'blogs',
                        :action => 'index'

Use #assert_routing if you’re not using RESTful routes. If you’re using RESTful routes you’ll want to specify the HTTP verb in route assertions and only #assert_recognizes supports this, so that’s your only move.