Great questions, Stefan! Let me preface my answer by saying: I’m not a rails user (and haven’t been for ~5 years) so my understanding of the situation may not be quite correct. Sam Phippen, Jon Rowe, or Aaron Kromer should be able to give you a more definitive answer but I’ll weigh in anyway.
The TL;DR is that the RSpec team has not chosen to deprecate controller specs — the Rails team has. Controller specs in rspec-rails wrap the rails controller functional testing infrastructure. The Rails team has chosen to remove this from Rails 5 — which means rspec-rails simply can’t support controller specs with Rails 5 out-of-the-box. Luckily, the rails team has moved the controller testing bits into the rails controller testing <https://github.com/rails/rails-controller-testing> gem, and writing controller specs with Rails 5 (and RSpec 3.5) should work if you add that gem to your Gemfile. As for the whether or not controller specs are a good idea: as with all things, it depends. Historically, Rails has had 2 similar (but slightly different) kinds of tests, and rspec-rails followed suit: - Controller specs - Request specs They look vaguely similar and the guidelines of when to use one vs the other is not very clear. Both allow you to simulate requests and make assertions about responses. The main difference is that controller specs instantiate your controller class and call methods on it directly (bypassing the routing layer and rack middleware stack) whereas request specs go through routing and rack middleware. This has a couple notable effects: - Controller specs were noticeably faster since they did so much less - Controller specs are full of gotchas, where something that a user would expect to work would not work because to work properly the request needs to go through one or more rack middlewares. In general, Rails controllers are designed to interact with rack middleware for all sorts of things so when you eliminate the middleware, the results can be strange and unintuitive. We’ve had many bug reports on rspec-rails that basically boiled down to “that’s just how controller specs work, so use a request spec instead for what you are trying to test.” >From what I understand, the Rails team has worked on making the full request specs faster in Rails 5 so that they are basically at speed parity with old controller specs. This means that the main benefit of controller specs over request specs (speed) no longer exists. Thus, the recommendation of the rails core team is to not write controller tests anymore, and write request tests instead. In general, that’s sound advice. For a specific project, controller specs might still make sense if you are really looking for the kind of isolation controller specs give you and understand the gotchas. I haven’t done Rails in a long time, but if I was — I’d generally try to keep my controllers free of much logic (delegating requests to bare ruby classes that can easily be tested in isolation) which means I’d tend to favor request specs as a way to ensure things work end-to-end and bypass controller specs altogether. On your project that may not be sound advice, though. HTH, Myron On Sat, May 14, 2016 at 9:54 AM, Stefan Kanev <[email protected]> wrote: Hi everybody. > > I recently watched a talk that said controller specs are getting > deprecated in the next version of RSpec. I found that surprising. I’m > definitely not trying to push against this decision, but I would really > like to understand its logic. > > I’ve thought long and hard and I was not able to convince myself that > controller specs are unhelpful. Of course, in order to be useful, they > require a certain style of writing specs and controllers. I’d like to > explain my approach and I’d really love to get some feedback. Am I missing > something that invalidates my logic? > > Let’s start with “my” style of controllers. They should contain as little > logic as possible and delegate everything else to collaborators (a model or > a service). Each controller essentially follows the same pattern: > > 1. It picks a bunch of stuff from params > 2. It passes them to a model/service that carries out the work > 3. It decides what to do next based on the outcome (render a template > or redirect somewhere) > > The create action in the default scaffold are a great example. To > summarise, a controller: > > - delegates (most of) the work to a model/service; > - is responsible for figuring out what to pass to the model/service; > - is responsible for deciding where to send the user next; > - usually communicates with a single model/service over a thin (1-2 > methods) interface; > - uses a small number (1-2) of instance variables to pass to the view. > > Now, following this style, the spec is written like so: > > - Collaborators are replaced with doubles > - Just to be clear, the database isn’t hit, neither in setup nor > verification > - Views are not rendered > - Expectations are set on (1) messages sent to collaborators, (2) the > HTTP response (redirect, render, etc) and (3) variables passed to the view. > > As far as I can tell, this is the GOOS style of testing, applied to > controllers – collaborators are mocked and the interaction itself is > tested, not the end result. If memory serves right, that’s also how The > RSpec Book talks about controller specs. If you want an example, you can > check this controller > <https://github.com/skanev/evans/blob/master/app/controllers/my_challenge_solutions_controller.rb> > and this spec > <https://github.com/skanev/evans/blob/master/spec/controllers/my_challenge_solutions_controller_spec.rb> > I wrote a while ago. > > I’m under the impression that this is the popular style of controller > specs in the RSpec community, although I might be wrong. I’m reiterating it > only to make sure we’re on the same page. > > So, anyway: assuming controller specs are written that way, I think they > are indeed useful. Just not in the same way as feature or model specs. > > The point of view I subscribe to, is that automated testing is not just > about catching regressions (Safety Net). It’s about many things, like > documentation, driving design, productivity, to name a few. Yes, the Safety > Net of controller specs is nowhere near what you get out of feature or > request specs. But that’s not why I write controller specs. I write them > because they help design. Namely, the spec: > > - gives feedback that helps keep the interface between controller and > collaborator simple; > - puts positive pressure on the design direction – another developer > is less likely to extend the controller with the business logic and more > likely to put in the service; > - helps move the logic away from the controller to a model/service, > where it can be tested in isolation and relatively faster (compared to > request/feature). > > I admit that when I was starting, this was a tricky concept to get right. > But once I grokked it, it was pivotal to my understanding of how to keep > the controller simple. Controller specs have helped me learn how to do > better design and they keep helping me to keep my designs clean. > > It goes without saying, but I also write feature specs that also cover > (some of) the logic in integration. > > So, conclusion time. If you’ve gone this far into reading this, I thank > you for your time, and I would really like to hear what you think. > > To loop back to the beginning, controller specs are getting deprecated. > Justin suggests using request specs instead. I neither feel that I will > benefit from stopping, nor I see how replacing them with request specs is > better. Hence, I don’t understand the decision to deprecate controller > specs. > > What am I missing? > > -- > You received this message because you are subscribed to the Google Groups > "rspec" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/rspec/20160514165452.GA66296%40corrino.local > <https://groups.google.com/d/msgid/rspec/20160514165452.GA66296%40corrino.local?utm_medium=email&utm_source=footer> > . > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "rspec" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/rspec/CADUxQmvY6A2hdMiWcb7ZWoePUe6ac23HO1Ozk2j32Sy5oJwxvA%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
