SlideShare a Scribd company logo
Behavior driven
development with JGiven
Achim Wiedemann | 24.10.2017
24.10.2017 Achim WiedemannSeite 2
Who am I?
Achim Wiedemann
Software developer
Joined Haufe-Lexware in April 2015
Working on lexoffice
24.10.2017 Achim WiedemannSeite 3
Sorry, but…
No Cloud
No Microservices
No Docker
No Big Data
24.10.2017 Achim WiedemannSeite 4
Agenda
Part I – Introduction to BDD
Part II – Traditional BDD tools
Part III – BDD with JGiven
24.10.2017 Achim WiedemannSeite 5
Part I – Introduction to BDD
24.10.2017 Achim WiedemannSeite 6
What is Behavior Driven Development?
Method of writing software tests
• Started around 2004 by Dan North
• TDD for business functionality
Goals for tests:
• Focus on business value
• Make writing tests simple
• Use domain specific language
• Provide value for devs and business people
• Make acceptance criteria executable
24.10.2017 Achim WiedemannSeite 7
BDD - where does it fit in?
Unit tests:
• Focus on technical components
• Traditional driver of TDD
Acceptance tests:
• Focus on business components
• Driver of BDD
• Usually UI or API tests
http://martinfowler.com/bliki/TestPyramid.html
24.10.2017 Achim WiedemannSeite 8
Acceptance criteria
States requirements
Needs to be met for implementation to be accepted
Can be written in the form:
As a [role]
I want [feature]
so that [benefit]
Example:
As a customer,
I want to withdraw cash from an ATM,
so that I don’t have to wait in line at the bank.
 Involved roles
 User intent
 Business value
24.10.2017 Achim WiedemannSeite 9
Acceptance criteria – 2
Writing acceptance criteria can be hard
Don‘t fall into this trap:
As a user,
I want to withdraw cash from an ATM,
so that I can withdraw cash from an ATM
Simpler to write, but:
• Doesn‘t show the involved roles
• Doesn‘t show the business value for the user
24.10.2017 Achim WiedemannSeite 10
Validating acceptance criteria with scenarios
Specify tests against acceptance criteria
Scenarios can be derived from acceptance criteria:
As a customer,
I want to withdraw cash from an ATM,
so that I don’t have to wait in line at the bank.
Derived scenario „Account is in credit“:
Given the account is in credit
And the card is valid
And the dispenser contains cash
When the customer requests cash
Then ensure the account is debited
And ensure cash is dispensed
And ensure the card is returned
24.10.2017 Achim WiedemannSeite 11
Validating acceptance criteria with scenarios - 2
Use Given-When-Then form:
• Given [context]
When [events]
Then [expected outcomes]
Simple template
Easy to read
Easy to write
Central part of BDD
24.10.2017 Achim WiedemannSeite 12
BDD summary
Validate against AC with Scenarios
• Use Given – When – Then form
Goals for tests:
• Focus on business value  
• Make writing tests simple  
• Use domain specific language  
• Provide value for devs and business people  
• Make acceptance criteria executable  
24.10.2017 Achim WiedemannSeite 13
Part II – Traditional BDD tools
24.10.2017 Achim WiedemannSeite 14
JBehave
The missing part: „Make acceptance criteria executable“
• JBehave was born
Uses a *.story file for scenarios (plain text)
Scenarios are mapped to test methods (Java)
Run scenario tests like JUnit tests
View results as report (text, HTML, XML, …)
24.10.2017 Achim WiedemannSeite 15
JBehave
Scenario: trader is not alerted below threshold
Given a stock of symbol STK1 and a threshold of 10.0
When the stock is traded at 5.0
Then the alert status should be OFF
Scenario: trader is alerted above threshold
Given a stock of symbol STK1 and a threshold of 10.0
When the stock is traded at 11.0
Then the alert status should be ON
public class TraderSteps { // look, Ma, I'm a POJO!!
private Stock stock;
@Given("a stock of symbol $symbol and a threshold of $threshold")
public void aStock(String symbol, double threshold) {
stock = new Stock(symbol, threshold);
}
@When("the stock is traded at $price")
public void theStockIsTradedAt(double price) {
stock.tradeAt(price);
}
@Then("the alert status should be $status")
public void theAlertStatusShouldBe(String status) {
ensureThat(stock.getStatus().name(), equalTo(status));
}
}
24.10.2017 Achim WiedemannSeite 16
JBehave summary
The good:
• Plain english
• Focus on business value
• Use of domain specific language
• Business people can write scenarios
The bad:
• Plain english
• String matching
• No guidance with domain specific language
• Usually devs end up writing scenarios
24.10.2017 Achim WiedemannSeite 17
Part III – BDD with JGiven
24.10.2017 Achim WiedemannSeite 18
JGiven
Created in 2014 by Jan Schäfer (TNG Technology Consulting)
Main goal:
• Remove disconnect between code and plain text in BDD
JGiven:
• Write everything in Java code
• Promote code reuse
• Leverage existing tools (JUnit)
• Great reports
24.10.2017 Achim WiedemannSeite 19
Scenario example: place order in shop
@Test
public void logged_in_customer_should_be_able_to_place_an_order() {
given()
.user_is_logged_in_as(USER_TEST.username, USER_TEST.password)
.and().user_is_on_catalog_page();
when()
.user_adds_item_to_cart(PRODUCT_ID_BOOK, 1)
.and().user_opens_cart_page()
.and().user_follows_shipping_address_link()
.and().user_enters_some_shipping_address()
.and().user_places_order();
then()
.user_should_be_on_order_success_page();
}
Logged in customer should be able to place an order
Given user is logged in as test test
And user is on catalog page
When user adds item to cart 1 1
And user opens cart page
And user follows shipping address link
And user enters some shipping address
And user places order
Then user should be on order success page
24.10.2017 Achim WiedemannSeite 20
Dissecting a scenario test
public class OrderScenarioTest extends ScenarioTest<GivenStage, WhenOnCatalogPageStage, ThenStage> {
private static final String PRODUCT_ID_BOOK = "1";
@Test
public void logged_in_customer_should_be_able_to_place_an_order() {
given()
.user_is_logged_in_as(USER_TEST.username, USER_TEST.password)
.and().user_is_on_catalog_page();
when()
.user_adds_item_to_cart(PRODUCT_ID_BOOK, 1)
.and().user_opens_cart_page()
.and().user_follows_shipping_address_link()
.and().user_enters_some_shipping_address()
.and().user_places_order();
then()
.user_should_be_on_order_success_page();
}
}
Step
method
Stage
Scenario
24.10.2017 Achim WiedemannSeite 21
Scenarios
Methods in normal JUnit test classes
Derive JUnit test from ScenarioTest
• given()
• when()
• then()
Specify stages as type parameters
Use snake_case for test methods for proper casing
24.10.2017 Achim WiedemannSeite 22
Scenarios - 2
public class OrderScenarioTest extends ScenarioTest<GivenStage, WhenOnCatalogPageStage, ThenStage> {
private static final String PRODUCT_ID_BOOK = "1";
@Test
public void logged_in_customer_should_be_able_to_place_an_order() {
given()
.user_is_logged_in_as(USER_TEST.username, USER_TEST.password)
.and().user_is_on_catalog_page();
when()
.user_adds_item_to_cart(PRODUCT_ID_BOOK, 1)
.and().user_opens_cart_page()
.and().user_follows_shipping_address_link()
.and().user_enters_some_shipping_address()
.and().user_places_order();
then()
.user_should_be_on_order_success_page();
}
}
:GivenStage
:WhenOnCatalogPageStage
:ThenStage
24.10.2017 Achim WiedemannSeite 23
Creating a DSL with stages
Building blocks of scenarios
Model states and actions
• States: stages
• Actions: step methods
Form DSL with a fluid interface
Given on catalog page
When add item to cart
and view cart
and order items
and confirm order
and continue shopping
and view past orders
Then order history should not be empty
24.10.2017 Achim WiedemannSeite 24
Creating a DSL with stages - 2
Derive from Stage
• and()
• with()
• but()
Fluid interface:
• Step methods which return stages
Allows sentences like:
given().user_is_on_catalog_page().and().user_adds_item_to_cart("4711", 3);
public class WhenOnCatalogPageStage extends Stage<WhenOnCatalogPageStage> {
@ScenarioState
protected CatalogPage catalogPage;
public WhenOnCatalogPageStage user_adds_item_to_cart(String productId, int quantity) {
for (int i = 0; i < quantity; i++)
catalogPage.addProductToCart(productId);
return this;
}
}
24.10.2017 Achim WiedemannSeite 25
Creating a DSL with stages - 3
public class WhenOnCatalogPageStage extends Stage<WhenOnCatalogPageStage> {
@ScenarioState
protected CatalogPage catalogPage;
@ScenarioState
protected CartPage cartPage;
@ScenarioState
protected OrderHistoryPage orderHistoryPage;
@ScenarioStage
protected WhenOnCartPageStage cartStage;
public WhenOnCatalogPageStage user_adds_item_to_cart(String productId, int quantity) {
for (int i = 0; i < quantity; i++)
catalogPage.addProductToCart(productId);
return this; // State machine: transition to same state (on catalog page)
}
public WhenOnCartPageStage user_opens_cart_page() {
cartPage.openPage();
return cartStage; // State machine: transition to different state (on cart page)
}
public void user_opnes_order_history_page() {
orderHistoryPage.openPage(); // State machine: end
}
}
24.10.2017 Achim WiedemannSeite 26
Creating a DSL with stages - 4
Model states with stages
Model actions with step methods
Naming is key: focus on business language for your DSL
public class OrderScenarioTest extends ScenarioTest<GivenStage, WhenOnCatalogPageStage, ThenStage> {
private static final String PRODUCT_ID_BOOK = "1";
@Test
public void logged_in_customer_should_be_able_to_place_an_order() {
given()
.user_is_logged_in_as(USER_TEST.username, USER_TEST.password)
.and().user_is_on_catalog_page();
when()
.user_adds_item_to_cart(PRODUCT_ID_BOOK, 1)
.and().user_opens_cart_page()
.and().user_follows_shipping_address_link()
.and().user_enters_some_shipping_address()
.and().user_places_order();
then()
.user_should_be_on_order_success_page();
}
}
24.10.2017 Achim WiedemannSeite 27
Step methods
Actions of our DSL
Make up sentences in report
Use snake_case for correct casing in report
24.10.2017 Achim WiedemannSeite 28
Sharing state
State can be shared accross stages
• Page objects
• Services
• Stages
Injection via @ScenarioState annotations
public abstract class WhenBaseStage<SELF extends WhenBaseStage<SELF>> extends Stage<SELF> {
@ScenarioState
protected LoginPage loginPage;
@ScenarioStage
protected WhenOnCatalogPageStage catalogStage;
...
public WhenOnCatalogPageStage user_logs_in_as(TestUser user) {
if (!loginPage.isUserOnPage())
loginPage.openPage();
loginPage.loginWithCredentials(user.username, user.password);
return catalogStage;
}
...
}
24.10.2017 Achim WiedemannSeite 29
Sharing state - 2
State is passed from stage to stage
Initialization best in Given stage
Alternative to @ScenarioState annotations:
• @ProvidedScenarioState / @ExpectedScenarioState
public class GivenStage extends Stage<GivenStage> {
private final PageFactoryResource pageFactory = new PageFactoryResource();
@ScenarioState
private CatalogPage catalogPage;
@ScenarioState
private LoginPage loginPage;
@ScenarioState
private CartPage cartPage;
@BeforeScenario
public void setUp() {
catalogPage = pageFactory.createCatalogPage();
loginPage = pageFactory.createLoginPage();
cartPage = pageFactory.createCartPage();
}
...
}
24.10.2017 Achim WiedemannSeite 30
Reports
24.10.2017 Achim WiedemannSeite 31
Reports - 2
Correct casing when snake_case is used in methods
• Example: item_is_registered_in_SAP()
Scenarios can be grouped via tags
• Use custom annotations to create tags
Custom formatters for improved readability
• Step methods
• Method parameters
Formats: HTML and JSON
24.10.2017 Achim WiedemannSeite 32
Tags
@IsTag(name="Critical", description="Features that are critical for the user")
@Retention(RetentionPolicy.RUNTIME)
public @interface CriticalFeature {
}
@CriticalFeature
@Test
public void added_item_appears_in_cart() {
...
}
24.10.2017 Achim WiedemannSeite 33
Formatters
Improve readability with formatters
• Use $ in method names
• Custom formatters via @Format
Code:
when().user_adds_item_to_cart("4711", 3)
Generated report:
When user adds item to cart 4711 3
Code (using placeholders):
when().user_adds_item_$_to_cart_of_quantity_$("4711", 3)
Generated report (using placeholders):
When user adds item 4711 to cart of quantity 3
24.10.2017 Achim WiedemannSeite 34
Formatters - 2
@Test
public void added_item_appears_in_cart() {
given()
.user_is_logged_in_as(USER_TEST);
when()
.user_adds_item_$_to_cart_of_quantity_$(PRODUCT_ID_BOOK, 1)
.and().user_opens_cart_page();
then()
.user_should_see_cart_item_count_of(1);
}
24.10.2017 Achim WiedemannSeite 35
JGiven - Summary
The good:
• Simple JUnit tests
• Pure Java – no mapping from text to code
• Business focused DSL
• Developer friendly
The bad:
• Documentation quite good but could be even better
• Relatively unknown
• Business people can‘t write scenarios
24.10.2017 Achim WiedemannSeite 36
DEMO
https://github.com/achwie/hystrix-demo

More Related Content

PDF
Docker in Production at the Aurora Team
PPTX
Managing short lived Kubernetes (Production) deployments
PPTX
Externalized Spring Boot App Configuration
PPTX
Chugging Our Own "Craft Brew” – HPE’s Journey Towards Containers-as-a-Service...
PDF
Haufe Onboarding - Fast Iterating With the MERN Stack - TEC Day 2019
PDF
Platform Engineering with the CDK
PPTX
My session slides from unityConnect 2016 in Haarlem
PDF
Serverless Functions: Accelerating DevOps Adoption
Docker in Production at the Aurora Team
Managing short lived Kubernetes (Production) deployments
Externalized Spring Boot App Configuration
Chugging Our Own "Craft Brew” – HPE’s Journey Towards Containers-as-a-Service...
Haufe Onboarding - Fast Iterating With the MERN Stack - TEC Day 2019
Platform Engineering with the CDK
My session slides from unityConnect 2016 in Haarlem
Serverless Functions: Accelerating DevOps Adoption

What's hot (20)

PPTX
Session Slides from DEVintersection Europe
PPTX
European SharePoint Conference - TH3
PDF
Everything You Need to Know About Docker and Storage by Ryan Wallner, ClusterHQ
PPTX
Session Slides from DEVintersection Europe
PPTX
My slides from SharePoint Saturday Oslo
PDF
How to Make Money Solving 5 Major Problems of Cloud Hosting Customers
PDF
IaC on AWS Cloud
PDF
DevEx | there’s no place like k3s
PDF
Velocity NYC 2016 - Containers @ Netflix
PPTX
End-to-end test automation with Endtest.dev
PDF
56k.cloud training
PDF
A curtain-raiser to the container world Docker & Kubernetes
PDF
JEEconf 2017
PPTX
Languages don't matter anymore!
PDF
From VMs to Containers: Decompose and Migrate Old Legacy JavaEE Application
PDF
Nils Rhode - Does it always have to be k8s - TeC Day 2019
PDF
Automating CICD Pipeline with GitLab and Docker Containers for Java Applications
PPTX
Structured Container Delivery by Oscar Renalias, Accenture
PDF
All the reasons for choosing react js that you didn't know about - Avi Marcus...
PPTX
Serverless
Session Slides from DEVintersection Europe
European SharePoint Conference - TH3
Everything You Need to Know About Docker and Storage by Ryan Wallner, ClusterHQ
Session Slides from DEVintersection Europe
My slides from SharePoint Saturday Oslo
How to Make Money Solving 5 Major Problems of Cloud Hosting Customers
IaC on AWS Cloud
DevEx | there’s no place like k3s
Velocity NYC 2016 - Containers @ Netflix
End-to-end test automation with Endtest.dev
56k.cloud training
A curtain-raiser to the container world Docker & Kubernetes
JEEconf 2017
Languages don't matter anymore!
From VMs to Containers: Decompose and Migrate Old Legacy JavaEE Application
Nils Rhode - Does it always have to be k8s - TeC Day 2019
Automating CICD Pipeline with GitLab and Docker Containers for Java Applications
Structured Container Delivery by Oscar Renalias, Accenture
All the reasons for choosing react js that you didn't know about - Avi Marcus...
Serverless
Ad

Similar to Behavior-Driven Development with JGiven (20)

PDF
Presentation by Erik van der Hoeven (Wisdom as a Service) at the Data Vault M...
PPTX
Behavior-driven Development and Lambdaj
PPTX
Building In Quality: The Beauty Of Behavior Driven Development (BDD)
PPTX
Bdd with Cucumber and Mocha
PPTX
Dynamics ax 2012 development overview
PDF
Mastering JavaScript and DOM: A Gateway to Web Development
PDF
About The Event-Driven Data Layer & Adobe Analytics
PPTX
MongoDB.local Atlanta: MongoDB Stitch Tutorial
PDF
CV - Abhijit
PPTX
Behaviour Driven Development V 0.1
PPTX
Automation testing
PPTX
MongoDB.local Seattle 2019: MongoDB Stitch Tutorial
PDF
B2C-Commerce-Developer Dumps
PPTX
An Introduction to Domain Driven Design in PHP
PPTX
Pricing On Purpose Our Journey Public Version
PPTX
You know what iMEAN? Using MEAN stack for application dev on Informix
PDF
2015 in tothebox-introtddbdd
PDF
Intro to TDD & BDD
PDF
ITB2015 - Behavior Driven Development, Automation and Continuous Integration
Presentation by Erik van der Hoeven (Wisdom as a Service) at the Data Vault M...
Behavior-driven Development and Lambdaj
Building In Quality: The Beauty Of Behavior Driven Development (BDD)
Bdd with Cucumber and Mocha
Dynamics ax 2012 development overview
Mastering JavaScript and DOM: A Gateway to Web Development
About The Event-Driven Data Layer & Adobe Analytics
MongoDB.local Atlanta: MongoDB Stitch Tutorial
CV - Abhijit
Behaviour Driven Development V 0.1
Automation testing
MongoDB.local Seattle 2019: MongoDB Stitch Tutorial
B2C-Commerce-Developer Dumps
An Introduction to Domain Driven Design in PHP
Pricing On Purpose Our Journey Public Version
You know what iMEAN? Using MEAN stack for application dev on Informix
2015 in tothebox-introtddbdd
Intro to TDD & BDD
ITB2015 - Behavior Driven Development, Automation and Continuous Integration
Ad

More from Haufe-Lexware GmbH & Co KG (20)

PDF
Tech stackhaufegroup
PPTX
X-celerate 2019: Iterating fast with the MERN Stack
PPTX
Cloud Journey: Lifting a Major Product to Kubernetes
PPTX
ONA ( organizational network analysis ) to enable individuals to impact their...
PPTX
ONA ( organizational network analysis ) enabling individuals to impact their ...
PPTX
Using word vectors to enable better search in our legal products
PPTX
Identifying customer potentials through unsupervised learning
PPTX
Field report: Rapid application development
PPTX
DevOps Journey of Foundational Services at Haufe
PPTX
New Serverless World - Cloud Native Apps
PPTX
Microservice Transformation of the Haufe Publishing System
PPTX
Haufe API Strategy
PPTX
Haufe's Tech Strategy In Practice
PPTX
Kubernetes Intro @HaufeDev
PPTX
API Management with wicked.haufe.io
PDF
Reactive microservices
PDF
An Introduction to event sourcing and CQRS
PDF
The seven more deadly sins of microservices final
PDF
The seven deadly sins of microservices
PDF
Building a microservice ecosystem
Tech stackhaufegroup
X-celerate 2019: Iterating fast with the MERN Stack
Cloud Journey: Lifting a Major Product to Kubernetes
ONA ( organizational network analysis ) to enable individuals to impact their...
ONA ( organizational network analysis ) enabling individuals to impact their ...
Using word vectors to enable better search in our legal products
Identifying customer potentials through unsupervised learning
Field report: Rapid application development
DevOps Journey of Foundational Services at Haufe
New Serverless World - Cloud Native Apps
Microservice Transformation of the Haufe Publishing System
Haufe API Strategy
Haufe's Tech Strategy In Practice
Kubernetes Intro @HaufeDev
API Management with wicked.haufe.io
Reactive microservices
An Introduction to event sourcing and CQRS
The seven more deadly sins of microservices final
The seven deadly sins of microservices
Building a microservice ecosystem

Recently uploaded (20)

PPTX
CHAPTER 2 - PM Management and IT Context
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PPTX
L1 - Introduction to python Backend.pptx
PPTX
Computer Software and OS of computer science of grade 11.pptx
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
System and Network Administraation Chapter 3
PDF
top salesforce developer skills in 2025.pdf
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
PTS Company Brochure 2025 (1).pdf.......
PPTX
Introduction to Artificial Intelligence
CHAPTER 2 - PM Management and IT Context
Operating system designcfffgfgggggggvggggggggg
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
L1 - Introduction to python Backend.pptx
Computer Software and OS of computer science of grade 11.pptx
Upgrade and Innovation Strategies for SAP ERP Customers
How to Choose the Right IT Partner for Your Business in Malaysia
Adobe Illustrator 28.6 Crack My Vision of Vector Design
System and Network Administraation Chapter 3
top salesforce developer skills in 2025.pdf
Softaken Excel to vCard Converter Software.pdf
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
Understanding Forklifts - TECH EHS Solution
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Wondershare Filmora 15 Crack With Activation Key [2025
PTS Company Brochure 2025 (1).pdf.......
Introduction to Artificial Intelligence

Behavior-Driven Development with JGiven

  • 1. Behavior driven development with JGiven Achim Wiedemann | 24.10.2017
  • 2. 24.10.2017 Achim WiedemannSeite 2 Who am I? Achim Wiedemann Software developer Joined Haufe-Lexware in April 2015 Working on lexoffice
  • 3. 24.10.2017 Achim WiedemannSeite 3 Sorry, but… No Cloud No Microservices No Docker No Big Data
  • 4. 24.10.2017 Achim WiedemannSeite 4 Agenda Part I – Introduction to BDD Part II – Traditional BDD tools Part III – BDD with JGiven
  • 5. 24.10.2017 Achim WiedemannSeite 5 Part I – Introduction to BDD
  • 6. 24.10.2017 Achim WiedemannSeite 6 What is Behavior Driven Development? Method of writing software tests • Started around 2004 by Dan North • TDD for business functionality Goals for tests: • Focus on business value • Make writing tests simple • Use domain specific language • Provide value for devs and business people • Make acceptance criteria executable
  • 7. 24.10.2017 Achim WiedemannSeite 7 BDD - where does it fit in? Unit tests: • Focus on technical components • Traditional driver of TDD Acceptance tests: • Focus on business components • Driver of BDD • Usually UI or API tests http://martinfowler.com/bliki/TestPyramid.html
  • 8. 24.10.2017 Achim WiedemannSeite 8 Acceptance criteria States requirements Needs to be met for implementation to be accepted Can be written in the form: As a [role] I want [feature] so that [benefit] Example: As a customer, I want to withdraw cash from an ATM, so that I don’t have to wait in line at the bank.  Involved roles  User intent  Business value
  • 9. 24.10.2017 Achim WiedemannSeite 9 Acceptance criteria – 2 Writing acceptance criteria can be hard Don‘t fall into this trap: As a user, I want to withdraw cash from an ATM, so that I can withdraw cash from an ATM Simpler to write, but: • Doesn‘t show the involved roles • Doesn‘t show the business value for the user
  • 10. 24.10.2017 Achim WiedemannSeite 10 Validating acceptance criteria with scenarios Specify tests against acceptance criteria Scenarios can be derived from acceptance criteria: As a customer, I want to withdraw cash from an ATM, so that I don’t have to wait in line at the bank. Derived scenario „Account is in credit“: Given the account is in credit And the card is valid And the dispenser contains cash When the customer requests cash Then ensure the account is debited And ensure cash is dispensed And ensure the card is returned
  • 11. 24.10.2017 Achim WiedemannSeite 11 Validating acceptance criteria with scenarios - 2 Use Given-When-Then form: • Given [context] When [events] Then [expected outcomes] Simple template Easy to read Easy to write Central part of BDD
  • 12. 24.10.2017 Achim WiedemannSeite 12 BDD summary Validate against AC with Scenarios • Use Given – When – Then form Goals for tests: • Focus on business value   • Make writing tests simple   • Use domain specific language   • Provide value for devs and business people   • Make acceptance criteria executable  
  • 13. 24.10.2017 Achim WiedemannSeite 13 Part II – Traditional BDD tools
  • 14. 24.10.2017 Achim WiedemannSeite 14 JBehave The missing part: „Make acceptance criteria executable“ • JBehave was born Uses a *.story file for scenarios (plain text) Scenarios are mapped to test methods (Java) Run scenario tests like JUnit tests View results as report (text, HTML, XML, …)
  • 15. 24.10.2017 Achim WiedemannSeite 15 JBehave Scenario: trader is not alerted below threshold Given a stock of symbol STK1 and a threshold of 10.0 When the stock is traded at 5.0 Then the alert status should be OFF Scenario: trader is alerted above threshold Given a stock of symbol STK1 and a threshold of 10.0 When the stock is traded at 11.0 Then the alert status should be ON public class TraderSteps { // look, Ma, I'm a POJO!! private Stock stock; @Given("a stock of symbol $symbol and a threshold of $threshold") public void aStock(String symbol, double threshold) { stock = new Stock(symbol, threshold); } @When("the stock is traded at $price") public void theStockIsTradedAt(double price) { stock.tradeAt(price); } @Then("the alert status should be $status") public void theAlertStatusShouldBe(String status) { ensureThat(stock.getStatus().name(), equalTo(status)); } }
  • 16. 24.10.2017 Achim WiedemannSeite 16 JBehave summary The good: • Plain english • Focus on business value • Use of domain specific language • Business people can write scenarios The bad: • Plain english • String matching • No guidance with domain specific language • Usually devs end up writing scenarios
  • 17. 24.10.2017 Achim WiedemannSeite 17 Part III – BDD with JGiven
  • 18. 24.10.2017 Achim WiedemannSeite 18 JGiven Created in 2014 by Jan Schäfer (TNG Technology Consulting) Main goal: • Remove disconnect between code and plain text in BDD JGiven: • Write everything in Java code • Promote code reuse • Leverage existing tools (JUnit) • Great reports
  • 19. 24.10.2017 Achim WiedemannSeite 19 Scenario example: place order in shop @Test public void logged_in_customer_should_be_able_to_place_an_order() { given() .user_is_logged_in_as(USER_TEST.username, USER_TEST.password) .and().user_is_on_catalog_page(); when() .user_adds_item_to_cart(PRODUCT_ID_BOOK, 1) .and().user_opens_cart_page() .and().user_follows_shipping_address_link() .and().user_enters_some_shipping_address() .and().user_places_order(); then() .user_should_be_on_order_success_page(); } Logged in customer should be able to place an order Given user is logged in as test test And user is on catalog page When user adds item to cart 1 1 And user opens cart page And user follows shipping address link And user enters some shipping address And user places order Then user should be on order success page
  • 20. 24.10.2017 Achim WiedemannSeite 20 Dissecting a scenario test public class OrderScenarioTest extends ScenarioTest<GivenStage, WhenOnCatalogPageStage, ThenStage> { private static final String PRODUCT_ID_BOOK = "1"; @Test public void logged_in_customer_should_be_able_to_place_an_order() { given() .user_is_logged_in_as(USER_TEST.username, USER_TEST.password) .and().user_is_on_catalog_page(); when() .user_adds_item_to_cart(PRODUCT_ID_BOOK, 1) .and().user_opens_cart_page() .and().user_follows_shipping_address_link() .and().user_enters_some_shipping_address() .and().user_places_order(); then() .user_should_be_on_order_success_page(); } } Step method Stage Scenario
  • 21. 24.10.2017 Achim WiedemannSeite 21 Scenarios Methods in normal JUnit test classes Derive JUnit test from ScenarioTest • given() • when() • then() Specify stages as type parameters Use snake_case for test methods for proper casing
  • 22. 24.10.2017 Achim WiedemannSeite 22 Scenarios - 2 public class OrderScenarioTest extends ScenarioTest<GivenStage, WhenOnCatalogPageStage, ThenStage> { private static final String PRODUCT_ID_BOOK = "1"; @Test public void logged_in_customer_should_be_able_to_place_an_order() { given() .user_is_logged_in_as(USER_TEST.username, USER_TEST.password) .and().user_is_on_catalog_page(); when() .user_adds_item_to_cart(PRODUCT_ID_BOOK, 1) .and().user_opens_cart_page() .and().user_follows_shipping_address_link() .and().user_enters_some_shipping_address() .and().user_places_order(); then() .user_should_be_on_order_success_page(); } } :GivenStage :WhenOnCatalogPageStage :ThenStage
  • 23. 24.10.2017 Achim WiedemannSeite 23 Creating a DSL with stages Building blocks of scenarios Model states and actions • States: stages • Actions: step methods Form DSL with a fluid interface Given on catalog page When add item to cart and view cart and order items and confirm order and continue shopping and view past orders Then order history should not be empty
  • 24. 24.10.2017 Achim WiedemannSeite 24 Creating a DSL with stages - 2 Derive from Stage • and() • with() • but() Fluid interface: • Step methods which return stages Allows sentences like: given().user_is_on_catalog_page().and().user_adds_item_to_cart("4711", 3); public class WhenOnCatalogPageStage extends Stage<WhenOnCatalogPageStage> { @ScenarioState protected CatalogPage catalogPage; public WhenOnCatalogPageStage user_adds_item_to_cart(String productId, int quantity) { for (int i = 0; i < quantity; i++) catalogPage.addProductToCart(productId); return this; } }
  • 25. 24.10.2017 Achim WiedemannSeite 25 Creating a DSL with stages - 3 public class WhenOnCatalogPageStage extends Stage<WhenOnCatalogPageStage> { @ScenarioState protected CatalogPage catalogPage; @ScenarioState protected CartPage cartPage; @ScenarioState protected OrderHistoryPage orderHistoryPage; @ScenarioStage protected WhenOnCartPageStage cartStage; public WhenOnCatalogPageStage user_adds_item_to_cart(String productId, int quantity) { for (int i = 0; i < quantity; i++) catalogPage.addProductToCart(productId); return this; // State machine: transition to same state (on catalog page) } public WhenOnCartPageStage user_opens_cart_page() { cartPage.openPage(); return cartStage; // State machine: transition to different state (on cart page) } public void user_opnes_order_history_page() { orderHistoryPage.openPage(); // State machine: end } }
  • 26. 24.10.2017 Achim WiedemannSeite 26 Creating a DSL with stages - 4 Model states with stages Model actions with step methods Naming is key: focus on business language for your DSL public class OrderScenarioTest extends ScenarioTest<GivenStage, WhenOnCatalogPageStage, ThenStage> { private static final String PRODUCT_ID_BOOK = "1"; @Test public void logged_in_customer_should_be_able_to_place_an_order() { given() .user_is_logged_in_as(USER_TEST.username, USER_TEST.password) .and().user_is_on_catalog_page(); when() .user_adds_item_to_cart(PRODUCT_ID_BOOK, 1) .and().user_opens_cart_page() .and().user_follows_shipping_address_link() .and().user_enters_some_shipping_address() .and().user_places_order(); then() .user_should_be_on_order_success_page(); } }
  • 27. 24.10.2017 Achim WiedemannSeite 27 Step methods Actions of our DSL Make up sentences in report Use snake_case for correct casing in report
  • 28. 24.10.2017 Achim WiedemannSeite 28 Sharing state State can be shared accross stages • Page objects • Services • Stages Injection via @ScenarioState annotations public abstract class WhenBaseStage<SELF extends WhenBaseStage<SELF>> extends Stage<SELF> { @ScenarioState protected LoginPage loginPage; @ScenarioStage protected WhenOnCatalogPageStage catalogStage; ... public WhenOnCatalogPageStage user_logs_in_as(TestUser user) { if (!loginPage.isUserOnPage()) loginPage.openPage(); loginPage.loginWithCredentials(user.username, user.password); return catalogStage; } ... }
  • 29. 24.10.2017 Achim WiedemannSeite 29 Sharing state - 2 State is passed from stage to stage Initialization best in Given stage Alternative to @ScenarioState annotations: • @ProvidedScenarioState / @ExpectedScenarioState public class GivenStage extends Stage<GivenStage> { private final PageFactoryResource pageFactory = new PageFactoryResource(); @ScenarioState private CatalogPage catalogPage; @ScenarioState private LoginPage loginPage; @ScenarioState private CartPage cartPage; @BeforeScenario public void setUp() { catalogPage = pageFactory.createCatalogPage(); loginPage = pageFactory.createLoginPage(); cartPage = pageFactory.createCartPage(); } ... }
  • 31. 24.10.2017 Achim WiedemannSeite 31 Reports - 2 Correct casing when snake_case is used in methods • Example: item_is_registered_in_SAP() Scenarios can be grouped via tags • Use custom annotations to create tags Custom formatters for improved readability • Step methods • Method parameters Formats: HTML and JSON
  • 32. 24.10.2017 Achim WiedemannSeite 32 Tags @IsTag(name="Critical", description="Features that are critical for the user") @Retention(RetentionPolicy.RUNTIME) public @interface CriticalFeature { } @CriticalFeature @Test public void added_item_appears_in_cart() { ... }
  • 33. 24.10.2017 Achim WiedemannSeite 33 Formatters Improve readability with formatters • Use $ in method names • Custom formatters via @Format Code: when().user_adds_item_to_cart("4711", 3) Generated report: When user adds item to cart 4711 3 Code (using placeholders): when().user_adds_item_$_to_cart_of_quantity_$("4711", 3) Generated report (using placeholders): When user adds item 4711 to cart of quantity 3
  • 34. 24.10.2017 Achim WiedemannSeite 34 Formatters - 2 @Test public void added_item_appears_in_cart() { given() .user_is_logged_in_as(USER_TEST); when() .user_adds_item_$_to_cart_of_quantity_$(PRODUCT_ID_BOOK, 1) .and().user_opens_cart_page(); then() .user_should_see_cart_item_count_of(1); }
  • 35. 24.10.2017 Achim WiedemannSeite 35 JGiven - Summary The good: • Simple JUnit tests • Pure Java – no mapping from text to code • Business focused DSL • Developer friendly The bad: • Documentation quite good but could be even better • Relatively unknown • Business people can‘t write scenarios
  • 36. 24.10.2017 Achim WiedemannSeite 36 DEMO https://github.com/achwie/hystrix-demo