Jun 29

Everyone is familiar with routes in rails been a Rails developer we add and edit config/routes.rb many time throughout our application.But let get it straight how many of us actually write test for routes that we define.I guess hardly anyone does I too used to avoid writing it until I found out how easy and fun it is to write route test. So let me show you

A Routes Test has basically 3 parts

    1. assert_generate
    2. assert_recognizes
    3. assert_routing

1. assert_generate.
Asserts that the options you provide can be used to generate the provided path.

assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)

Let see an example
Suppose I have a routes “http://localhost:3000/users/new” so the assert_generate for the following path look like this.

assert_generate("/users/new",:controller => "user",:action => "new")

This tell that the controller and action pair generate the provided path in this case(“/users/new”)

Now make it bit complex
What about parameters passed in to the routes,well you can write test for that as well
Here how
e.g suppose above path look like this ‘http://localhost:3000/users/new?account=1’
Now as you can see the there a additional parameter that been passed now
so the test for the above path would look like

assert_generates("/users/new",{:controller => "users" , :action => "new",:account_id => "1"}, {}, {:account_id => "1"})

Now one might ask why the path isn’t written like this ‘/users/new?account=1’ that because the ‘account_id=1’ is passed as parameters and we all know one never get a path with parameter add to routes if we do rake routes. So to take care of that extra parameter one need to tell what extra(parameter) that will be passed,in this it is “account_id”

Now when you run the following test it run without any error and failure

2. assert_recognizes.
Basically it just the inverse of assert_generate.assert_recognizes asserts that Rails recognizes the route given by expected_options.

assert_recognizes(expected_options, path, extras={}, message=nil)

e.g Let do assert_recognizes for the same path(/users/new?account=1) for which we did assert_generate.
Here it is.

assert_recognizes({:controller => "users",:action => "new",:account_id => "1"},"/users/new",{:account_id => "1"})

Here again your are a specify the extra as ‘account_id’

Now see a trivial example

http://localhost:3000/users/1 => :controller => “users”, :action => “show”

http://localhost:3000/users/1 => :controller => “users”,:action => “destroy”

so the assert_recognizes for the above two would look like this

assert_recognizes({:controller => "users",:action => "show",:id => "1"},{:path => "/users/1",:method => "get"})
assert_recognizes({:controller => "users",:action => "destroy",:id => "1"},{:path => "/users/1",:method => "delete"})

3. assert_routing.
assert_routing essentially combines “assert_recognizes” and “assert_generates” into one step.

assert_routing(path, options, defaults={}, extras={}, message=nil)

assert_routing for the above path are as follow

i. “http://localhost:3000/users/1?account_id=1”

assert_routing('/users/new', {:controller => 'users', :action => 'new',:account_id => "1"},{},{:account_id => "1"})

ii. “http://localhost:3000/users/1” => Show action

assert_routing('/users/1',:controller => "users",:action => "show",:id =>"1")

iii. “http://localhost:3000/users/1” => Destroy action with method => ‘delete’

assert_routing({:method => "delete",:path => '/users/1'}, {:controller => 'users', :action => 'destroy',:id => "1"})

You Can also try few console trick while writing the test.

$ script/console
>> routes = ActionController::Routing::Routes</strong>

>> routes.generate :controller => "users" , :action => "new"
=> "/users/new"

>> routes.generate :controller => "users" , :action => "edit", :id => "1"
=> "/users/edit/1"

>> routes.recognize_path '/users/new'
=> {:controller=>"users", :action=> "new"}

>> routes.recognize_path '/users/edit/1'
=> {:controller=> "users", :id=> "1", :action=>"edit"}
Tagged with:
preload preload preload