stupid question about BDD

Hi,

I’m divin’ into BDD with RSpec, Cucumber & Friends and wanted to know whether I got it right. When I go for BDD I skip unit tests? Is that right or am I wrong?

Thanx.

Cheers,
Chris

No, you should complement BDD with unit tests of some sort.

Unit tests at the model level are very helpful and important IMO.

I tend to have very light unit tests on my views and fairly light on
my controllers since since the bulk of the code is in models (and
Cucumber tests the view/controller pretty well.)

Thanks for the replies.

I fired that question cause I bought a bunch of BDDCasts from (bddcasts.com) and the first thing they did when bootstrapping the application, was to delete the test folder. So that and the first chapter of the book (mentioned above) got me thinking that bdd replaces unit testing as it is focusing on behaviour which is in total contrast to unit tests which focuses on . Sure, you still could test in both directions but somehow that idea sounded like a lot of work.

Random thought, but if they're using RSpec for unit testing then the
test folder would be redundant (everything would go into spec/).

Why? What does a "unit test" do that an RSpec test of your models
doesn't?

About this topic from the author of the book -

http://blog.davidchelimsky.net/2009/02/02/rspec-works-with-test-unit/Thanks to Shannon on vark.com for pointing me towards this.

The primary difference between – say – rSpec and Test::Unit is syntactical. However, the specification of how something “should behave” puts you in a different frame of mind than testing that something did behave that way. Consider this:

it “should have 10 records” do

MyModel.create(:amount => 40.50, :tax_rate => 0.10)

MyModel.first.tax.should ==(4.50) # forget, for the moment, floating point inaccuracy

end

This is specifying the behavior that a $40.50 purchase taxed at 10% should set a “tax” attribute in the model to $4.50. The Test::Unit alternative is to assert that this happened. E.g.:

MyModel.create(:amount => 40.50, :tax_rate => 0.10)

assert_equal(4.50, MyModel.first.tax)

Ultimately, you are:

  1. Unit testing

and

  1. Doing the exact same thing with somewhat different syntax

Personally, I read and write the rSpec syntax more naturally than Test::Unit, but it’s a matter of taste.

Now, if you go to Cucumber or Rails Integration testing, you are moving away from unit testing to more end-to-end behavioral testing. My personal opinion is that they are both important for a project of any scale, but writing the scenarios for Cuke first and the unit tests to drive the features out is the most natural way to do it.

Hope this helps

The primary difference between – say – rSpec and Test::Unit is syntactical. However, the specification of how something “should behave” puts you in a different frame of mind than testing that something did behave that way. Consider this:

it “should have 10 records” do

MyModel.create(:amount => 40.50, :tax_rate => 0.10)

MyModel.first.tax.should ==(4.50) # forget, for the moment, floating point inaccuracy

.should == 4.05 # floating point isn’t THAT bad :wink:

end

This is specifying the behavior that a $40.50 purchase taxed at 10% should set a “tax” attribute in the model to $4.50. The Test::Unit alternative is to assert that this happened. E.g.:

MyModel.create(:amount => 40.50, :tax_rate => 0.10)

assert_equal(4.50, MyModel.first.tax)

Ultimately, you are:

  1. Unit testing

and

  1. Doing the exact same thing with somewhat different syntax

Personally, I read and write the rSpec syntax more naturally than Test::Unit, but it’s a matter of taste.

Now, if you go to Cucumber or Rails Integration testing, you are moving away from unit testing to more end-to-end behavioral testing. My personal opinion is that they are both important for a project of any scale, but writing the scenarios for Cuke first and the unit tests to drive the features out is the most natural way to do it.

Hope this helps

Thanks for the replies.

I fired that question cause I bought a bunch of BDDCasts from (bddcasts.com) and the first thing they did when bootstrapping the application, was to delete the test folder. So that and the first chapter of the book (mentioned above) got me thinking that bdd replaces unit testing as it is focusing on behaviour which is in total contrast to unit tests which focuses on . Sure, you still could test in both directions but somehow that idea sounded like a lot of work.

You received this message because you are subscribed to the Google Groups “Ruby on Rails: Talk” group.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.

You received this message because you are subscribed to the Google Groups “Ruby on Rails: Talk” group.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.

Rob Biedenharn http://agileconsultingllc.com

Rob@AgileConsultingLLC.com

+1 513-295-4739

Skype: rob.biedenharn

Satyajit Malugu wrote:

Hassan Schroeder wrote:

    sax wrote:
    > No, you should complement BDD with unit tests of some sort.

    Why? What does a "unit test" do that an RSpec test of your models
    doesn't?

About this topic from the author of the book -

http://blog.davidchelimsky.net/2009/02/02/rspec-works-with-test-unit/*
*

The above link just says it is possible, which can be useful if you are
converting an existing application from unit tests to cucumber, rspec.
Rspecs are designed to replace unit tests not complement them. If you
are starting a new application using BDD you should be creating rspecs
not unit tests.

Edward

The primary difference between – say – rSpec and Test::Unit is syntactical. However, the specification of how something “should behave” puts you in a different frame of mind than testing that something did behave that way. Consider this:

it “should have 10 records” do

MyModel.create(:amount => 40.50, :tax_rate => 0.10)

MyModel.first.tax.should ==(4.50) # forget, for the moment, floating point inaccuracy

.should == 4.05 # floating point isn’t THAT bad :wink:

Gee. A broken test, right out of the box. My bad. Well, I guess that cements the deal. If my program passes the spec above, there’s definitely a bug somewhere. Programmer error?

**MyModel.create(:amount => 40.50, :tax_rate => 0.10)

**assert_equal(4.50, MyModel.first.tax)

You should definitely work for the government. :wink:
Gonna recommend you. :stuck_out_tongue:

(Typos can happen to anyone.)

Cheers,

Chris

I got it as wrong as you did.

until I grabbed a copy of "The RSpec book" from the Pragmatic
bookshelf
http://pragprog.com/titles/achbd/the-rspec-book

It's the best insight into the workflow and practices, I thought I got
it all until i read this book (still reading...)

It's worth it mate,

Cheers,
Bachir

That all depends on ones definition of a unit test of course. I think
of a unit test as something that tests the model or other low level
component of an application (ie a unit). I believe the term
originally arose from testing units of hardware rather than software,
though I may be wrong here. From that point of view I would suggest
that all methods of a model should be tested by unit tests, but which
testing framework one uses to do this is a matter of personal taste.

Colin

It probably did originate in hardware testing, my intuition tells me
that it might well have come from military or manned spaceflight
projects*.

For software the terms unit and integration testing probably
originated in the 1970s when the big ideas were functional
decomposition and stepwise refinement. The predominant way to develop
large software systems was to do a lot of analysis up front, divide
the problem into smaller, but still rather large components, then
break these down into subcomponents, and the subcomponents into
individual functions/subroutines which were flow-charted before being
handed to 'coders'.

Unit testing insured that the functions/subroutines did what they were
intended to do.
Integration testing insured that the subcomponents did what they were
intended to do, it effectively tested the interactions between the
pieces covered by unit tests, and that the subcomponents implemented
their components as intended.
System testing was effectively the next step up, insuring that the
entire system worked as specified.

These days folks tend to call what used to be called integration
testing functional testing, and what used to be called system testing
integration testing, probably because there's been a shift from
building whole systems to building hopefully reusable components.

Thankfully there's a lot less of the old separation of development
into analysis/implementation phases these days.

Rails muddied the waters by using functional testing to refer to what
was mostly unit testing of controllers. And the term functional
testing is already muddy because many people consider functional tests
as tests of the function of a piece of the system at whatever level,
and non-functional testing to be about testing aspects such as
performance, scalability, security ...

* I recently read "Angle of Attack" a history of North American
Aviation's involvement in the Apollo program. It mentioned that NAA
instituted stand-up meetings, something which many practitioners of
'agile' practices use. It also mentioned that the guy who introduced
them had experience them as part of an Air Force project.

Neither. It depends on your workflow, the resources that you have and
results that you want. I started with Test::Unit, never really 'got
it', and moved onto RSpec. Again, I just never really felt
comfortable with the admixture of test code and program specification
occurring in the same place. Plain text stories were added to RSpec
about a year ago last August and that seemed to me more promising.
However, I again got lost in the setup and configuration details.

However, all that effort eventually led me to Cucumber. It seems to
me that Cucumber's approach significantly lowers the intellectual
loading on the developer because it focuses ones attention on just one
aspect of the problem domain (testiing) at a time. In the feature
files you concentrate on what to test. In the step files you
concentrate on how to test.

In my own case, although I have some unit tests and some RSpec tests,
in the main I now just write Cucumber features and steps. My gut
feeling is that Cucumber has got it right for applications that are
primarily all about presentation (not to exclude other application
types but this is what Rails is all about) , that testing how the
system 'presents' itself to the end users is the only testing that
matters. If you are testing that from the outset then the boundary
conditions that creep in when one does stand alone tests first and
then integration tests after are wrinkled out from the outset.

I have listened to the arguments for mocking and such, but other than
for external services that lack a test interface themselves, I remain
unconvinced that it ever serves better to mock database tables and
attributes than to hit the actual database. I know that this is
absolute heresy in some quarters but I just do not see any significant
advantage to mocking. Other than, perhaps, in the circumstance where
application developers do not have control over database access or
design even for development and testing purposes. And if that
condition exists then I would have serious reservations regarding the
likelihood of a successful project whether mocking is used or not.

I mention this because it seems to me that the main difference between
TestUnit/Rspec/etc. and Cucumber is the mental approach to what you
are doing. Cucumber's approach seems to me to do a better job of
keeping ones attention on what should be done and then allowing one to
concentrate on how to prove that this is accomplished in detail after
the big picture is sketched. In my opinion, TestUnit, Rspec and
brethren just drop one down far too low and far too fast into the
details of testing and mocking often forms a considerable component of
that detail. Unless one already has a great deal of development
experience and self discipline, and sometimes even with those worthy
attributes, one can get too caught up in the details of testing at the
expense of everything else.

Anyway, if my own experience is any guide: If you start out with
Cucumber and develop the knack for keeping the feature clauses at a
high enough level to convey intent without revealing implementation
details; And if you keep the step definitions small, focused and
numerous enough to force the application through the wringer; Then I
doubt that adding TestUnitt or RSpec tests later will add any
significant value in the vast majority of cases.

Of course, as they say, YMMV.

Satyajit Malugu wrote:

Hassan Schroeder wrote:

    sax wrote:
    > No, you should complement BDD with unit tests of some sort.

    Why? What does a "unit test" do that an RSpec test of your models
    doesn't?

About this topic from the author of the book -

http://blog.davidchelimsky.net/2009/02/02/rspec-works-with-test-unit/*
*

The above link just says it is possible, which can be useful if you are
converting an existing application from unit tests to cucumber, rspec.
Rspecs are designed to replace unit tests not complement them. If you
are starting a new application using BDD you should be creating rspecs
not unit tests.

That all depends on ones definition of a unit test of course. I think
of a unit test as something that tests the model or other low level
component of an application (ie a unit). I believe the term
originally arose from testing units of hardware rather than software,
though I may be wrong here. From that point of view I would suggest
that all methods of a model should be tested by unit tests, but which
testing framework one uses to do this is a matter of personal taste.

I would suggest that it is not necessarily desirable to test every method in a model. Rather, it is desirable to test whether your model does what it is supposed to do -- irrespective of the methods used to achieve that end. This makes the "refactor" of red/green/refactor much more pleasant because you don't necessarily need to rewrite your tests (specs) just because you either 1) added a method to factor out common functionality; or 2) changed some method name in the guts of your model. The important point is that in a proper spec, the model should *behave* as specified both before and after refactoring.

Someplace else in this thread, the rSpec book was mentioned. I highly recommend it. Additionally, consider joining the rspec and cukes groups on Google Groups, as they discuss both unit and integration testing in the context of these two tools. I think you'll find the insights of frequent posters on these lists invaluable.

Steve

...

I would suggest that it is not necessarily desirable to test every method in a model. Rather, it is desirable to test whether your model does what it is supposed to do -- irrespective of the methods used to achieve that end. This makes the "refactor" of red/green/refactor much more pleasant because you don't necessarily need to rewrite your tests (specs) just because you either 1) added a method to factor out common functionality; or 2) changed some method name in the guts of your model. The important point is that in a proper spec, the model should *behave* as specified both before and after refactoring.

I disagree, not in the principle that a model should 'behave' as
specified, but whether this can always easily be ensured by top level
behavioural analysis. Sometimes special cases that should be tested
are much more obvious when looking at low level functions than looking
at high level behaviour. For example I would ensure that for each
conditional statement in a method there is a test that checks the true
and false path for each condition. Otherwise these may be executed in
production, perhaps in some unusual situation, when they have not been
tested.

Colin

Even if, from a high level, your feature uncovers the fact that
there's a problem, a thorough set of specs testing specific low-level
behaviors can tell you exactly where that problem lies. Five minutes
of spec writing can save me an hour of troubleshooting. I'm still
pretty new to TDD, but the time I've saved fixing problems has
convinced me.

If you're doing *test-driven* development there won't *be* any
methods in your code that don't have tests, whether done under
`rake test` or rspec or whatever :slight_smile: