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][controller] and [this spec][spec] I wrote a while ago. [controller]: https://github.com/skanev/evans/blob/master/app/controllers/my_challenge_solutions_controller.rb [spec]: https://github.com/skanev/evans/blob/master/spec/controllers/my_challenge_solutions_controller_spec.rb 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? -- Stefan Kanev ¦ @skanev ¦ http://skanev.com/ Every program has (at least) two purposes: the one for which it was written, and another for which it wasn't. -- 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. For more options, visit https://groups.google.com/d/optout.
