Pondering Pickled Patterns

Mar 7, 2010

cucumber

For me Pickle is what made
Cucumber make sense to me for integration testing.
I had a hard time coping with the idea of spending so much time going
between nearly English features and huge swaths of regular expressions.
Pickle cuts down on a lot of the regular expression drudgery by defining
some generic steps for working with models. If you haven’t tried Pickle
out yet, I highly recommend it. Railscast
186 gives a
great overview.

In addition to the generic step definitions Pickle provides, it also
gives you access to the powerful regular expressions that drive those
steps. I just spent some time hung up on one of those regexps,
capture_model.

In the feature I was creating a labeled account and then visiting the
users page for that account:

Given an account: "spectre" exists
When I go to the users page for the account: "spectre"

Then I was using capture_model in a pattern in
features/support/paths.rb like so:

Unfortunately, every time I ran the feature, #model would
return nil. After banging my head into this for a while I
finally determined that #capture_model was capturing an
empty pattern, so I was passing "" to #model.

I printed out the the regexp returned by #capture_model
to see what was going on (brace yourself):

The regular expression is built up programmatically at runtime based on
the models which currently exist in your application. (As you can see
above, in the application I was working on I only had Account and User
models defined). The regexp is long and looks a little like Lisp code
that’s been tweaking, but if you look closely you’ll probably come to
realize (faster than I did) that it will happily match an empty string.
In fact, in the pattern I was using in paths.rb#capture_model was matching an empty string and the rest
of the line was being thrown away. Unfortunately that part – the
account: "spectre" – was the most important part…

Realizing where I was going wrong I anchored my pattern to the end of
the line:

when/the users page for #{capture_model}$/

Woo! Now the line only matches when everything between “the users page
for “ and the end of the line can be matched by
#capture_model. With this addition, the regexp captured
the model label account: "spectre" and #model
finally returned the record. Allons-y!

The moral of the story: anchor your patterns whenever possible. It’s
generally good practice if only to make sure you acting on the correct
data.