[rspec-users] Step matchers

Pat Maddox pergesu at gmail.com
Sun Oct 14 20:09:22 EDT 2007

On 10/14/07, David Chelimsky <dchelimsky at gmail.com> wrote:
> On 10/14/07, David Chelimsky <dchelimsky at gmail.com> wrote:
> > On 10/14/07, Pat Maddox <pergesu at gmail.com> wrote:
> > > I think we all know that the readability of steps isn't great right
> > > now, and in fact there's a very recent thread that discusses just
> > > that.  It was that recent thread that prompted me to explore this a
> > > bit.
> > >
> > > The basic idea is that you define step matchers, which have a regex,
> > > and then you match step names against that regex.  Kind of tough for
> > > me to explain so I'll just link to some code :)
> > >
> > > spec: http://pastie.caboo.se/107116
> > > impl: http://pastie.caboo.se/107117
> > >
> > > Instead of writing
> > > Given "a user named __ who is __ years old", "Pat Maddox", 22
> > >
> > > it allows you to write
> > > Given "a user named Pat Maddox who is 22 years old"
> > >
> > > I wrote it out as a separate matcher because it was just easiest to do
> > > it that way while I explored this approach, no messing around with
> > > RSpec internals to get it to really work.  However if we went this
> > > route the structure would certainly be different.
> > >
> > > Hopefully you can get the idea from the example code.  Ideally what I
> > > would like is to write step libraries that are external to the stories
> > > themselves.  The stories would be much clearer because the
> > > implementation would not be embedded, and the step names themselves
> > > would make a lot more sense.
> > >
> > > wdyt?
> >
> > LOL - I just suggested something like this in the other thread you
> > cite. Though your idea strikes me as far more flexible and usable.
> > Well done!!!!
> This just occurs to me. If we do away with the need for special
> characters/positioning, blocks, etc, we should be able to do just
> this, no?
> Given a savings account with 100 dollars
> When the account owner asks for 101 dollars
> Then the account owner should receive 0 dollars
> Then the account should have 100 dollars
> Look mom - no quotes!

How would you plan to implement this?  Read in a text file, strip the
leading Given/When/Then and match each line?

The one catch I see is that because stories are structured, you still
need something to demarcate steps within a scenario and scenarios
within a story.

In general, I prefer your syntax, making it look like a plain-text
spec instead of Ruby code.  I question whether it's a big enough win
to justify writing a parser instead of simply writing valid Ruby.  At
this point, personally I'd say no, but I can see how it would be nice
for customers and spec readers/maintainers.

Actually, would you mind showing an example of a full spec with this
syntax?  Maybe something like:

Story: Creating a post
  As a user
  I want post to my blog
  So that I can share information with my fellow Rubyists

  Scenario: anonymous user
    Given no blog posts in the system

    When I POST to /posts with title=Post Title, body=Post body

    Then the page should show Post title
    And the page should show Post body
    And the page should show Posted by: 'anonymous'

  Scenario: logged in user
    Given no blog posts in the system
    And a user named Pat
    And logged in as Pat

    When I POST to /posts with title=Custom Title, body=Custom body
    And the page should show Custom Title
    And the page should show Custom body
    And the page should show Posted by: 'Pat'

Actually a parser for this would be quite simple, and I definitely
prefer it to the Ruby version.  It makes sense to use the interpreter
when you're defining step implementations inline, but if you're not
then it doesn't really add any value and looks/feels weird.

One other thing I thought of is that we can combine spec matchers with
your ? syntax idea.  Basically, regexps don't really get you anything
in this type of situation, since you're going to be matching the whole
string, and regexp doesn't convert data types for you.  You could
define a step like

Step "I like to eat, eat, eat ? and ?" do |food1, food2|
  @fav_foods ||= [food1, food2]

and then when it gets used in the spec, it's simply
Given I like to eat, eat, eat apples and bananas

Under the hood, the ? get converted to (.*), which again works fine
since you're matching the entire string exactly anyway.  It's a lot
more readable than full-blown regexps.


More information about the rspec-users mailing list