On Mar 19, 2008, at 8:42 AM, Glenn Ford wrote:

> My primary concern when writing my specs that are to cover complicated
> features is that I do NOT want false confidence.  If I write a spec,
> and it passes, I want that to mean it works in my app.  When the spec
> goes green, my next step is to go hit Refresh in my browser.  If it
> doesn't work in my browser, then in my opinion, my spec is crap.  It's
> telling me things work when they don't.

This paragraph caught my eye, especially in my specific issue of mocks/ 
stubs versus fixtures in our own tests.

In my view tests I use mock_model with a hash of valid attributes.   
This allows a mock with automatic stubs for these valid attributes:

valid_user_attributes = {
        'name' => 'user name',
        'userid' => 'userid'
}

before (:each) do
        @mock_user = mock_model(User, valid_user_attributes)
        [...]
end

A sample test to verify that one of these attributes is properly  
displayed looks like:

it "should display the user name in the contact box" do
        do_render
        response.should have_tag('div#contact', /[EMAIL PROTECTED]/)
end

The dev that wants all fixtures does this by loading a fixture record:

before (:each) do
        user = User.find( users(:david).id )
        [...]
end

His tests written to check that particular attributes were properly  
displayed in the view look like:

   it "should display the user name in Contact Pod" do
     do_render
     response.should have_tag('div#contact', /^#{users(:david).name}/)
   end

This developer added some new code to the view in question, displaying  
a new table value and complained when my mock/stub version of the test  
failed because there was no stub to display that new attribute.   
However, though his test passed, he had failed to add the "name"  
attribute to his fixtures.  This meant that users(:david).name was  
returning an empty string ('') and his test was just checking that an  
empty string was in the view output, which would pass EVERY time!

I demonstrated this by putting an 'X' after each of the names in the  
regex (like /[EMAIL PROTECTED]/) to force a failure.  When I ran  
both versions of the test I saw the following output for my test:

</.*User NameX.*/> expected but was <"User Name\n 123 Any St....
The fixtures version of the test with the 'X' returned this error:
</^X/> expected but was <"User Name\n \n \n...
Note that nothing is showing prior to the X, because name wasn't in  
the fixture.  My point is that was much easier to forget to add the  
new attributes to the fixtures in another file.  When adding the new  
attribute to the valid_user_attributes you'd have to create it as an  
empty string ('name' => '') which would be much less likely to happen.
With the fixtures version pulling data from the fixtures files it's  
much less obvious when you have bad data in the fixture.  As far as  
maintenance, the mock/stub version only required one line to be added  
to the valid_user_attributes hash.  The fixtures version requires that  
new attribute to be added to every fixture that will be using that  
attribute and it's easy to accidently leave it out of some fixture  
records.
The result, at least in *this* particular case, is that it was much  
easier to end up with a number of tests returning false "passes" using  
the fixtures method.
I'm not a 100% mock/stub proponent, but I'm very much against 100%  
fixtures and like using mocks and stubs for view tests where what you  
are testing is that the proper data is displayed in the correct  
containers in the view.
David
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to