RSpec â Controller or Request Specs?
by David Elliott (Software Development Profession)
We recently started a new Rails 5 project, and a conversation started around if we should be using RSpec controller or request specs. A quick google search shows that in the RSpec 3.5 release notes the recommendation is as follows:
âFor new Rails apps: we donât recommend adding the rails-controller-testing gem to your application. The official recommendation of the Rails team and the RSpec core team is to write request specs instead.â
And the readme has been updated to say:
âController specs can be used to describe the behaviour of Rails controllers. As of version 3.5, however, controller specs are discouraged in favour of request specs (which also focus largely on controllers, but capture other critical aspects of application behaviour as well). Controller specs will continue to be supported until at least version 4.0 (see the release notes for details).â
So what are the differences between controller and request specs, and when should we use each?
Controller Specs
Controller specs are RSpec wrappers for Rails functional tests. They simulate a single HTTP request in each example. By default views are not rendered; the controller spec stubs views with a template that renders an empty string (the template must exist). As you only call a controller action, only the controller is tested.
Here we are testing that the response is successful, it assigns the user to the users instance variable, and that it will render the correct template (note that it doesnât actually render the template).
Pros
- Test controller actions
- Fast
Cons
- No longer recommended by Rspec
- Some methods now deprecated (
assigns
andassert_template
) - Doesnât test entire stack
Request Specs
Request specs are RSpec wrappers for Rails integration tests. They are designed to test the entire stack, including routing. You can specify single or multiple requests across multiple controllers or sessions. If we look at an equivalent test we created in the controller example above:
Here we test the users controller action as before. In addition, we also test that our routes file correctly routes the users_path
route to the controller action, as well as rendering and checking the content on our page. If we were redirecting to another page, or wanted to do multiple requests, such as a GET
and a POST
in the same example, we could do that as well.
Request specs give you the ability to test what your application does, rather than how it does it. For example, instead of testing that the right template is rendered in a controller spec, with a request spec we can test that the content we are expecting to appear actually appears in the response body.
Pros
- Test entire stack
- Fast
- Recommended by Rspec
Cons
- For existing applications using controller specs, effort required to upgrade
Conclusion
Request specs allow you to test the entire application stack, and although there were some concerns raised about speed (in Rails 4 request specs were slower than controller specs), since Rails 5 request specs are now faster than both were in Rails 4.
So which should you use? For new applications, the recommendation is clear â Request specs should be used. For existing applications support for controller specs will remain until at least RSpec version 4.0, but it is something to be aware of and whenever tests are added or updated switching to request specs would be a good idea. There is really no reason to use controller specs over request specs going forward.
References:
http://rspec.info/blog/2016/07/rspec-3-5-has-been-released/
https://github.com/rspec/rspec-rails
https://relishapp.com/rspec/rspec-rails/v/3-8/docs/controller-specs
https://relishapp.com/rspec/rspec-rails/v/3-8/docs/request-specs/request-spec
~~~~~~~~~~~~~~~~~~~~
If you enjoyed this article, please feel free to hit theð clap button and leave a response below. You also can follow us on Twitter, read our other blog or check us out on LinkedIn.
If youâd like to come and work with us, please check current vacancies on our job board!
~~~~~~~~~~~~~~~~~~~~