BDD testing is becoming popular for good reason now. There are a number of popular BDD frameworks are available in market. I choose cucumber for my BDD testing and JaCoCo for code coverage. This post explain how you can integrate Cucumber with Spring boot and use JaCoCo for code coverage.
Complete code for this post is available here
If you are familiar with Spring boot, Cucumber and JaCoCo then you may skip the intro.
What is Spring Boot:
Spring boot is one the best framework currently available for developing REST Api using Java. Spring boot takes away a lot of boiler plate codes that developer used to do in traditional approach with spring.
Spring Boot comes with handy tools (like JPA integration, Logging framwork, Social Media integration etc) and integration to make life simpler. Read more about it here.
What is Cucumber:
Cucumber is framework for BDD (Behaviour driven development) Testing. It usage Gherkin for DSL (Domain Specific language) for writing test cases. These test cases are written in plain english which makes it easy for non-programmers to write test cases or business expectations. Later on these test cases are mapped to java program which checks the results against expectation. You may read more about Cucumber here
What is JaCoCo:
JaCoCo is code coverage tool for reporting how much of your code has been tested. It has a very good integration with maven. You may find more about it here
According to BDD or behaviour driven development you first write behaviour for which we use a framework which understand DSL (Domain specific Language) Cucumber uses Gherkin for this.
We write set of feature files.
Each feature file contains multiple scenario which represents one test.
Each scenario contains multiple steps. These steps are mapped to a java function which implements these tests
Setting up Cucumber with Spring boot
As mentioned we are using Spring boot to write our API. I have used Spring boot initializer to generate my project. I have implemented a basic book library. All books are stored in a List which stays in memory. So i don’t need any database or other fancy stuffs. so i only used web and dev-tool as my dependencies.
Dependencies for Cucumber:
For advance report generation we use below mentioned plugins
Please note this is not necessary but i recommend to use this.
So far we are done with setting up cucumber with Spring boot. Let’s begin with writing test cases.
Writing test cases with cucumber and spring boot comprise below mention components:
- Feature file: Contains our feature and scenario in plane english which is understandable by business people or non-technical persons.
You may have as many feature files as you want but as standard goes, please use one feature file for one module or resource of your application. eg: in our library API book is one and only module. Hence below is our only feature file
Here number 10 (notice, numbers are in quotes) will be passed to corresponding java function as parameter. Same with 200.
Lines starting with When, Given, Then etc are called steps. These steps will be mapped to a function. Classes in which those functions are defined are called Glue
Number will be passed as parameter if they are in quote and as string if they are inside double quotes
- Test Runner: Like JUnit we need a test runner here as well. We need just one runner. Below is our Test Runner
CucumberOptions provides many options to configure cucumber. We have used below
Feature: Used for mentioning location of your feature files
Glue: Used for mentioning java classes which contains function corresponding to each steps (explained later)
Format: Specification for generating reports
The only purpose of this class is to start tests, please do not write any code inside this as the result will be unexpected.
Next thing we need is something which will tell cucumber about the Spring boot application. Below is what i used
I will annotate each of my Glue classes which needs tests my REST application with @ConfigTest. This will Boot my spring boot application on port defined by SpringBootTest.WebEnvironment.DEFINED_PORT which is 8080 by default.
Next we will write our Glue or class which will actually run my tests. Below is my only Glue
This class will contain test corresponding to each feature mentioned in feature file. You may use one class for writing tests for all feature as well as u can write one class for each step.
This Glue is for API endpoint
/books?count=<number of books> which will return number of books mentioned by count parameter
Below is method for my step “Given Book Library is initialized”.
As i have used library completely in memory, so before testing my REST endpoint i must have an initialized book library.
Now, if you look at our feature file we are left with two more steps one for “When” and another for “Then”.
Here goes step “When ’10’ Books are requested”
Please note a regular expression in place of number 10. This regular expression matches every number, hence even if you change number in feature file from 10 to 100, You will not have to change your glue code. In-fact there’s a way to mention multiple inputs in feature file as well.
Here I created URL for requesting book by setting count to 10. hence my url will be /books?count=10 which should return (by definition) 10 book records. Which is exactly what are next step says “Then List of ’10’ books should be returned with status ‘200’”
Below is method for corresponding to this step
Assert used here belongs to JUnit.
This completes our test case for one endpoint. Now we can run our test using maven to see if it works.
mvn clean test to run the test.
In log you can see all the steps and a report will be generated in directory named “cucumber-reports” inside target.
If you have used cucumber plugin for advance report, use
mvn clean install command. a detailed report will be generated inside same directory.
If No test run by
mvn clean test then may be maven is unable to pick your test runner. In this case you have to mention your TestRunner class to maven. Change your maven-surefire plugin as mentioned below
Next Step will be configuring JaCoCo
JaCoCo is used for measuring code coverage. This is a good measure for know how well your code is tested. Around 80% code coverage is considered as good.
JaCoCo instruments compiled java classes for measuring codes that executed during Testing. It attaches hooks during several phases of maven build cycle and instruments classes accordingly.
In order to Setup JaCoCo you need to use below plugin (taken directly from JaCoCo documentation)
Now when you run
mvn clean install JaCoCo reports will be generated inside directory named “site” inside target.
This conclude this post. Hope everything is clear and understandable. Please drop comment if any discussion needed.