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:

case page_name
# ...
when /the users page for #{capture_model}/
  account = model($1)
  users_path(:subdomain => account.subdomain)
# ...

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):

/((?:(?:)|(?:(?:a|an|another|the|that) )?(?:(?:(?:(?:first|last|(?:\d+(?:st|nd|rd|th))) )?(?:account|user))|(?:(?:account|user)(?::? \"(?:[^\\"]|\.)*\")))))/

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.