Post by byrnejb Post by Matt Wynne Post by byrnejb
It does not help that the libraries of steps_definitions distributed
with Cucumber-Rails, Webrat and so forth encourage both step nesting
( reuse ) and imperative feature statements ( When /^I fill in "(.*)"
with "(.*)"$/ do |arg1,arg2| ). These libraries are the first
introduction to step_definitions for most adopters. their appearance
and usage inevitably sets the expectation as to what is 'right'. While
their provision is well intentioned I have come to believe that their
example starts many people down the wrong path with respect to both
step definitions and feature statements.
What are we going to do about it?
Well, I have given this matter some thought in the past and I do not
have a good answer to that question. There may not be one. Cucumber,
by its very nature and design, expresses the tensions between design
and implementation. The two are widely separated spaces,
distinguished not only in purpose but also in concept and language.
In my ever evolving article on the Cucumber wiki ( Cucumber
Backgrounder ) I explore this tension to the best of my current
knowledge but I cannot resolve the different goals that each sets.
I have had a long and difficult road to BDD ( not that I have finished
the journey ), coming as I do from a professional background in heavy
and mid-range iron using mainly 4GLs, central data dictionaries, and
CODASYL databases. The concepts of OOP, TDD and BDD always seemed to
elude me regardless how much effort I expended trying to grasp their
essentials. I came to Ruby after spending four futile years with Java
watching the libraries grow exponentially in that time. I tried
TestUnit, then RSPec, RSpec Stories. Because of that last effort I
happened to be present on the RSpec mailing list when Cucumber was
first broached as an idea.
You can easily follow the evolution of my knowledge thereafter through
the archives of this very mailing list and that of RSpec. It is not
too much to say that for me Cucumber alone provided the entry point
into gradual comprehension of OOP and BDD. The essential
simplification which Cucumber provided was that it did not try to
reconcile the tensions between design and implementation. It simply
accepted them and provided a formal bridge from one to the other but
teated them as entirely distinct. The material implementation of that
distinction was the critical intellectual insight that Cucumber
provided which I had found in no other place.
For me the great revelation came when I finally understood that
features faced outward and simply said what should be done without any
reference to how success could be measured. Steps faced inward and
simply determined that what was requested in fact was done. In
consequence the former should look, in my opinion, as much like plain
written language as possible. The latter however, are the province of
the implementors and can look like anything at all because the people
concerned with design should never see them. Thus I have no strong
opinions on whether steps within steps are good or bad, so long as
things that pass values stay entirely in the step_definition files.
My observation is that difficulties with Cucumber and programming with
steps in feature statements often comes from those people who
perpetually straddle both sides of design and implementation. I
suspect that most users of this tool work in very small teams, or
individually like myself. They may have some competence as a domain
expert but often do not. They work mostly for resource constrained
clients whose knowledge of their own business is often astonishingly
shallow ( a case all to common with clients that are not so
constrained ). Because of the blurring of design and implementation
that this circumstance engenders the resulting conflations and
confusions are carried over into the use, or misuse, of feature files
as something akin to a script processor.
We are all always looking for the silver bullet. In the hands of a
truly competent person Cucumber can perform amazing feats of design.
To such a person Cucumber is akin to the silver bullet and naturally
they speak of it as such. Those that learn of Cucumber from these
testimonials naturally desire that they will obtain the same results
with no additional effort on their part. Therein lies the seeds of
disappointment. Like many powerful tools, in the hands of the inexpert
Cucumber can do great harm as well. I am not sure that it is
possible, or desirable, to constrain or expand Cucumber in vain
attempts to protect or indulge the ignorant. There is no substitute
Cucumber itself comes with no predefined steps. These are invariantly
provided by other projects a a means to incorporate their particular
tool into a Cucumber framework. I cannot see how our position on the
matter will have the slightest influence on those other projects that
In short, the root of most of this difficulty is simple want of
copious, lucid, example filled, indexed and cross-referenced
documentation for our tools, be they Cucumber, Capybara, Webrat or
whatever. The writers of such tools are so intimately familiar with
their function that the absence or lamentable quality of their
documentation excites no notice. The users of such products do not
wish to spend more time discovering the intracity of a tool's poorly
documented API then writing productive code. Predefined steps are a
poor substituted for well organized complete documentation but often
that is all one gets to work with and so, that is exactly what we do.
Thankyou for this most insightful post.
I don't think the step definition libraries can be replaced. I think their
role and affect is very similar to that of generators in Rails. They provide
very quickly. However as you become more and more experienced with the tool
you realise that they are actually counter-productive. However if they were
removed the tool would become unusable to new users. In the same way that
Rails would be unusable without generators for new users. The initial
learning curve would be so much steeper, that many would not get past it.
people to stop using them. Personally I'm beginning to see them as a smell.
If they're in my feature, then my feature smells and needs refactoring. So
in a way their presence in Cuke is still useful.