On Thu, Jan 14, 2010 at 5:46 AM, John P. [email protected]
wrote:
Normally in .Net when TDDing a controller class I would mock out other
library classes that the controller calls, such as Repository layer
classes. However I notice when using Cucumber people very rarely mock
anything and I’m assuming this is because Cucumber is meant for testing
the full stack (Integration testing).
Cucumber is intended for Acceptance Testing. The entry point into the
system
can vary. With Rails you can go through the browser (driving Selenium,
Watir, etc from Cucumber), start at the router, or even go directly to
the
model in cases where that’s appropriate.
re: Integration testing, everybody has a different definition. Before
Rails
came along, the prevalent definition that I was aware of was “testing
the
behaviour of two non-trivial components together.”
More recently, the definition that makes most sense to me comes from
Growing
Object Oriented Software [1]. I don’t have the book in front of me, but
from
memory it is something like “testing your code with other code that you
don’t have any control over.” Because we need a database for all levels
of
Rails testing, this suggests that all Rails testing is Integration
Testing.
In Rails’ terminology, however, “integration testing” means very
specifically testing the full stack minus the browser.
I’d normally do this with something like Selenium in .Net.
My question is, when creating a controller (or other class) that relies
on other library classes is it best to just use RSpec rather than
Cucumber to mock out the other dependencies and then bring in Cucumber
scenarios later when you know your RSpec tests are passing?
“is it best?” is always relative. YMMV. That said, the outside-in
process of
BDD using Cucumber and RSpec together works well like this (borrowed and
modified from the 2nd post in
http://groups.google.com/group/cukes/browse_thread/thread/2598d6fcd29bfd86):
- Identify business need (the very outside)
- Discuss what feature would solve this need (feature injection)
- Write a Cucumber scenario that interacts with the system boundaries
(that
have yet to be written)
- Run the scenario and watch it fail because the code doesn’t exist yet
- Write a little piece of the system boundary code that was missing and
caused the test to fail
- Run the scenario and watch it fail again, this time because the
code doesn’t do what it needs to yet
- Write a code example in RSpec
- Run the code example and watch it fail
- Write enough code to make it pass
- Run the scenario and check its status
- Repeat 7-10 until you have enough code (and not more than just
enough)
to make the scenario pass.
One catch-phrase that comes to mind is “use Cucumber to learn what code
to
write, use RSpec to write the right code.”
You should know that there is a trend these days among
Cucumber/RSpec/Rails
users to not write controller specs on the basis that controllers are
covered by the Cucumber scenarios. The benefit is a faster suite that
appears to have less duplication between testing layers. The drawback is
that you lose the benefit of discovering model interfaces when you’re
specifying the controllers in isolation.
My view is that this makes sense for the boilerplate stuff, but
customizations of the controller are well served with isolated specs in
RSpec.
More answer than you bargained for, I imagine.
HTH,
David
[1]
http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627