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:
paramsThe create action in the default scaffold are a great example. To summarise, a controller:
Now, following this style, the spec is written like so:
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 and this spec 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:
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 rspec+un...@googlegroups.com.To post to this group, send email to rs...@googlegroups.com.To view this discussion on the web visit https://groups.google.com/d/msgid/rspec/20160514165452.GA66296%40corrino.local.For more options, visit https://groups.google.com/d/optout.
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 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:
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:
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
--
To view this discussion on the web visit https://groups.google.com/d/msgid/rspec/1463245789.2265969.607836353.1F8B788C%40webmail.messagingengine.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rspec/CAK-y3CthYrttU5tM8sAV%3DJiOED3ou7Qr15-8%2BeHaE2z4o%2Bg1Bw%40mail.gmail.com.