Want to know a little more about setting up Cucumber with Java? Try this

cucumerCucumber holds a lot of promise: what if I could actually get my product managers/owners to help me write a bunch of stories that both of us can understand and agree on. What if I can take those human-readable stories and just plug then into my automated unit tests?

Even better, what if I don’t have to rewrite my app in Ruby and I can do it with Java? As it turns out, the Cucumber folks back ported Cucumber to support Java, so maybe I can have it all.

There are already some pretty good quick start guides out there (such as Kerry’s here and c0deattack’s here). My goal in writing this is to propose a slightly more complex (and more realistic) version and raise some discussion points around it.

(By the way, if you want to skip all my verbosity, you can check my code on Github here: https://github.com/mrice/simple-cucumber-java)

Get ready to think about your JUnit tests differently

When I looked at the other examples, I was initially confused because Cucumber does things differently from how I usually think of JUnit tests. Hopefully a little introduction will keep you from getting confused too.

JUnit is straightforward for most Java developers: Create a test class. Decorate its methods with a @Test annotation. Let your IDE or Maven pass or fail each test as you go by calling JUnit’s various assert methods. There are complex topics around mocking and the distinction between unit and integration tests, but that’s basically it.

Cucumber will make you approach things differently. While you create a test class that JUnit can see (named with Test, like we used to do with JUnit), you’re not going to decorate any methods with your @Test annotation. Instead, you’re going to bind methods to the steps in your cucumber definition and ultimately run your assertions later in the process.

But the most confusing aspect, for me anyway, is the way that binding causes me to structure my tests differently. Instead of just running each test discretely, you have to manage the state of the test as it spans across each of the steps of the definition. For example, I wrote a trivial Gherkin-style definition to verify that when I pass a string into a method that I get the same string back (more on this later):

simple-gherkin

The confusion for me came when I realized there isn’t a simple @Test decoration that you can run for this sequence. Instead, the Cucumber JUnit technology is going to fire a method for each step. You need to track the first string from the “Given” step and later verify that’s the same string you get when it fires the “Then” step. It’s easy enough in this example, but you could be holding a lot of state you’ve add a lot of “ands” and “buts” to your sequence.

If this is the first time you’ve considered Cucumber with Java, you might be a little confused so please read on.

How to run Cucumber with Java

Let’s start with something to test

First, you’re going to need to create something you want to test (so as not to confuse you, I’ll do the code first, test second). For my demo, I’m going to follow what some of the other bloggers have done (see above) and create trivial business classes so we can focus on the tests.

Let’s write some test scenarios with Gherkin

Obviously, those classes would be easy to test with JUnit. But if we want to write some Cucumber/Gherkin BDD tests, we might write the following:

gherkin-full-example

Take a good look at the syntax, it’s pretty interesting. If you want to learn more about this Given-When-Then structure in the context of Java, you should read this.

Configure your Maven project

I probably should have told you earlier that this post relied on Maven, but shouldn’t you be doing that by default by now? 🙂 Include these dependencies (and update your version numbers if you’re reading this long after I wrote it):

Save your feature file to the right location

Write a file that you can name <anything>.feature with the contents I have above. This is the heart of the BDD approach, these human-readable files, but we need to put it somewhere were Cucumber can see it. Place the file in the src/test/resources folder (you can configure around this if you want). For now, match the same package folder structure of the tests you want to run. Here’s what my structure looks like (the echo.feature at the bottom is where I stored my Cucumber file):

cucumer-structure

Create a class to bootstrap JUnit

I think this aspect of Cucumber for Java has room for improvement, but for now I also think you have to do it this way. Create a class with whatever name you want to call it (I chose CucumberRunnerTest), but make sure your class ends with the name Test.

There are quite a few options that you can set with a @CucumberOptions annotation, but you can read those all over the web.

Now, write your definition classes

Notice that the JUnit test class doesn’t have any test cases. So now, we’re finally going to run some tests. I’ll just start by showing you one:

Take a little time to study it. There’s a lot written about how to make this work, so I won’t cover it in depth. There are, however, a few things I want you to notice:

  • Notice the @Given, @When, and @Then decorations. These are how you map the Gherkin BDD scenario file to the actual test cases (and you thought Cucumber was smart enough to parse that file).
  • Notice that the strings match the text almost exactly. I’m kind of surprised by this because it seems brittle. Maybe there’s a better way to do it…?
  • Notice the little regex statements in the strings and how the number of regex match the number of arguments in the functions.
  • Notice the un-Java-like-non-camel case convention. This seems to be the way the other Cucumber examples are, but I’m sure you don’t have to do this.
  • Most importantly: notice how we have to spread the state of the test over the whole test class. I think this is interesting because it drives a certain kind of design on your tests: in my mind, I’d like to have each class assigned to a scenario to make it clean; but I’m worried it might get a little messy.

Run your tests!

That should be it. I have two different classes, one for the string matching code and one for the int matching code. You should see something like this:

test

One thought on “Want to know a little more about setting up Cucumber with Java? Try this”

Leave a Reply

Your email address will not be published. Required fields are marked *