Where to test routes in ruby on rails

13,313

Solution 1

Routes should be done as part of integration tests. Integration tests are where you test the important work flows of your application - more specifically whether a URL is defined or not seems to be an important workflow.

Your integration test would look like any normal integration test:

# /tests/integration/routes_test.rb
require 'test_helper'

class RoutesTest < ActionController::IntegrationTest
  test "route test" do
    assert_generates "/photos/1", { :controller => "photos", :action => "show", :id => "1" }
    assert_generates "/about", :controller => "pages", :action => "about"
  end
end

As to @jemminger's response of not testing routes - While it is Rail's tests that verify that routes.rb works, it's not Rail's responsibility to test whether http://yoursite.com/users is defined in your routes. The caveat is that most route testing could be done in existing integration tests, so specific tests for routes could be redundant.

The specific use case I can think of are all the people that have already, or are going to upgrade from Rails 2 to Rails 3. The code to define routes has changed significantly, and it's better to find out from tests that the routes were upgraded correctly, than from users when they report 404 errors.

Solution 2

Why do you feel the need to test the routes? Purely to make sure that the routes defined in your routes.rb actually work? If so, then don't. That's not the job of your application's tests to make sure that the framework's internals operate properly - that's the job of the Rails framework's own tests.

If perhaps you have some sort of dynamic/user definable route that you want to test, I'd probably go with integration.

Solution 3

I suggest you create a test file for the routes in your test/controllers folder.

class HomeRoutesTest < ActionController::TestCase

  test "must route to home index" do
    assert_routing '/', controller: "home", action: "index"
  end

end

It was mentioned that they belong to integration test. I disagree. You merely test routes, that's it. So it would rather fall into functional or even unit testing instead of integration testing.

You can find a reference in the Rails RailsGuide Testing, section 9. Testing Routes

Integration tests are for the flow, where you test the interaction of different controller action, e.g. executing a business process like user logs in, browses the site and puts an item into the basket. That said your integration tests won't work if your routes don't work. Thus many say that integration tests is the place where you test routes. However, considering the development cycle, you would create unit tests, controller tests, route tests, etc. first before doing the integration tests.

And on another note: assert_routing does both tests: assert_generates and assert_recognizes.

Solution 4

According to a comment in this rails bug, the proper place is in a functional test. If you try to test them in an integration test, the routes you established in routes.rb will not be available.

require 'test_helper'

class FooControllerTest < ActionController::TestCase
  test "foo routes" do
    assert_recognizes({:controller => 'foo_controller', :action => 'list'}, '/foos'
  end
end

Route tests are good places to list links that exist in the wild, and avoid inadvertently breaking them with a code change. It's a little strange that the tests are scoped to a controller, since it's the route set as a whole you're actually testing, but I haven't heard of a 'route set test'.

Share:
13,313
Anthony Serdyukov
Author by

Anthony Serdyukov

I'm a CTO at EDISON Software Development company with 10 years of experience. I'm specialized in .NET, Qt, web Development, cryptography, federated authentication, project management, architecture and system design.

Updated on June 14, 2022

Comments

  • Anthony Serdyukov
    Anthony Serdyukov about 2 years

    Where to test routes in ruby on rails?

    • unit tests?
    • functional tests?
    • integration tests?

    Addition:

    To be exact, where to apply assertions described on guides and on api?

  • Anthony Serdyukov
    Anthony Serdyukov over 13 years
    Please take a look at addition to the question.
  • jemminger
    jemminger over 13 years
    Again, ask yourself "Why?" You should be testing the parts of your application that are outside the scope of the basic framework's responsibilities, and that are potential failure points. If you have some routes that need testing under different scenarios, then use those route testing helpers. I would probably use them in functional and/or integration tests.
  • Anthony Serdyukov
    Anthony Serdyukov over 13 years
    "Why?" is another question. It's reasonable, but another. There are dedicated assertions and the question is where to use them?
  • jemminger
    jemminger over 13 years
    Routes deal with URLs, so my inclination would be to test them in functional/integration tests. They might not even be included by default in unit tests. Ultimately, there's no hard rule where it's permissable or forbidden.
  • Michael Durrant
    Michael Durrant almost 13 years
    I think that the important thing that gets tested here (as it should be) is that the route exists at all. So the application structure is getting tested. That way if someone changed a route that a function depends on then there is a test to catch that. i.e. you don't need to test so much that the route 'works' just that it 'exists'. You'll test separately whether it 'works' with controller testing. So as always tests are never required... but strongly recommended and the more of your application that you depend on, the more comprehensive your tests should be.
  • mrt
    mrt almost 10 years
    Just a note that the assert_recognizes might be the assertion you wanna use.
  • Debajit
    Debajit almost 10 years
    Redirected routes (which do not have a controller e.g. if you redirect say an old RSS feed to a new RSS feed url) cannot be tested in functional tests. They can only be part of an integration test (At least if you're using Minitest)
  • Ely
    Ely about 9 years
    This answer should not be the accepted answer. Routes testing should belong to Functional Tests, as referenced in the RailsGuides for Testing.
  • Marius Butuc
    Marius Butuc about 9 years
    For newer versions of Rails, your class should inherit from ActionDispatch::IntegrationTest as opposed to ActionController::IntegrationTest
  • Daniel
    Daniel about 8 years
    Example code here on rail guides: guides.rubyonrails.org/testing.html#testing-routes
  • Michael Wang
    Michael Wang over 6 years
    The purpose of testing routes is not to test Rails internal operation. It's to test if I wrote the routes.rb correctly. E.g. it's common to missing 's' in "get '/users', to: 'user#index'", you want to catch this kind of error in build time instead of runtime.
  • jemminger
    jemminger over 6 years
    @MichaelWang Wouldn't your controller or integration tests catch those?
  • Michael Wang
    Michael Wang over 6 years
    @jemminger Yes, if the routes is defined by standard resources, I would test them in controller tests. But there are cases for customized routes, such as "get '/colleagues', to: 'user#index'". In such cases, I don't think it's controller tests' responsibility to test them. Therefore, as you suggest, a good place to test would be integration test.