maxheapsize.com test it. code it. ship it.

Cucumber-jvm for Java

Posted on in Java, Test | Comments

In an earlier article I compared cucumber (with Cuke4Duke) and Concordion. It was very cumbersome due to the ruby/jruby jvm chain. Behold - the new cucumber-jvm was released. So how did it improve ?

Cucumber-jvm has support for many languages, e.g. Scala, Groovy, Closure and of course Java. I will focus on Java and Maven.

To get you maven project going you just need to include the following dependencies:

[Dependencies] (pom.xml) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<dependencies>
    <dependency>
      <groupId>info.cukes</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>1.0.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>info.cukes</groupId>
          <artifactId>cucumber-junit</artifactId>
           <version>1.0.2</version>
       <scope>test</scope>
    </dependency>
    <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
       <version>4.10</version>
      <scope>test</scope>
    </dependency>
</dependencies>

First thing you (or your Business Analyst or something) is doing, is describing your feature. It would look something like:

Feature: Hello Car

Scenario: Car can drive
    Given I have a car
    When I add 4 wheels
    Then It can drive

You need to put that into a file called Car.feature. The .feature extension is important.

To get all Cucumber-jvm tests off the ground we need one test runner. I often see it being called RunCukesTest.

[Test Runner] (RunCukesTest.java) download
1
2
3
4
5
6
7
8
9
package com.maxheapsize.cucumberdemo;

import cucumber.junit.Cucumber;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@Cucumber.Options(format = {"pretty", "html:target/cucumber"})
public class RunCukesTest {
}

You note the Cucumber.Options annotation. It will also produce a nice html in the given directory.

Writing the test now itself is no different than with Cuke4Duke.

[The test class] (CarTest.java) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.maxheapsize.cucumberdemo;

import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;
import org.junit.Assert;

public class CarTest {

  private Car car;

  @Given("I have a car")
  public void I_have_a_car() {
    car = new Car();
  }

  @When("^I add (\\d+) wheels")
  public void I_add_wheels(int wheels) {
     car.setWheels(wheels);
  }

  @Then("^It can drive$")
  public void iShouldBeAbleToDriveTheCar() {
    Assert.assertTrue(car.canDrive());
  }
}

You need to match the .feature description with @Given, @When, @Then Annotation (regexp that is). Each usage of any of the annotations is called a step definition. Each one must be unique among all .feature files (as far as I can tell). The code will be executed accordingly.

A maven test will get you:

Maven Cucumber-jvm test output

Make sure you put your .feature file in the right location. It needs right next to tests. I tend to put it into the resources folder in maven so it does not ‘pollute’ my Java source files.

Cucumber-jvm Test source tree

Finally your Html report is rendered (somewhat nicely and collapsable).

Cucumber-jvm test output

And yes, this applies to cucumber-jvm version 1.0.2.

I hope you found that useful as very short intro into cucumber-jvm. If you are wondering if you would want to use concordion check out my older blog post.

If I would have a choice again.I would choose cucumber-jvm for using a BDD tool. The plain text format makes it easy to read for a non programmer and it produces somewhat good documentation (if used well of course ;-) ). The tool chain is much smoother now and faster as well.

What I found missing is support for my favorite unit test tool TestNG. I also don’t know yet how to execute a single feature/scenario when having multiple ones (which will be almost certain always the case).

The learn more about cucumber checkout their website.

The code used above is available on GitHub

Comments