Here I am sharing how you can integrate cucumber for behavior driven testing with spring boot integration test and how you collect the reports in Jenkins pipeline.
In a sample spring boot app generated from my custom spring boot archetype we will show a small integration test suite with cucumber and spring boot.
Steps to follow are :
1- Add cucumber maven dependencies to your spring boot pom.xml
<!-- Cucumber--> <dependency> <groupId>info.cukes</groupId> <artifactId>cucumber-java</artifactId> <version>${cucumber-version}</version> <scope>test</scope> </dependency> <dependency> <groupId>info.cukes</groupId> <artifactId>cucumber-junit</artifactId> <version>${cucumber-version}</version> <scope>test</scope> </dependency> <dependency> <groupId>info.cukes</groupId> <artifactId>cucumber-spring</artifactId> <version>${cucumber-version}</version> <scope>test</scope> </dependency>
2- Define cucumber features in your test resources :
3- How to define the features implementation to be executed with your spring boot app logic :
the feature description :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Feature: the health can be retrieved | |
Scenario: client makes call to GET /health | |
When the client calls /health | |
Then the client receives response status code of 200 |
the feature implementation :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* how the feature is executed | |
*/ | |
public class GetHealthStep extends CucumberRoot { | |
private ResponseEntity<String> response; // output | |
@When("^the client calls /health$") | |
public void the_client_issues_GET_health() throws Throwable { | |
response = template.getForEntity("/health", String.class); | |
} | |
@Then("^the client receives response status code of (\\d+)$") | |
public void the_client_receives_status_code_of(int statusCode) throws Throwable { | |
HttpStatus currentStatusCode = response.getStatusCode(); | |
assertThat("status code is incorrect : " + | |
response.getBody(), currentStatusCode.value(), is(statusCode)); | |
} | |
} |
4- How to execute the integration test :
you need to configure the root executor with Cucumber runner as the following:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* the main class for cucumber where you configure where the features are defined and which formats of reports needed to be generated | |
*/ | |
@RunWith(Cucumber.class) | |
@CucumberOptions(features = {"src/test/resources/features"}, format = {"pretty", "html:target/reports/cucumber/html", | |
"json:target/cucumber.json", "usage:target/usage.jsonx", "junit:target/junit.xml"}) | |
public class CucumberIntegrationIT { | |
} |
and the integration test triggering which will be done via spring boot integration test :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* main spring boot integration test with integration test profile | |
*/ | |
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) | |
@ActiveProfiles("INTEGRATION_TEST") | |
@ContextConfiguration | |
public class CucumberRoot { | |
@Autowired | |
protected TestRestTemplate template; | |
@Before | |
public void before() { | |
// demo to show how to add custom header Globally for the http request in spring test template , like user header | |
template.getRestTemplate().setInterceptors(Collections.singletonList((request, body, execution) -> { | |
request.getHeaders() | |
.add("userHeader", "user"); | |
return execution.execute(request, body); | |
})); | |
} | |
} |
5- how to collect the test reports in Jenkins pipeline :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
stage('Integration tests') { | |
// Run the maven build | |
steps { | |
script { | |
def mvnHome = tool 'Maven 3.3.9' | |
if (isUnix()) { | |
// to skip unit testing execution | |
sh "'${mvnHome}/bin/mvn' verify -Dunit-tests.skip=true" | |
} else { | |
bat(/"${mvnHome}\bin\mvn" verify -Dunit-tests.skip=true/) | |
} | |
} | |
// here cucumber extension will collect the reports for you | |
cucumber buildStatus: null, fileIncludePattern: '**/cucumber.json', jsonReportDirectory: 'target', sortingMethod: 'ALPHABETICAL' | |
} | |
} |
Complete working sample is here :
GitHub: https://github.com/Romeh/spring-boot-sample-app
References :
- Cucumber: https://cucumber.io/
- Spring boot : https://projects.spring.io/spring-boot/