Behaviour-Driven Development (BDD) with Cucumber, Junit and Spring Boot
Behaviour-Driven Development aka BDD.BDD is a collaborative approach to software development that bridges the communication gap between business and IT. It helps teams create business requirements that can be understood by the whole team. Specifying examples uncovers misunderstandings people might not even be aware of. Teams that practice BDD focus on preventing defects rather than […]
Behaviour-Driven Development aka BDD.BDD is a collaborative approach to software development that bridges the communication gap between business and IT. It helps teams create business requirements that can be understood by the whole team. Specifying examples uncovers misunderstandings people might not even be aware of. Teams that practice BDD focus on preventing defects rather than finding them. This leads to less rework and quicker market time.
Benefits of Behaviour-Driven Development
1. Reduces rework caused by misunderstood or vague requirements2. Reduces technical debt caused by reluctance to refactor code3. Reduces slow feedback cycles caused by silos and hand-overs4. Narrows the communication gaps between team members5. Fosters better understanding of the customer6. Promotes continuous communication with real world examples
Requirements
For the purpose of this tests I will use STS as workspace and very very important 1.5.12.RELEASE version of Spring. If you use the latest one you will be in trouble. And lastly, the latest version of the Cucumber plugin.
How to write simple test in plain English with Gherkin?
So, enough with the boring definitions. Let’s start with the work part.The first thing you need to know about BDD with Cucumber is that you write your tests in plain English. The language itself is called Gherkin and resemble something like this:Scenario: Hearing your snake you anticipate soundGiven I have hungry snakeWhen When I feed my snakeThen I receive snek snekAs you can see it is plain english. This way you are able to connect your business to your application. What is happening behind is that we are using annotations to mark our test code to the tests.
Dependencies required for this example
First create Spring starter project and change the version of Spring, because it will be set to the latests one.
Now for the purpose of the test we will have simple SnakeController which we will test.
@Controller
public class SnakeController {
private boolean fed;
@Autowired
public SnakeController() {
super();
}
public void feed()
{
fed = true;
}
public String poke() {
if(this.fed == true)
return "snek snek ^_^";
else
return "hiss";
}
}
File structure and good practices for storing your Gherkin tests. Writing your first test.
Until now - nothing new. Let’s continue to the tests. As I mentioned above all tests that are in the Gherkin language are simple files with .feature extension.You can create them everywhere in your project. It is a good practice to make folder in your src/test/resources and put them there.I prefer to add even a feature folder for personal preference. So you only need to create a file there with the feature extension and start writing tests. You have to end with something like this:Then let’s add what we want to test in the feature file.Feature: What does your snake sayI want to use this to check what snake saysScenario: Hearing your snake you anticipate soundGiven I have hungry snakeWhen When I feed my snakeThen I receive snek snek
Creating runner responsible for the execution of your tests
We create a simple runner that will run our test code:
@RunWith(Cucumber.class)
@CucumberOptions(plugin = { "pretty"},
features = { "src/test/resources/features" })
public class TestRunner {
}
Make sure to notice that we are giving the destination of our feature file in the features argument.
The trick part.Creating @SpringBootTest glued to your Gherkin definitions.
Now it is becoming little tricky. We are going to run the tests with Spring so we need to make abstract class that will use the @SpringBootTest functionality and our Cucumber annotated tests are going to use it.
@RunWith(SpringRunner.class)
@SpringBootTest
public abstract class CucumberStepDefinitions {
}
And at last we are gluing our step definitions from our feature file to our test code:
public class SnakeMeasureTest extends CucumberStepDefinitions {
@Autowired
SnakeController snake;
@Given("^I have hungry snake")
public void i_have_hungry_snake() {
assertEquals("hiss", snake.poke());
}
@When("^When I feed my snake$")
public void when_i_feed_my_snake() {
snake.feed();
}
@Then("^I receive snek snek$")
public void receive_snek_snek() {
assertEquals("snek snek ^_^", snake.poke());
}
}
Make sure to note that the Gherkin annotations from the feature file are above our test functions. In the end you have to run your test as simple Junit test and you should receive something like this in your console:I hope you find the information useful. If you like what you have just read or have any questions, hit the comment button below.
Sign up for our newsletter and never miss an article
[mc4wp_form id=8036]
Manage Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.