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.

Reply via email to