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.
- 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.
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.
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-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).
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).
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.
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
Finally, to build this application and to run BDD test (alongwith normal JUnit test) we have to tell gradle about it’s presence:
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:
And here is the output report for this basic sample application with just one feature and one scenario looks like below:
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!