Testing Routes in Rails

Routes in rails are really cool but they can be confusing to newbies and, as they become more complex, it can be difficult to make sure that all of your paths are still working like you expect. My intention here is not to provide a primer on routes but rather to show how easy it is to test and verify routes.

As you define new routes it is important to write tests to validate url formats. You need tests to verify that urls are mapped to the right controller and action:

                 :controller => "dashboard",
                 :action => "directory_stations")

And you need tests to verify that controller/action combinations can be correctly mapped back to a url:

assert_recognizes({ :controller => "dashboard",
                    :action => "directory_stations" },

The console is your friend when you are trying to test or debug a tricky mapping. Launch the console and, to save some typing, assign a local variable:

$ script/console
>> r = ActionController::Routing::Routes

If you want to see currently defined routes:

>> puts r.routes
ANY /:controller/:action/:id/ {}
ANY /:controller/:action/:id.:format/ {}
=> nil

The first part of the output tells you what HTTP verb the routing applies to, ANY in this case. Other possible values are GET, POST, HEAD, etc. The next element in the output is the pattern that matches the route. The empty braces show that we don’t have any of the optional parameters defined that might modify the behavior of the route.

To verify that urls are mapped to the right controller and action use recognize_path:

>> r.recognize_path "/station/index/42.html"
=> {:controller=>"station", :action=>"index", :format=>"html", :id=>"42"}
>> r.recognize_path "/station/index/42"
=> {:controller=>"station", :action=>"index", :id=>"42"}
>> r.recognize_path "/station/index"
=> {:controller=>"station", :action=>"index"}
>> r.recognize_path "/station"
=> {:controller=>"station", :action=>"index"}

To verify that controller/action/id/etc. combinations correctly map back to a url:

>> r.generate :controller => :station
=> nil
>> r.generate :controller => :station, :action=> :index
=> nil
>> r.generate :controller => :station, :action=> :index, :id=>42
=> nil
>> r.generate :controller => :station, :action=> :index, :id=>42, :param => "xyzzy"
=> nil

7 thoughts on “Testing Routes in Rails”

  1. This is really cool, the ability to run scenarios through your routes in console! For anyone that uses Shoulda as their testing suite, I wrote a plugin to cut way down on the effort. This is the article explaining the plugin itself, with some testing background: http://bit.ly/test_routes

    Thanks again for the info on routing in the console.

  2. Congrats, Nate, this is currently google’s #1 for ‘Testing Rails Routes’. Get some adsense in here 😉


  3. Ideas why im getting this error?

    1.9.2-p290 :003 > r = ActionController::Routing::Routes
    NameError: uninitialized constant ActionDispatch::Routing::Routes
    from (irb):3
    from /Users/toddmueller/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.0/lib/rails/commands/console.rb:47:in `start’
    from /Users/toddmueller/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.0/lib/rails/commands/console.rb:8:in `start’
    from /Users/toddmueller/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.0/lib/rails/commands.rb:41:in `’
    from script/rails:6:in `require’
    from script/rails:6:in `’

  4. The listed functions seem to be for Rails 2. In Rails 3, the listed expressions are “uninitialized constants.” I can’t find these functions in Rails 3. Hints?

Comments are closed.