[rspec-users] Step matchers

Pat Maddox pergesu at gmail.com
Mon Oct 15 20:44:01 EDT 2007

On 10/15/07, Zach Dennis <zach.dennis at gmail.com> wrote:
> To me adding a story parser to parse a text file adds overhead to the
> rspec team and to developers and customers using it. In a way I fear
> that the textual freedom of a raw text file will lead to many gray
> area's both on the rspec's implementation of it and also for
> developers trying to explaining to their customers why or why they
> cannot do something. I don't know if this is greater then the
> conversation that already has to take place though. I personally don't
> know customer's who write the final draft of an acceptance test.

The parser will be trivial.  You're looking at 60 lines tops.

> Wincet Colaitua brings up a good point [3] in regards to StepMatchers:
>   "My main concern here is that you're now having to keep two files in
>   sync to have the stories work properly."

Perhaps there was some confusion with how I implemented that initial
StepMatcher.  I've since explained that ultimately it should contain
both the matching and mechanics.  Unless Wincent was referring to
keeping the plain-text stories in sync with the StepMatchers.  On the
surface that sounds valid, but at the same time if you've got

Given "a user named", "Wincent" do |name|
  @user = User.create :name => name

.... some other scenario

Given "a user named", "Pat"

You still have to keep stuff in sync.  It's easy here of course
because it's all in the same file...but then what happens when you
recognize you're using this "a user named" step in every single one of
your stories?  You extract it to another file, and then now you have
to make sure the story steps are in sync with the extracted steps.

> Wincent also brings up in the same post [3]
>  "The great thing about the Story Runner in its current form (and RSpec too)
>   is that you can start off by writing a skeleton using a natural-language-like
>   Ruby DSL, and then you flesh it out with code to fulfill its purpose"
> This is the part of Story Runner that I want to hold onto. In my
> opinion a worthwhile balance to start exploring is one that does the
> following things:
> * creates an easy one to one mapping between a description and a method
> * remove do/end blocks, they are not needed and are a negative for the customer
> * keeps story's clean and tidy, not full of unnecessary code artifacts
> An implementation of this is the test/unit StoryRunner project that
> I've been working on.
>   http://continuous.rubyforge.org/svn/trunk/test_unit_story_runner/
> It is similar to rspec's implementation but it does the three things
> listed above. A nicely color formatted example can be found at
> http://pastie.caboo.se/107537
> A few things to note about the example:
> * Story's do not use do/end blocks to organize scenarios. It is not
> needed. Scenario's belong to the last Story declaration preceding it.
> * Scenario's do use do/end blocks to nest their story parts.
> * Descriptions used for Given, Then, When and And translate to a
> method call. The rules are simple. Take the description, downcase it
> and strip out punctuation. Replace whitespace with underscores and try
> to find a method. If one exists, call it. If one doesn't exist strip
> the first word, and try again. Repeat until there are no words left.
> If no method was matched then raise an exception with the original
> description string.

See, I would much rather mentally map
Given a user named Wincent to
StepMatcher.new("a user named ?")
than to
def a_user_named___(name)

It seems to me that mapping to a method leaves you with the sync
issues but in a far less readable format.  Another thought is that if
you have a full-fledged object, you can do basic things like
decomposing methods.

> The idea behind this is that you create a clean way to write and
> maintain Story's. It minimizes the "cody" aspects while still allowing
> you to write executable ruby code.

The main point I'm trying to get across, and I believe Dave is (obv
jump in if I'm wrong), is that once we start making these sorts of
enhancements then there's no reason to make it Ruby executable code
anymore.  If we don't need do...end blocks, and we don't need
arguments, there's really nothing left and the Ruby interpreter is no
longer adding any value and should be refactored away.

> The helper methods which are implemented follow a simple convention
> for translating a  sentence description into a helper method and the
> implementation of the story's are implemented in well named helper
> methods (which i think adds to maintainability over StepMatchers).

How does auto-mapping to method names add to maintainability over
auto-mapping to strings?  I'm not seeing that, and I'd like to
understand your perspective.


More information about the rspec-users mailing list