Behavior-Driven Development (BDD) is een manier van software ontwikkelen waarbij je het gewenste gedrag van een systeem beschrijft vanuit het perspectief van de gebruiker of de business. In plaats van direct te denken aan technische oplossingen, begin je bij BDD met het beschrijven van voorbeelden van gewenst gedrag in gewone taal. Dit helpt om misverstanden te voorkomen en zorgt ervoor dat iedereen (ontwikkelaars, testers, opdrachtgevers) hetzelfde beeld heeft van wat het systeem moet doen.
Een state diagram (toestandsdiagram) is een visueel hulpmiddel dat laat zien in welke verschillende toestanden (states) een systeem of onderdeel van een systeem zich kan bevinden, en hoe het systeem van de ene naar de andere toestand overgaat. Dit type diagram wordt veel gebruikt in softwareontwikkeling om het gedrag van bijvoorbeeld een object, proces of applicatie te modelleren.
State diagrams helpen je om:
Hieronder zie je een voorbeeld van een state diagram. Het proces beschrijft de registratie van een nieuwe gebruiker.
stateDiagram-v2
[*] --> NietGeregistreerd
NietGeregistreerd --> FormulierIngevuld : Gebruiker vult registratieformulier in
FormulierIngevuld --> Geregistreerd : Gegevens zijn geldig
FormulierIngevuld --> NietGeregistreerd : Gegevens ongeldig
Geregistreerd --> EmailBevestigd : Gebruiker bevestigt e-mail
Geregistreerd --> NietGeregistreerd : Gebruiker annuleert registratie
EmailBevestigd --> [*]
Gherkin is een taal die gebruikt wordt om het gedrag van software te beschrijven in een begrijpelijke en gestructureerde manier. Het is een onderdeel van het Behavior Driven Development (BDD) proces en helpt teams om de vereisten van de software te begrijpen en te communiceren. Gherkin gebruikt een eenvoudige syntaxis die gemakkelijk te lezen en te schrijven is, waardoor het toegankelijk is voor zowel technische als niet-technische teamleden.
Gherkin beschrijft het gedrag van software in termen van “features”, “scenarios” en “steps”:
In Gherkin worden de stappen beschreven in de vorm van “Given”, “When” en “Then”:
Hier is een voorbeeld van hoe Gherkin gebruikt kan worden om het gedrag van het gebruikersregistratieproces te beschrijven:
Feature: Gebruikersregistratie
Scenario: Succesvolle registratie
Given de gebruiker is niet geregistreerd
When de gebruiker vult het registratieformulier correct in
And de gebruiker bevestigt de registratie via e-mail
Then is de gebruiker geregistreerd en bevestigd
Scenario: Registratie met ongeldige gegevens
Given de gebruiker is niet geregistreerd
When de gebruiker vult het registratieformulier onjuist in
Then blijft de gebruiker niet geregistreerd
Scenario: Gebruiker annuleert registratie
Given de gebruiker is niet geregistreerd
When de gebruiker vult het registratieformulier correct in
And de gebruiker annuleert de registratie
Then blijft de gebruiker niet geregistreerd
Zoals eerder uitgelegd, wordt Gherkin gebruikt om het gewenste gedrag van software in begrijpelijke scenario’s te beschrijven. Maar om deze scenario’s daadwerkelijk te kunnen testen en automatiseren, heb je een tool nodig die deze Gherkin-bestanden kan uitvoeren. Hier komt het Cucumber framework in beeld.
Cucumber is een testautomatiseringsframework dat direct werkt met Gherkin-scenario’s. Het framework leest de scenario’s uit de feature-bestanden en koppelt deze aan zogenaamde step definitions: code die de beschreven stappen uitvoert. Hierdoor kun je de in Gherkin beschreven requirements direct valideren met geautomatiseerde tests. Dit zorgt voor een naadloze verbinding tussen specificatie (Gherkin) en uitvoering (Cucumber).
.feature-bestanden.Stel je hebt het volgende Gherkin-scenario in registratie.feature:
Feature: Gebruikersregistratie
Scenario: Succesvolle registratie
Given de gebruiker is niet geregistreerd
When de gebruiker vult het registratieformulier correct in
And de gebruiker bevestigt de registratie via e-mail
Then is de gebruiker geregistreerd en bevestigd
De bijbehorende step definitions in Java kunnen er zo uitzien:
package nl.jouwproject.stappen;
import io.cucumber.java.nl.Gegeven;
import io.cucumber.java.nl.Als;
import io.cucumber.java.nl.Dan;
public class RegistratieSteps {
@Gegeven("de gebruiker is niet geregistreerd")
public void gebruikerNietGeregistreerd() {
// Setup voor niet-geregistreerde gebruiker
}
@Als("de gebruiker vult het registratieformulier correct in")
public void registratieformulierCorrectIngevuld() {
// Formulier correct invullen
}
@Als("de gebruiker bevestigt de registratie via e-mail")
public void registratieBevestigenViaEmail() {
// E-mail bevestigen
}
@Dan("is de gebruiker geregistreerd en bevestigd")
public void gebruikerGeregistreerdEnBevestigd() {
// Controleer registratie en bevestiging
}
}
Om Cucumber correct te laten werken, is het belangrijk dat je projectstructuur overeenkomt met de package-instellingen in je Cucumber-runner en step definitions. Hieronder een voorbeeld van een mogelijke folderstructuur, inclusief de locatie van de Cucumber-runner:
project-root/
└── src/
└── test/
├── java/
│ └── nl/
│ └── jouwproject/
│ └── stappen/
│ ├── RegistratieSteps.java
│ └── RunCucumberTest.java
└── resources/
└── features/
└── registratie.feature
nl.jouwproject.stappen.features onder resources.Hieronder zie je hoe de Cucumber-runner eruitziet, passend bij deze structuur:
package nl.jouwproject.stappen;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;
import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("features") // map met feature-bestanden
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "nl.jouwproject.stappen") // package met step definitions
public class RunCucumberTest {
}
Voor Maven voeg je de volgende dependency toe aan je pom.xml (versie juni 2025):
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.15.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit-platform-engine</artifactId>
<version>7.15.0</version>
<scope>test</scope>
</dependency>
features-map met je .feature-bestanden.Cucumber maakt het mogelijk om specificaties en tests te combineren, waardoor je requirements direct kunt valideren met geautomatiseerde tests.