Best practices for testing Routes?

I'm wondering if there are any accepted practices for testing routes
in rails. For instance, if I added a route like:

map.root :controller => 'welcome'

And I wanted to add an assertion like:

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

Where should tests like this be placed? It seems like they could go
in a routes.rb testing class, but would that go in the functional
tests folder or in the integration folder? Or a test could be added
to the welcome controller's tests, since it's the one that should
handle the request.

I've been looking around online, and looking through some open source
rails apps, but I haven't found an answer yet. Is there a right place
for this?

Maybe I'm being overly defensive in my testing.

I tend to take the perspective that there should be a test for
anything that I expect the application to do. That way the tests can
act as a specification for what is expected of the app, and also they
guard against me doing something stupid in the future, like adding a
higher priority route that preempts the route I'm testing.

I was trying to provide the simplest example possible to avoid forcing
people to read too much, but I'm afraid my example might have been too
simple. I don't intend to test that "map.root" works, instead I want
to test that my application routes requests the way I want it to.

Here is a more in depth example of the sort of tests I'm thinking of.
Say I wanted to create a blog like the one described in example 2 of
the Rails Introduction to Routes page at http://manuals.rubyonrails.com/read/chapter/65.

If I approached this using test driven methodology I would write a
test and then add a route to fulfill that test. So, when I added my
posts/show/10 route there would have been a test proving that it
worked. Later when I added the new route from the example:

map.connect ':year/:month/:day', :controller => 'blog', :action =>
'by_date'

I would immediately notice that my posts/show/10 test failed. Then it
wouldn't take long to realize that the new route was too vague, and it
was matching the posts route when it shouldn't. So, I could get to
the better route from the example with less effort:

map.connect 'date/:year/:month/:day', :controller => 'blog', :action
=> 'by_date',
              :month => nil, :day => nil,
              :requirements => {:year => /\d{4}/, :day => /
\d{1,2}/, :month => /\d{1,2}/}

Without tests to validate my routes I might not have noticed this
mistake as quickly, and once I did notice it might take me longer to
find the problem if I had made other changes between adding the
problem route and noticing the problem.

I realize not everyone uses TDD, but I'm sure some Rails developers
do. I'm wondering if any test first Rails people out there have any
advice on where to stick tests of this nature.

ryan_s,
I tend to put these tests in the same file that tests the controller to which the route is connected. For the example in this message, that'd be in test/functional/blog_controller_test.rb. But know that there are two forms that your testing needs to take.

For a GET route, it's as simple as (I always put a test that the controller name is right, too):

   def test__controller_naming
     assert_equal('similarity', @controller.controller_name,
                  "None of the routing tests will work if controller_name is not 'similarity'")
   end

   # for a non-standard default action
   def test__route_similarity_categories
     assert_routing '/similarity', { :controller => 'similarity', :action => 'categories' }
   end

   # for a nested-ish resource
   def test__route_similarity_candidates
     assert_routing('/similarity/1/group/2',
                    { :controller => 'similarity', :action => 'list',
                      :id => '1', :trait_group => '2' })
   end

However, if you want to test that the specific kind of request is used, you need to use the two separate methods that assert_routing uses internally because there's no way to pass all the needed options through.

   # Need to split these out in order to require that POST is used.
   def test__route_similarity_make_similar
     assert_recognizes({ :controller => 'similarity', :action => 'make_similar',
                         :id => '1', :trait_group => '2', :leader => '3', :follower => '4' },
                       { :path => '/similarity/1/group/2/3/4', :method => :post })

     assert_generates('/similarity/1/group/2/3/4',
                      { :controller => 'similarity', :action => 'make_similar',
                        :id => '1', :trait_group => '2', :leader => '3', :follower => '4' })
   end

This route happens to be for an AJAX'd action so less fluff in the URL wasn't a concern.

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

Thanks Rob, this is just the sort of information I was looking for.

Ryan

The way I think about this is that I'm testing that what I put in my
config/routes.rb file does what I think it should.

For those using RSpec, the latest version makes two specs for a
controller if you use the "script/generate rspec_scaffold foo" command

specs
   controllers
       foos_controller_spec.rb
       foos_routing_spec.rb

The foos_controller_spec.rb corresponds roughly to the test case for
the controller in the test/integration directory and contains
specifications of the behavior of the controller.

The foos_routing_spec.rb contains specs for routes pertaining to the
FoosController.

I was quite skeptical about Rspec when I first learned of it a year
ago, but it's winning me over.

That's interesting Rick. I've been meaning to look into RSpec for a
while now, but this gave me the impetus to actually do it. It looks
to me like a nice way of providing more verbose tests. I think I'll
give it a try and see how I like it. Thanks for the tip.

Ryan