Unit Testing of Routes

Hi,

I am trying to pull together a unit testing for routes but I am
getting confused. I have read AWDWR section 21.4 which explains how
to code the assertions. http://guides.rubyonrails.org/testing.html#testing-routes
also basically says the same. The problem I have is working out what
else I need in my test/unit/test_routing.rb.

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

  def test_recognizes
    ActionController::Routing.use_controllers! ["quote"]
    load "config/routes.rb"
    test "internal routing" do
      assert_recognizes({"controller" => "quote" , "action" =>
"index" }, "/quote" )
      assert_recognizes({"controller" => "quote" , "action" =>
"new" }, "/" )
    end
  end

  def test_routing
    true
  end

The output is the following:

$ ruby -I development test/unit/routing_test.rb
Loaded suite test/unit/routing_test
Started

Finished in 0.000182 seconds.

0 tests, 0 assertions, 0 failures, 0 errors

Agreed it is super fast, but there appears to be no testing going on.
It's early days on my testing on Rails so I am sure I am missing
something major here. Thanks for any pointers in the right direction.

O.

The example in the guide does the testing in a functional test, where
the routing system is already loaded. I'd recommend that you do the
same.

--Matt Jones

You need to put those test methods into a Test::Unit::TestCase...

Hi,

I am trying to pull together a unit testing for routes but I am
getting confused. I have read AWDWR section 21.4 which explains how
to code the assertions. http://guides.rubyonrails.org/testing.html#testing-routes
also basically says the same. The problem I have is working out what
else I need in my test/unit/test_routing.rb.

Change the file name from test_routing.rb to routing_test.rb (the rake task to run the tests is probably looking for *_test.rb). Your specific run of the file with ruby is actually fine, however.

I typically put these into test/functional/..._test.rb because they relate to controllers (and functional tests are really "unit tests for controllers").

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

class RoutingTest < Test::Unit::TestCase

  def test_recognizes
   ActionController::Routing.use_controllers! ["quote"]
   load "config/routes.rb"
   test "internal routing" do
     assert_recognizes({"controller" => "quote" , "action" =>
"index" }, "/quote" )
     assert_recognizes({"controller" => "quote" , "action" =>
"new" }, "/" )
   end
end

# get rid of this do-nothing test

def test_routing
   true
end

end

The output is the following:

$ ruby -I development test/unit/routing_test.rb
Loaded suite test/unit/routing_test
Started

Finished in 0.000182 seconds.

0 tests, 0 assertions, 0 failures, 0 errors

Agreed it is super fast, but there appears to be no testing going on.
It's early days on my testing on Rails so I am sure I am missing
something major here. Thanks for any pointers in the right direction.

O.

I would similarly avoid testing more than one route per test. I tend to only bother with routing tests when they relate to AJAX callbacks or otherwise represent literal URL strings in JavaScript. Your tests seem to be verifying that you are using Rails routing properly -- not that it is wrong, but it should be more for your learning that a habit that you continue once you understand how to create routes.

Here's some actual code from the test/functional/similarity_controller_test.rb on one of my projects (but only some parts that are testing routes). (And be aware that this project is *OLD* as in Rails 1.2.6 so investigate how to do the same thing in your particular version of Rails. In particular, I know that setup is completely different in Rails 2.x.)

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

# Re-raise errors caught by the controller.
class SimilarityController; def rescue_action(e) raise e end; end

class SimilarityControllerTest < Test::Unit::TestCase
   fixtures :users, :categories, :products

   def setup
     @controller = SimilarityController.new
     @request = ActionController::TestRequest.new
     @response = ActionController::TestResponse.new
   end

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

   # vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb

   def test__route_similarity_categories
     assert_routing '/similarity', { :controller => 'similarity', :action => 'categories' }
   end

   def test__route_similarity_trait_groups
     assert_routing '/similarity/1/groups', { :controller => 'similarity', :action => 'trait_groups', :id => '1' }
   end

   def test__route_similarity_candidates
     assert_routing('/similarity/1/group/2',
                    { :controller => 'similarity', :action => 'list',
                      :id => '1', :trait_group => '2' })
   end

#....

   # 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

   # Need to split these out in order to require that DELETE is used.
   def test__route_similarity_remove
     assert_recognizes({ :controller => 'similarity', :action => 'remove',
                         :id => '1', :trait_group => '2', :follower => '4' },
                       { :path => '/similarity/1/group/2/remove/4', :method => :delete })

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

#....
end

I hope that helps you.

-Rob

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

Rob and Matt,

Thanks for your reply. I have now got my head around this now, and
have now traced where my routing problem is and now have an reusable
test to check I don't break things by changing routes.rb in future.
Rob, having a real-life example was what I was really looking for in
the documentation, I always find that more useful.

Here is my new 'functional' test in full as a reference for future to
just get the basic stuff going.

# test/functional/routing_test.rb
require File.dirname(__FILE__) + '/../test_helper'

class RoutingTest < ActionController::TestCase

  def setup
    load "config/routes.rb"
  end

  def test_recognizes_quote_routes
    ActionController::Routing.use_controllers! ["quote"]
    assert_recognizes({:controller => 'quote' , :action => 'index' },
"/quote" )
    assert_recognizes({:controller => 'quote' , :action => 'new' },
"/" )
    assert_recognizes({:controller => 'quote' , :action =>
'affiliate', :affiliate => 'xxxx'}, "/xxxx" )
    assert_recognizes({:controller => 'quote' , :action =>
'promotion', :affiliate => 'scan', :promotion => 'promo'}, "/scan/
promo" )
  end

  def test_recognizes_policyholder
    ActionController::Routing.use_controllers! ["policyholder"]
    assert_recognizes({:controller => 'policyholder' , :action =>
'new' }, "/policyholder/new" )
    assert_recognizes({:controller => 'policyholder' , :action =>
'edit', :id => '3' }, "/policyholder/edit/3" )
  end

  def test_recognizes_confirmation
    ActionController::Routing.use_controllers! ["confirmation"]
    assert_recognizes({:controller => 'confirmation' , :action =>
'new' }, "/confirmation/new" )
  end

end

-- and to run it.

$ ruby test/functional/routing_test.rb
Loaded suite test/functional/routing_test
Started
...
Finished in 0.157376 seconds.

3 tests, 7 assertions, 0 failures, 0 errors

Thanks again.

O.