What’s so good about Cucumber?
In an Agile process we describe the system requirements by defining a series of features. A feature has a description that provides the context. It is usually written in the form of a User Story:
As a [system role]
In order to [desired benefit/business objective]
I want to [required feature]
A feature contains one or many scenarios that describe its behaviors — that is where Cucumber comes in in the process.
Cucumber is a Behavior Driven Development (BDD) testing framework that offers a way to write tests that anybody can understand — regardless of their technical knowledge.
It makes it possible for developers to work with non-technical stakeholders when defining a systems features and makes the workflow of delivering them less technical and therefore more accessible to the entire project team.
The pattern of a Cucumber test is simple yet powerful:
1. put the system (product/service) into a particular state
2. execute the test steps
3. evaluate the state of the product.
From a technical perspective we make use of a language called Gherkin that lets us describe a software’s behavior without detailing how that behavior is implemented.
With Gherkin we can write scenarios that describe a users’ interaction with our system using a small set of keywords. The most common keywords are “Given”, “When” and “Then” — they are used for different purposes.
Consider a news service application. Let’s assume that we want to describe a requirement that states that if there are some articles, these should be displayed on a specific page (url). We could write a scenario like this:
The good thing with Gherkin is that scenarios can be written by non-coders. That means that we can involve all stakeholders in the process of creating them and make sure that they truly reflect the requirements and are understood by the development team. Also, apart from being part of the testing suite, the scenarios can also serve as documentation.
Once the scenario is defined it is the developers responsibility to make it executable. They set up a number of parsers that match the steps (reffered to as step definitions) and execute code based on them. Note that this part of the test is not interesting for the non-technical stakeholders.
Just to illustrate how the steps above can look like once actual code has been added to them.
At this point the developer starts to work his way through a series of errors that the tests will generate for him and implement a solution that makes the test pass.
In the example above, I would assume that the flow would look something like this:
- There is no route
/articles— define a route
- There is no controller and action to handle the request made to the url — create one
- There is no
Articlemodel — create a model using unit specs
Articlemodel has no
titleattribute — add an attribute to the Article model
- There is no template to render — create a view template
- There is no output of data passed to the template from the controller action — add code that displays the data in html on the template
At this point I would assume the test would go green and I would move on to the next scenario.
What’s the benefit?
In my opinion, this approach helps teams to stay focused on the user and hers/his experience of the system. It also helps teams to better understand all the bits and pieces of the product. Writing the scenarios becomes more and more complex as the system grows of course — but in doing so your domain knowledge increases and all parts of the system (at least the parts that involves the users) are known throughout the entire team — not only by the tech people.
Setting up Cucumber in Rails is dead simple — the process is for most parts automated with cucumber-rails. Even if you use other Rack based frameworks the setup and configuration is not complicated. Also, Cucumber comes for other languages as well — check out Cucumber-JVM and Cucumber-JS if you are interested in using this approach in your project.
Personally, I use Cucumber extensively in my workflow — both when working with my clients and when I write implementation. It has proven over and over again to add value and lead to a better user experience in the projects I’ve been building.