BDD Simplified with SpringBoot


This article demonstrates how to setup and write BDD/Cucumber style tests with Gradle based SpringBoot Service

Well, I don’t think BDD and Cucumber requires another introduction so I’ll directly jump to the point. Today, I’m going to show how easy is to setup BDD / Gherkin style Integration or End-to-End micro-service API’s test or even mix it up with JUnit tests.

Tech Stack:

  • Gradle 4+
  • SpringBoot 2+
  • Cucumber with Serenity* 1.9+

*Serenity generates fancy cucumber tests report; great to be integrated with CI/CD builds.

If you are using IntelliJ IDE and don’t already installed/activated following plugins then its time now to do so. This is going to be the best 2 mins investment.

IntelliJ IDE Plugins

Behavioral Driven Development (BDD) testing style requires first writing scenarios under test in a simple Gherkin (english like) language with Given, When, And & Then keywords which should be written in a way to easily understandable by not just engineers but also by all stakeholders. Final aggregated report by Serenity is a great way to visualize scenarios covered by automated BDD tests.


Step-1) Write a BDD style test

First create a feature file (demo.feature) as shown below and write a Gherkin style scenario.

BDD Scenario — Feature file

Every statement (called as ‘Step’) in scenario starts with a keyword (like Given, And, When, Then) serves a special meaning and eventually invokes a method from a Step Definition class (shown below: DemoFeatureTestSteps.java)

This is just a very basic example to depict how a standard scenario looks like and what kind of steps it should cover. From any Step we can also pass arguments to methods in form of a String, Int or even Array or iterate over same step(s) with different data for each row of input taken from tabular data input.


Step-2) Create step definitions to do the actual work

Note that step definition class (shown below) uses @Autowired services! So how’s that magic possible?

Did you notice this class extends an abstract base class (BaseIntegrationTest) ?

Step Definitions Class

Step-3) Load spring context for integration test

All the magic here is in the annotation @SpringBootTest which loads spring context from main class (i.e. BddDemoApplication) and uses separate @Configuration TestConfig (optional) and makes all @Service’s available as auto-wire candidates.

This way we can start end to end tests or integration tests with an added flavor of BDD. But this is not the actual start point of a BDD/Cucumber test. A Cucumber test requires CucumberRunner while it just loads the spring context with SpringRunner (~take a closer look at the annotations again).

Base class to bootstrap spring context

Step-4) Create feature runner (start point)

So let’s create a FeatureRunner class which @RunWith CucumberWithSerenity and provides facility to putting all things together.

Notice here important annotation @CucumberOptions (although those can be specified or overturned with command line, maven or gradle). Here, its specified that this DemoFeatureRunner with execute all the scenarios under demo.feature file.

We can specify more options here like: tag or glue; Option tag can be used to have more ways and control over scenarios to execute, while glue can be used if Step Definition classes are not following the convention of sharing the same parent package with Runner class (i.e. located in some other location / package and can not be self identifiable).

Starting Point: Cucumber Runner class

To execute the test simply click on the double right arrow icon adjacent to Runner class and it shows options to start the test in Run/Debug modes.

Run options (Edit Configurations… for more options)

Step-5) Gradle build setup (with optional different source-sets useful for CI/CD)

Check below the structure of the Demo Sample application follows. Note that under src dir, it has three source sets (although any combinations and naming can be adopted but build system should knows about those source sets inclusion or exclusion):

  • src/bdd-test -> for integration or Bdd style e2e tests and resources
  • src/main -> for main application classes and resources
  • src/test -> for normal JUnit test and resources
App package structure

Finally, to build this application and to run BDD test (alongwith normal JUnit test) we have to tell gradle about it’s presence:

Gradle build file: BDD Test source-set inclusion
Step-6) Check serenity report

Notice the final line where gradle task ‘aggregate’ is executed which comes from Serenity cucumber gradle plugin:

apply plugin: 'net.serenity-bdd.aggregator'

This task creates a final execution report under default directory:

{APP_ROOT}\target\serenity\index.html

And here is the output report for this basic sample application with just one feature and one scenario looks like below:

Serenity report

In case of any scenario step end up with some erroneous situation, then this report allows to drill down to the failing scenario’s failed step and points to exact error and stack trace as well.


Hope you enjoyed this quick and laconic article about Cucumber integration with SpringBoot and Gradle.
Full source code is available on github at: https://github.com/connect2manu/springboot-bdd-integration

Please drop a note about your feedback below or in case of any questions. Thank you for reading the full article. Hope that helps!