I’ve found Cucumber to be a pretty nice way of doing high level acceptance/integration testing. It’s also the first time I’ve ever thought that ATDD (acceptance test driven development) is actually achievable. The idea is that you write your “stories” in plain english, preferrably with your client/customer/product owner using the given/when/then style of syntax. Once written, these stories can be run through the Cucumber framework where it is parsed and coupled with custom ruby code (some of which you have to write) to essentially give you executable specifications. Of all the attempts I’ve seen out there to achieve ATDD and executable specifications, Cucumber really seems to have it nailed the best so far. Writing the stories does take some getting used to as you do somewhat have to learn to speak the “language” of Cucumber. But after writing your first couple “features”, as Cucumber calls them, you pretty much get the hang of it.
Here is an example of what a Cucumber feature looks like.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
The first section under the feature name is simply text to describe the feature in a typical As a/I want to/So that format. That text is for display purposes only and is not used during execution.
Next comes the scenarios which are executed when run through Cucumber. The first scenario simply verifies that when a link named “New” is clicked from the main users page, that it takes you to the “New User” page. This is a pretty simple one, but it’s nice to have some of these as kind of smoke tests.
The second one is interesting in that it acts as an outline to keep your cucumber features DRY. If there is one thing you’ll notice about the Ruby/Rails community and the tools/frameworks used is that there is an extreme emphasis on keeping things DRY, which I love. What this outline does is use tokens in the actual scenario steps, then specify a simple table representation that is used to plug in each “example” value when the scenario is run. So this scenario outline actually gets run 4 different times, once with each value for listed. The closest parallel I can think of in .NET land is RowTests with MBUnit, but I’m sure there are others such as Fitness, which I haven’t used too much.
I’ve used Cucumber to drive out almost every feature so far in this Rails app I’m building. And I can definitely say it’s been worth it. Especially when I go to update my gems to a new version or even try out the edge version straight from the Git repo. I’ve been able to lean on my Cucumber features to give me a nice sense at a high level as to the health of my application from the user’s point of view.
Great, so how does all this work?
No, really, how DOES this work?!?
Ok, so the “magic” of Cucumber is all in the step definitions, which are defined using Ruby. There is also some supporting Ruby code that you get out of the box with Cucumber that can help get you started. For example, it creates a file named “paths.rb” for you which is where you tell Cucumber where to navigate given a set of text. So when Cucumber encounters a line like this in your plain text scenario, “And I am on the users page”, it automatically knows the phrase “I am on” and signals to Cucumber that you’re wanting to navigate somewhere. Then it looks at the text after that, which is “the users page” in this case. This is where you need to give Cucumber a little help.
Here is an example of how to help a cuke out.
1 2 3 4 5 6 7 8 9 10
Since the Cucumber feature files are plain text and you are encouraged to use whatever language feels natural to you and your customer, you’re going to inevitably write something that Cucumber just doesn’t know how to do out of the box. This is where custom step definitions come into play. But don’t worry, they’re not as scary as they may look.
From the scenario above, Cucumber has no idea how to interpret “Given I am logged in as an admin” without a little help. Below you can see that I’m specifiying a regular expression for the text that Cucumber needs help with and then simply using Capybara to visit a page, fill in a couple fields and click a button to perform the login using the actual login page. Don’t let the regular expressions stuff scare you off. The awesome thing about running your Cucumber features is that when it comes across something it doesn’t understand it gives you the exact snippet of Ruby code that you can literally copy/paste from the terminal into a custom step file like the one show below. Since I’m still not a regular expression guru, I LOVE that Cucumber helps me with that!
1 2 3 4 5 6 7
Cucumber integration with Capybara (or Webrat) comes with a nice set of web related steps that cover a lot of the common cases. But at some point you’ll definitely want to define your own web related steps. I just created a file named “customwebsteps.rb” to place them in. This is a simple web step I defined to allow me to assert that an error is shown on the page containing the text I supply, which comes from my plain text scenario. Notice that you can chain together other web steps within each other like I’m doing below. My custom web step below is simply leveraging one of the built in Capybara web steps to do what it needs.
1 2 3
Clear as mud?
Well hopefully that gives you a little insight into how to get going with using Cucumber to drive top-down development using acceptance testing. At least, this has been my experience with it so far. I’d be very interested to hear your feedback and some of the ways you’ve been successful with acceptance testing using Cucumber or any other framework for that matter.