Thomas Sundberg

September 28, 2012

Test drive an implementation using an Executable Specification – revisited

This post has been migrated to

An example is perhaps the best way to describe something. Concrete examples are easier to understand than abstract descriptions.

I will show how Cucumber-JVM can be used to specify an example and how the example can be connected to the system under test, SUT. The example can then be executed using any IDE or using Maven.

The example

The example I will use is about car maintenance. A car with an empty fuel tank need to be refueled. We will develop some code that will solve this problem. What we actually will implement is a simple adding function, but that is beside the point.

File structure

Before you start building the example, I need to show the file structure this example lives in. This is almost big design upfront, but hopefully you can bear with me while I do that.

|-- acceptance
|   |-- pom.xml
|   `-- src
|       `-- test
|           |-- java
|           |   `-- se
|           |       `-- waymark
|           |           `-- example
|           |               |--
|           |               `-- steps
|           |                   `--
|           `-- resources
|               `-- se
|                   `-- waymark
|                       `-- example
|                           `-- CarMaintenance.feature
|-- pom.xml
`-- product
    |-- pom.xml
    `-- src
        `-- main
            `-- java
                `-- se
                    `-- waymark
                        `-- example

Given this file structure, you should be able to re-create this example.

The feature

Lets start with a feature. This is possibly the starting point for a very large project.


Feature: Daily car maintenance Cars need maintenance Scenario: Fuelling Given a car with 10 litres of fuel in the tank When you fill it with 50 litres of fuel Then the tank contains 60 litres

This feature is divided into two parts.

It starts with a headline and a description. This is background information. It tells us why we should bother creating this feature.

The introduction is followed by a scenario. A feature is made out of many scenarios. In this example there is just one scenario.

The scenario is then divided into three parts.

  • The ‘Given’ part describes how the system should be prepared before the testing. This is the setup for the system.
  • The ‘When’ part describes how the system should be used. This is the execution part of the example.
  • The ‘Then’ part is where you verify that the system is in the expected state. This is the assert part of the test.

Glue code

The feature above is not possible to run on its own. It need som glue to connect with the system that should be tested. The glue is divided in two parts. First there is a JUnit class that will connect the feature to a runner. It may look like this:


package se.waymark.example; import cucumber.junit.Cucumber; import org.junit.runner.RunWith; @RunWith(Cucumber.class) public class RunCukesTest { }

The test class is annotated with an annotation that defines that this class should be executed with a JUnit runner called ‘Cucumber.class’.


This annotation will enable us to execute this feature both in a IDE and with any build tool. With this in place, you can debug a single feature as well as enjoy continuous integration using tools like Maven. The JUnit runner will search for features in the classpath so it is important that they are located in the same package as the test class or in a subpackage to the test class.

Then there are the step definitions that actually connects the feature to the system under test. It may look like this:


package se.waymark.example.steps; import cucumber.annotation.en.Given; import cucumber.annotation.en.Then; import cucumber.annotation.en.When; import se.waymark.example.Car; import static; import static org.junit.Assert.assertThat; public class FuelCarSteps { private Car car; @Given("^a car with (\\d*) litres of fuel in the tank$") public void createCar(int initialFuelLevel) { car = new Car(initialFuelLevel); } @When("^you fill it with (\\d*) litres of fuel$") public void addFuel(int addedFuel) { car.addFuel(addedFuel); } @Then("^the tank contains (\\d*) litres$") public void checkBalance(int expectedFuelLevel) { int actualFuelLevel = car.getFuelLevel(); assertThat(actualFuelLevel, is(expectedFuelLevel)); } }

It consists of three methods. One method for each step

  • Setup the system under test
  • Execute the implementation
  • Validate the result

Every step definition is annotated with a regular expression. If the regular expression contains capture groups, a pair of parenthesis, the matches from these groups will be passed to the step definition method. The captured string will automatically be converted to the declared parameter type.

The step definitions and the test class must be separated. It means that there will be an empty test class. This is the desired behaviour of Cucumber.

Production code

With a feature and step definitions in place, it is time to develop the production code. This is the simplest solution that could work. It may even be seen as so small that it will not suffice. But it is sufficient for this starting point of our world domination product.


package se.waymark.example; public class Car { private Integer fuelLevel; public Car(int initialFuelLevel) { fuelLevel = initialFuelLevel; } public void addFuel(int addedFuel) { fuelLevel = fuelLevel + addedFuel; } public int getFuelLevel() { return fuelLevel; } }

Maven poms

The final glue needed to be able to execute this example are three Maven poms. I use Maven to avoid all problems with downloading dependencies. Maven also integrates very well with the editor of my choice, IntelliJ IDEA.

Lets start from the top of our file hierarchy, the root pom for the entire example.


<?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <groupId>se.waymark.cucumber</groupId> <artifactId>example</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>product</module> <module>acceptance</module> </modules> <properties> <>UTF-8</> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> </dependencies> </project>

It connects the two modules and defines that JUnit should be available in every module during the test phase.

The next pom we need is the pom for the production code example/product/pom.xml


<?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <parent> <groupId>se.waymark.cucumber</groupId> <artifactId>example</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>product</artifactId> </project>

It doesn’t do anything more than defines the module so it can be built.

The final pom that is needed is one that retrieves the cucumber dependencies and connects the production code to the acceptance tests.


<?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <parent> <groupId>se.waymark.cucumber</groupId> <artifactId>example</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>acceptance</artifactId> <dependencies> <dependency> <groupId>se.waymark.cucumber</groupId> <artifactId>product</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>info.cukes</groupId> <artifactId>cucumber-java</artifactId> <version>1.0.14</version> </dependency> <dependency> <groupId>info.cukes</groupId> <artifactId>cucumber-junit</artifactId> <version>1.0.14</version> </dependency> </dependencies> </project>


It is not very difficult to implement an executable specification. We need a feature, some scenarios, step definitions and some wiring to connect the different parts. The feature is written using Gherkin, the step definitions and production code is written in Java and finally the wiring is done using Maven.

So Executable Specification or Specifications by Example isn’t rocket science, it is definitely doable and is a a great complement to the unit tests that you should use when developing the product.


This post has been reviewed by some people who I wish to thank for their help

  • Malin Ekholm
  • Johan Karlsson
  • Aslak Hellesoy

Thank you very much for your feedback!


Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at

%d bloggers like this: