On Mar 18, 2008, at 6:36 AM, Alan Larkin wrote:
> David Schmidt wrote:
>> 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 Schmidt
>>
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> rspec-users mailing list
>> rspec-users@rubyforge.org
>> http://rubyforge.org/mailman/listinfo/rspec-users
>
> I was going to start a thread about mocks and fixtures this morning  
> too, so Ill
> use this one.
>
> Let me first say that I am a very very recent comer to RSpec so my  
> opinions dont
> carry much weight, but ...
>
> I have come to the tentative conclusion that mocking is fine in view  
> specs where
> you are really only interested that certain assigns have been made  
> and that they
> respond to certain messages. In fact mocks are ideal. Possibly in  
> models too.
> However in controller specs I think you find examples where fixtures  
> are just
> the best way to go. In these cases, from what I have seen, mocking  
> leads to
> brittle and frankly worthless tests (a half-arsed test is worse than  
> no test at
> all, right?).
>
> The case that crystalised that opinion for me was a spec for a  
> destroy action.
> In spec::rails scaffold (and in many examples I see online) this  
> action is
> tested by asserting that the instance receives a destroy message. I  
> personally
> think thats inadequate. It makes assumptions about implementation  
> and doesnt
> guard against unwanted side effects.
>
> I should be able to delete a record any way I please (delete, destroy,
> connection().execute(...)) and the test should pass.

However, each of those have different behaviour, and that is what I am  
spec'ing when I do model.should_receive(:destroy)

James Deville


> This is BDD after all. We
> should be testing the behaviour of the action, not the  
> implementation, and the
> desired behaviour is that the corresponding record *and only that  
> record* are
> deleted ... no one cares how its achieved. The only correct way to  
> test this
> IMHO is to assert that TheModel.find(:all) before the action is  
> equal to
> TheModel.find(:all) after the action less the record in question.  
> For this I see
> fixtures as the way to go.
>
> Just my opinion. Commence flaming.
> _______________________________________________
> rspec-users mailing list
> rspec-users@rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users


_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to