Hello fellow RSpec users.
Before you all start warming up your flame throwers please let me
explain my Subject line.
I’ve been working over 4 months on a large Rails project with a few
other developers. Test coverage was spotty at best, though they
were RSpec tests. One of the other developers and I had started
adding more tests, mostly controller tests using the methodology given
at rspec.info for writing controller tests isolated from the model and
view layers using stubs and mocks.
Recently a new project manager was put in place and he brought in
another developer. This developer promptly started to re-write all
the existing controller (and later view) tests, removing all mocks
and stubs and replacing them with code to use fixtures. (He also
deletes many comments he finds in the code if he thinks they’re
obvious, but that’s another story…). His commit messages include
comments like “Stop mocking around” and “More fixes due to our test
mockery”.
When challenged on why he’s re-writing these tests instead of writing
new, missing tests (even tests using fixtures) he replied with this e-
mail with the subject “Why not MockEverything”. (Note that I do use
fixtures for model tests but follow the RSpec documentation and use
mocks/stubs for controller and view tests for isolation.) In the
email this developer mentions tests broken by the addition of
conditional to the view. This conditional used a model method not
previously used in the view, and the addition of one stub was
sufficient to fix the view test in question.
Here is his email to me, less his signature as I don’t want to make
this personal. I’d like to see what the RSpec user community has to
say in response to his comments, below:
— Why not MockEverything —
David I’ve removed the mocks on purpuse. Not that I have sufficient
ills with them to meddle without a need. We committed simple
template fixes adding a conditional and there, yet the tests broke.
Now this was to be expected, the tests were constructed by
exhaustively mocking out all methods called on the object. Add a
simple conditional be it harmless as it is now means another method
needs to be mocked out.
The MockEverything approach is not healthy, judicious use is
preferable. One thing is to write a short sample in a blog and another
is to have a working app with lots of tests. From all my apps that I
have worked on this has by far the lowest coverage both in profile and
in test value. There is no discussion we are all committed to tests.
To better see what constitutes good practice I recommend you to
inspect the source of RadiantCMS a beautiful and well engineered app
recently rewrote to use rspec instead of Test::Unit:
http://dev.radiantcms.org/browser/trunk/radiant/spec
Observe how the code is restrained in mocking, real objects are
preferred wherever possible. Incidentally they don’t use fixtures
rather factories to create real objects. Now the factory part is a
separate issue I’ll don’t discuss here, as it has its own
disadvantages especially a project with many models …
With real objects your test will not be brittle, and their value will
be kept even after adjusting the templates or doing other small
refactorings.
Contrary to common misconception test speed will not be affected
either. Especially for view tests where you don’t even have to save to
the db upon preparing the test rig.
Beside Radiant there where efforts to rspec Typo and Mephisto (both
noted rails blog engines). Still these were half harted conversions so
my arguments based on them would not have the same weight. RadiantCMS
is enough - they are used on ruby-lang.org and have converted 100% to
rspec … plus they also have good coverage showing that they actually
believe in tests. So please look into Radiant, you’ll find it most
helpful I think.
— END OF EMAIL—
Thank you,
David S.