Good practices on spec'ing views?

Hey guys.

I’ve been doing RSpec for more than a year by now, yet I cannot help but
feel that I’ve never got a single view spec right. I can see that I have
very few view specs and that my views tend be a lot messier than
everything
else. I’ve read the chapter in the RSpec book about spec’ing views, but
I
still think I’m not getting it right.

Assuming that I’m a view spec noob, would you guys care to share your
experience with writing them? What works and what doesn’t? What should I
avoid at all cost? And most importantly, how does the process of writing
view specs feel?

Thanks,
Stefan

On Fri, Apr 30, 2010 at 4:26 AM, Stefan K. [email protected]
wrote:

Hey guys.
I’ve been doing RSpec for more than a year by now, yet I cannot help but
feel that I’ve never got a single view spec right. I can see that I have
very few view specs and that my views tend be a lot messier than everything
else. I’ve read the chapter in the RSpec book about spec’ing views, but I
still think I’m not getting it right.
Assuming that I’m a view spec noob, would you guys care to share your
experience with writing them? What works and what doesn’t? What should I
avoid at all cost? And most importantly, how does the process of writing
view specs feel?

After my initial learning of RSpec, I don’t think I’ve written (m)any
view specs.

Why?

  1. Views shouldn’t have much if any logic, so not much behavior to spec
  2. Views tend to change a lot as the UI of an application evolves, so
    specs tend to be brittle.

If views have a lot of logic, that’s a code smell. In rails such
behavior belongs in either the controller, or a helper, and that’s
where I invest my spec efforts.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: rubyredrick (Rick DeNatale) · GitHub
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Stefan K., 2010-04-30 11:26:

And most importantly, how does the process of writing view specs
feel?

It sucks. :wink: I don’t feel like getting any return on the investment,
so I don’t write them.

IMO views should be about looks, and looks only. The most prominent
regression issue with views (as I regard them) is getting browsers to
render them right (enough). If somebody does (even partially)
automatized (even single browser) render testing, I’m all ears.

On Fri, Apr 30, 2010 at 4:26 AM, Stefan K.
[email protected]wrote:

avoid at all cost? And most importantly, how does the process of writing
view specs feel?

Before Cucumber came onto the scene view specs were a lot more prevalent
and
relevant. Cucumber does an excellent job of allowing us to drive the
implementation the views based on what our scenarios need. When Cucumber
is
not being used, I find view specs do offer a benefit, but when using
Cucumber, I find that takes the cake to driving the view
implementation.
These days, I always use Cucumber though, so it’s been a while since
I’ve
written view specs.

In The Rspec Book, section 24.6 (chapter 24), “When I write view specs”
offers some tips for determining when to write view specs. Have you read
this section?

Zach

Stefan K. wrote:

I’ve been doing RSpec for more than a year by now, yet I cannot help but
feel that I’ve never got a single view spec right. I can see that I have
very few view specs and that my views tend be a lot messier than
everything else. I’ve read the chapter in the RSpec book about spec’ing
views, but I still think I’m not getting it right.

Assuming that I’m a view spec noob, would you guys care to share your
experience with writing them? What works and what doesn’t? What should I
avoid at all cost? And most importantly, how does the process of writing
view specs feel?

I write view specs, and doing so encourages me to move behavior out of
the views and into the controller. I find it easy to write specs to
check how I render dynamic data, but still don’t have a good feel for
writing specs that check that action buttons submit the form I expect to
submit. I imagine writing more of the latter kind of spec will encourage
me to avoid complex form submissions.

I treat view specs like any other specs: when I have a tough time
writing the spec, then I rethink my design choices.

Thank you for your answers!

In The Rspec Book, section 24.6 (chapter 24), “When I write view specs”
offers some tips for determining when to write view specs. Have you read
this section?

I though I did, but I revisited it and I learned some new things.
Thanks!

I did some thinking on my own and I reached some conclusions. I would
like
to share them – it will help me structure my reasoning. I would be
happy to
hear what you think. This is going to be long.

I’m assuming that I want to use test doubles in view specs. I don’t see
much
value in testing model, view and helper code at once. Also, I’m only
checking for the presence of text and occasionally for the presence of a
link. I’m not asserting DOM structure or rendering order.

There is a big difference between using doubles in controller specs and
in
view specs. Controllers depend only on the models. Using test doubles in
their specs leads you to a nice, clean public interface of the models
and
only a handful of simple messages in the actions. The code is just a
simple
moderator. This is what a clean controller should be, in my opinion.

Views, on the other hand, know a lot of tiny details about the models.
After
all, they should if they are to present that information in a humane
way.
Thus, they are more coupled to the models than controllers. This
requires
more intricate test doubles. Furthermore, they also invoke helpers to do
some of the work. Not only you have to mock them too, but most of the
time
helpers just take a model and return a result dependent on it. This is
tricky to mock (simplest case you make a mock of the model and set an
expectation on a helper).

That’s two problems with test doubles in view specs – (1) view and
model is
more tightly coupled and (2) you have helpers as a depend-on component.
At
this point, getting the test doubles right is too much work. The usual
problem that I have, is that as soon as I complete a refactoring in the
model, I have to spend an equal (or even greater) effort to fix the
doubles
in spec failures, that are false negatives. I think I’ve seen this named
‘fragile test’.

Thus, my approach would be to avoid writing view specs most of the time
and
make sure I’ve provided the safety net with Cucumber. That is my case
against view specs.

I can see two reasons to write them, though.

First, I can consider it as purchasing technical debt. I write a view
spec
instead of a Cucumber scenario for a small behavior modification. This
gives
me the safety net for a lower price (view specs take considerably less
time), but the cost is that it hinders refactoring.

Second, if I have something complex to display and no idea now to
organize
it, I can use a view spec to drive the design. This let’s me base it on
feedback, but when I’ve implemented the functionality back-to-back, the
view
spec has turned into an expensive artifact that hinders further
refactoring.
I’ve done that a few times – it really helps me with the design, but I
find
myself removing the spec after a while since it takes just too much time
to
maintain.

I also see two things that might invalidate this reasoning.

First, presenters. They group the model and helpers logic that the view
depends on, so now I would have to mock only one object. More
importantly,
that object is specifically designed to be used by the view, which means
that the test double will be simple and that I can use the view spec to
drive the design of the presenter.

Second, moving all logic from the view to helpers that take the model as
a
parameter. This should simplify the test doubles, although you still
will
have to set expectations on helper invocations. This moves the intricate
knowledge of the models in the helpers, which are easier to test. The
view
mediates models and helpers.

I’m not sure if I like the resulting design. While the views look slick,
you
have to understand the helpers first in order to understand the view.
Logic
that belongs together is scattered around in multiple files,
intermingled
with other logic. Also, at this point I don’t see much reason to write a
view spec either, since the code that could possibly break is either in
models or helpers, which are tested in isolation. If you insist on doing
it,
setting up test doubles is still a bit weird (you have to set
expectations
and define results on helpers and you have to use mocks for models). It
gets
particularly tricky when the view iterates over a collection and calls a
few
helpers with each item.

On the more general note, while controllers are pretty OO in they nature
and
thus can tolerate test doubles, views are, well, just procedural Ruby
embedded in HTML. Applying mocks to them doesn’t seem a good fit to me.

So, what do you think? Does this make sense? Did I miss anything?

I test dynamic behavior in views using a combination of RSpec, Watir,
and Jasmine. I don’t test the structure of the view. I keep the
structure simple and keep client side behavior mostly in client side
code (i.e. javascript.)

RSpec + Watir + jasmine is a heavy set of testing tools, but that is
because most of the heavy lifting in modern web apps is in the
browser. I want to make sure that it can’t break. I keep it from
getting too big or too slow by eliminating interactions with the
server by mocking/stubbing Ajax calls.

I have had similar experiences. If I submit the form and assert stuff
about the next page that comes up then I end up with a big slow
integration test like the kind you talk about as bad. It seems to me
like this is an overly coupled design, but I don’t know a way around
it if I intend to use HTML forms as designed.

On the other hand, I can have a button click call something
asynchronously. I can put the Ajax call in its own javascript object.
Then I can stub that. Jasmine helps me do that quite nicely.

I am not entirely sure what all of the implications of this are. It
seems to me that even though the latter solution has more complexity
in terms of javascript my tests are telling me that it has lower
coupling and higher cohesion (i.e. page behavior is in javascript
objects, not on the server. Some objects know how to talk to a server,
but I can ignore those objects when I want to ignore the server.)

On Fri, May 7, 2010 at 6:49 PM, J. B. Rainsberger