SlideShare a Scribd company logo
1 of 51
Download to read offline
Cucumber and Spock Primer
BDD Masterclass
Building software that makes a difference, and building it well
@wakaleo
www.johnfergusonsmart.com
reachme@johnfergusonsmart.com
Writing Acceptance Criteria

in Gherkin
Overview
Overview
Basic Gherkin
Feature: Earning Frequent Flyer points through flights
Scenario: Economy flights earn points by distance
Given the distance from London to Paris is 344 km
When I fly from London to Paris in Economy
Then I should earn 344 points
A feature represents a
deliverable piece of functionality
Each feature should
have a title
A feature contains one
or more scenarios
Features and Scenarios
Overview
Overview
Basic Gherkin
Feature: Earning Frequent Flyer points through flights
In order to encourage repeat business
As an Airline Sales Manager
I want customers to be able to cumulate points when they
fly with us
Scenario: Economy flights earn points by distance
Economy class earns 1 point per kilometre
Given the distance from London to Paris is 344 km
When I fly from London to Paris in Economy
Then I should earn 344 points
Free-text description 

(great for living documentation)
You can also put a description
for a Scenario
Free text descriptions
Overview
Overview
Basic Gherkin
Scenario: Economy flights earn points by distance
Economy class earns 1 point per kilometre
Given the distance from London to Paris is 344 km
When I fly from London to Paris in Economy
Then I should earn 344 points
GIVEN: Preconditions
WHEN: Action to illustrate
THEN: Expected outcome
Scenarios
Overview
Overview
Basic Gherkin
Scenario: Economy flights over several legs
Given the distance from London to Paris is 344 km
And the distance from Paris to Krakow is 1500 km
When I fly from London to Krakow via Paris in Economy
Then I should earn 1844 points
And I should earn 18 status points
Multiple preconditions
Scenarios
Multiple outcomes
Overview
Overview
Basic Gherkin
Given steps
✓ Defines preconditions and context
✓ Typically something that happened in the past
✓ Can interact with the system
✓ Should not perform any actions being tested by the
scenario
Given a user registers on the site
And the user logs in
When the home page appears
Then the user’s name should be visible
Given a user has registered on the site
When the user logs in
Then the user’s name should be visible on
the home page
What are we testing here?
Overview
Overview
Basic Gherkin
When steps
✓ The action under test
✓ Avoid chaining too many clauses
Given a user has registered on the site
When the user enters 'Scott' in the user name
And the user enters 'Tiger' in the password
And the user selects 'UK' as the country
And the user clicks on the Login button
And the user validates the Cookies alert
Then the user’s name should be visible on the home page
Too much detail
To implementation-specific
Overview
Overview
Basic Gherkin
Then steps
✓ The expected outcome
✓ Can query the system
✓ Should not perform actions on the system
Given a batch file needs to be processed
When the user uploads the batch file
Then the result should be visible
And a notification message should be sent to the user
Overview
Overview
Basic Gherkin
Background steps
✓ Common steps for all the scenarios in a feature file
✓ Avoid duplication
✓ More focused scenarios
Feature: Earning Frequent Flyer points through flights
In order to encourage repeat business
As an Airline Sales Manager
I want customers to be able to cumulate points when
they fly with us
Background:
Given the distance from London to Paris is 344 km
And the distance from Paris to Krakow is 1500km
Scenario: Economy flights earn points by distance
When I fly from London to Paris in Economy
Then I should earn 344 points
And I should earn 3 status points
Scenario: Economy flights over several legs
When I fly from London to Krakow via Paris in Economy
Then I should earn 1844 points
And I should earn 18 status points
Overview
Overview
Basic Gherkin
Scenario Outlines
✓ Use a table to simplify duplicated but similar scenarios
Background:
Given the distance from London to Paris is 344 km
And the distance from Paris to Krakow is 1500km
And the distance from London to Budapest is 1600km
Scenario: Economy flights earn points by distance
When I fly from London to Paris in Economy
Then I should earn 344 points
And I should earn 3 status points
Scenario: Economy flights to Krakow
When I fly from London to Krakow in Economy
Then I should earn 1500 points
And I should earn 15 status points
Scenario: Economy flights to Budapest
When I fly from London to Budapest in Economy
Then I should earn 1600 points
And I should earn 16 status points
Overview
Overview
Basic Gherkin
Scenario Outlines
✓ Use a table to simplify duplicated but similar scenarios
Background:
Given the distance from London to Paris is 344 km
And the distance from Paris to Krakow is 1500km
And the distance from London to Budapest is 1600km
Scenario Outline:
When I fly from <departure> to <destination> in Economy
Then I should earn <points> points
And I should earn <status-points> status points
Examples:
| departure | destination | points | status-points |
| London | Paris | 344 | 3 |
| Paris | Krakow | 1500 | 15 |
| London | Budapest | 1600 | 16 |
Overview
Overview
Basic Gherkin
Embedded tables
✓ Use tables in steps to pass tabular data to the step
Scenario: Deposit into a current account
Given Joe has the following accounts:
| Number | Type | Balance |
| 123456 | Current | 1000 |
When he deposits €100 into his Current account
Then he should have the following balances:
| Number | Type | Balance |
| 123456 | Current | 1100 |
Overview
Overview
Basic Gherkin
Embedded tables
✓ Use tables in steps to pass tabular data to the step
Feature: Earning Frequent Flyer points through flights
In order to encourage repeat business
As an Airline Sales Manager
I want customers to be able to cumulate points when they fly with us
Background:
Given the following flight routes:
| departure | destination | distance |
| London | Paris | 344 |
| Paris | Krakow | 1500 |
| London | Budapest | 1600 |
Scenario Outline:
When I fly from <departure> to <destination> in Economy
Then I should earn <points> points
And I should earn <status-points> status points
Examples:
| departure | destination | points | status-points |
| London | Paris | 344 | 3 |
| Paris | Krakow | 1500 | 15 |
| London | Budapest | 1600 | 16 |
Overview
Overview
Basic Gherkin
Multi-line string parameters
✓ Pass in multi-line strings as parameters
Given a travel provides feedback about the flight
"""
It was OK
The food was rubbish but the staff were nice
The flight was delayed by 15 minutes
"""
Cucumber Step Definitions
Step Definitions
in Java with
Cucumber and
Serenity BDD
The Cucumber Test Runner
import cucumber.api.CucumberOptions;
import net.serenitybdd.cucumber.CucumberWithSerenity;
import org.junit.runner.RunWith;
@RunWith(CucumberWithSerenity.class)
@CucumberOptions(features = "src/test/resources/features/deposit_funds",
glue = "com.bddinaction.serenitybank")
public class DepositFunds {}
A Cucumber test runner
Which feature files to run
Where to find the step definition classes
Step Definitions
in Java with
Cucumber and
Serenity BDD
Step Definitions
Feature: Earning Frequent Flyer points through flights
Scenario: Economy flights earn points by distance
Given the distance from London to Paris is 344 km
When I fly from London to Paris in Economy
Then I should earn 344 points
@Given("^the distance from (.*) to (.*) is (d+) km$")
public void pointsEarnedBetweenCities(String departure,
String destination,
int distance)
throws Throwable {
}
@Given, @When, or @Then annotation
Matching regular expression
Matched expressions are passed in as parameters
Step Definitions
in Java with
Cucumber and
Serenity BDD
Matching Lists
Given the following possible destinations: London, Paris, Amsterdam
@Given("^the following possible destinations: (.*)$")
public void theFollowingPossibleDestinations(List<String> destinations) {
}
Declare a list of Strings
Given the following possible destinations:
| London |
| Paris |
| Amsterdam |
alternative notation
Step Definitions
in Java with
Cucumber and
Serenity BDD
Matching enums
When I fly from London to Paris in Economy
public enum City {
London, Paris, Amsterdam
}
public enum CabinClass {
Economy, Business, First
}
@When("^I fly from (.*) to (.*) in (.*)$")
public void iFly(City departure, City destination, CabinClass cabinClass){
}
Enums are matched automatically
Step Definitions
in Java with
Cucumber and
Serenity BDD
Matching tables
Given the following flight routes:
| departure | destination | distance |
| London | Paris | 344 |
| Paris | Krakow | 1500 |
| London | Budapest | 1600 |
public void flightRoutes(Map<String, String> flightRoutes) {}
Tables can be passed as a map of Strings
Step Definitions
in Java with
Cucumber and
Serenity BDD
Transformers
When I fly from San Francisco to Paris in Economy
public enum City {
London("London"),
Paris("Paris"),
SanFrancisco("San Francisco"),
SaintPetersbuug("St Petersburg");
public final String name;
City(String name) { this.name = name; }
}
@When("^I fly from (.*) to (.*) in (.*)$")
public void iFly(@Transform(CityConverter.class) City departure,
@Transform(CityConverter.class) City destination,
CabinClass cabinClass) {}
public class CityConverter extends Transformer<City> {
@Override
public City transform(String cityName) {
return Arrays.stream(City.values())
.filter(city -> city.name.equalsIgnoreCase(cityName))
.findFirst()
.orElseThrow(() -> new UnknownCityException(cityName));
}
}
BDD Unit Testing with Spock
Overview
Overview
Introduction
to Spock
http://spockframework.org/
import spock.lang.Specification
class WhenManagingAnAccount extends Specification {
def "depositing a sum into the account should update the balance"() {
given:
def currentAccount = new BankAccount("123456", AccountType.Current)
when:
currentAccount.deposit(1000)
then:
currentAccount.balance == 1000
}
}
All Spock tests extend Specification
Plain English test names
Arrange
Act
Assert
Acts as an assertion
Overview
Overview
Using Fields
class WhenWithdrawingFunds extends Specification {
def accountService = new AccountService();
def "withdrawing funds from a current account"() {
given:
def accountNumber = accountService.createNewAccount(Current, 100.00)
when:
accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now())
then:
accountService.getBalance(accountNumber) == 50.00
}
def "withdrawing funds from a savings account"() {
given:
def accountNumber = accountService.createNewAccount(BigSaver, 1000.00)
when:
accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now())
then:
thrown(MinimumBalanceRequiredException)
and:
accountService.getBalance(accountNumber) == 1000.00
}
}
Instantiated once before each test
Overview
Overview
Using Fields
class WhenWithdrawingFunds extends Specification {
@Shared def accountService = new AccountService()
def "withdrawing funds from a current account"() {
given:
def accountNumber = accountService.createNewAccount(Current, 100.00)
when:
accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now())
then:
accountService.getBalance(accountNumber) == 50.00
}
def "withdrawing funds from a savings account"() {
given:
def accountNumber = accountService.createNewAccount(BigSaver, 1000.00)
when:
accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now())
then:
thrown(MinimumBalanceRequiredException)
and:
accountService.getBalance(accountNumber) == 1000.00
}
}
Instantiated once and shared between the tests
Overview
Overview
Using Fields
class WhenWithdrawingFunds extends Specification {
def accountService
def setup() {
accountService = new AccountService()
}
def "withdrawing funds from a current account"() {
given:
def accountNumber = accountService.createNewAccount(Current, 100.00)
when:
accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now())
then:
accountService.getBalance(accountNumber) == 50.00
}
def "withdrawing funds from a savings account"() {
given:
def accountNumber = accountService.createNewAccount(BigSaver, 1000.00)
when:
accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now())
then:
thrown(MinimumBalanceRequiredException)
and:
accountService.getBalance(accountNumber) == 1000.00
}
}
Runs before each test
Overview
Overview
Using Fields
class WhenWithdrawingFunds extends Specification {
@Shared def accountService = new AccountService()
def setupSpec() {
accountService = new AccountService()
}
def "withdrawing funds from a current account"() {
given:
def accountNumber = accountService.createNewAccount(Current, 100.00)
when:
accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now())
then:
accountService.getBalance(accountNumber) == 50.00
}
def "withdrawing funds from a savings account"() {
given:
def accountNumber = accountService.createNewAccount(BigSaver, 1000.00)
when:
accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now())
then:
thrown(MinimumBalanceRequiredException)
and:
accountService.getBalance(accountNumber) == 1000.00
}
}
Runs once at the start of the Specification
See also cleanup() and cleanupSpec()
Overview
Overview
Exceptions
class WhenWithdrawingFunds extends Specification {
@Shared def accountService = new AccountService()
def "withdrawing funds from a savings account"() {
given:
def accountNumber = accountService.createNewAccount(BigSaver, 1000.00)
when:
accountService.makeWithdrawal(accountNumber, 50.00,
LocalDate.now())
then:
thrown(MinimumBalanceRequiredException)
and:
accountService.getBalance(accountNumber) == 1000.00
}
}
Expect this exception to be thrown
Also, the balance should be unchanged
Overview
Overview
Exceptions
def "withdrawing funds from a savings account"() {
given:
def accountNumber = accountService.createNewAccount(BigSaver, 1000.00)
when:
accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now())
then:
MinimumBalanceRequiredException exception = thrown()
and:
exception.message == "Minimum balance for this account is €1000.00"
and:
accountService.getBalance(accountNumber) == 1000.00
}
Expect this exception to be thrown
Check exception attributes
Overview
Overview
Data-Driven
Specifications
class WhenCalculatingDepositFees extends Specification {
def “correct deposit should be calculated"() {
expect:
DepositFee.forAccountType(accountType).apply(amount) == expectedDepositFee
where:
accountType | amount | expectedDepositFee
Current | 1000.0 | 0.0
BasicSavings | 100.00 | 0.50
BigSaver | 10.00 | 0.50
BigSaver | 100.01 | 0.75
BigSaver | 1000.01 | 1.25
}
}
Use these variables in the test
Overview
Overview
Data-Driven
Specifications
class WhenCalculatingDepositFees extends Specification {
@Unroll
def “A deposit of #amount in an #accountType account"() {
expect:
DepositFee.forAccountType(accountType).apply(amount) == expectedDepositFee
where:
accountType | amount | expectedDepositFee
Current | 1000.0 | 0.0
BasicSavings | 100.00 | 0.50
BigSaver | 10.00 | 0.50
BigSaver | 100.01 | 0.75
BigSaver | 1000.01 | 1.25
}
}
Table variables can be placed in the test title
Report a separate test for each row of data
Overview
Overview
Test Doubles
✓ Test Doubles
✓ Stand-ins for dependencies
✓ Transparently replace objects used by 

the class under test
✓ Make tests faster and easier to write
Overview
Overview
Test Doubles
✓ Test Doubles stand in for objects that are
✓ Unavailable or unfinished
✓ Slow
✓ Needs something that is unavailable
✓ Hard to instantiate
Overview
Overview
Test Doubles A complex remote service
Overview
Overview
Test Doubles def "should apply correct discount for a valid discount code"() {
given:
PriceService priceService = ???
OrderProcessor processor = new OrderProcessor(priceService);
and:
def mouse = new Product("Wireless Mouse", 20.00);
def tenPercentOffPrice = 18.00;
when:
def order = ProductOrder.discountedOrder(mouse, “MINUS_10_PERCENT");
def discountedPrice = processor.calculateTotalPriceFor(order)
then:
discountedPrice == tenPercentOffPrice;
}
How do we get a PriceService?
Overview
Overview
Test Doubles class PriceServiceTestDouble extends PriceService {
private final double discount;
TestPriceService(double discount) {
this.discount = discount;
}
@Override
public double percentageDiscountForCode(String discountCode) {
return discount;
}
}
A test double
Overview
Overview
Test Doubles def "should apply correct discount for a valid discount code"() {
given:
PriceService priceService = new PriceServiceTestDouble(0.20)
OrderProcessor processor = new OrderProcessor(priceService);
and:
def mouse = new Product("Wireless Mouse", 20.00);
def tenPercentOffPrice = 18.00;
when:
def order = ProductOrder.discountedOrder(mouse, “MINUS_10_PERCENT");
def discountedPrice = processor.calculateTotalPriceFor(order)
then:
discountedPrice == tenPercentOffPrice;
}
Now use the test double
Overview
Overview
Test Doubles
✓ There are several types of Test Doubles
✓ Stubs
✓ Fakes
✓ Mocks
Overview
Overview
Test Doubles
✓ Stubs
✓ Minimal implementation
✓ Returns hard-coded values
✓ State-based testing
class PriceServiceTestDouble extends PriceService {
@Override
public double percentageDiscountForCode(String discountCode) {
return 10;
}
}
Overview
Overview
Test Doubles
✓ Fakes
✓ Smarter stubs
✓ Some simple behaviour
✓ State-based testing
public class MockEnvironmentVariables implements EnvironmentVariables {
private Properties properties = new Properties();
public String getProperty(String name) {
return properties.getProperty(name);
}
public String getProperty(String name, String defaultValue) {
return properties.getProperty(name, defaultValue);
}
public void setProperty(String name, String value) {
properties.setProperty(name, value);
}
public void setValue(String name, String value) {
values.setProperty(name, value);
}
}
Overview
Overview
Test Doubles
✓ Mocks
✓ Sophisticated stubs
✓ Record and verify interactions
✓ Need a mocking framework
Overview
Overview
Test Doubles
✓ Mocks
✓ Only mock what you own
✓ Verify specification, not implementation
✓ Specify as little as possible in a test
✓ Only mock your immediate neighbours
✓ Don’t mock boundary objects
✓ Don’t mock domain objects
✓ Keep it simple
Overview
Overview
Test Doubles
in Spock
def vatService = Mock(VATService)
def seller = new Seller(vatService);
def “VAT should apply on ordinary articles"() {
given: "the VAT rate for shirts is 20%"
seller = new Seller(vatService);
vatService.getRateFor("shirt") >> 0.2
and: "we are selling a shirt"
def sale = seller.sells(1, "shirt").forANetPriceOf(10.00)
when: "we calculate the price including VAT"
def totalPrice = sale.totalPrice
then: "the price should include GST of 20%"
totalPrice == 12.00
}
The seller thinks he is using a real VATService
Create a mocked version of the VATService class
Stubbed return value for the getRateFor() method
Overview
Overview
Test Doubles
in Spock
def vatService = Mock(VATService)
…
VATService vatService = Mock()
You can create a mock object in two ways
(This way is more IDE-friendly)
def vatService = Mock(VATService)
…
VATService vatService = Mock()
Creating Mocks
Overview
Overview
Test Doubles
in Spock
def vatService = Stub(VATService)
…
VATService vatService = Stub()
A Stub returns empty or “dummy” responses for all method calls
(This way is more IDE-friendly)
Creating Stubs
Overview
Overview
Test Doubles
in Spock
vatService.getRateFor("shirt") >> 0.2
Mock the result of a particular method call
Return different values on successive calls
vatService.getRateFor("shirt") >>> [0.2, 0.1]
vatService.getRateFor("shirt") >>
{ throw new UnknownProductException()}
Do something in a closure
Mocking interactions
VATService vatService = Mock() {
getRateFor("shirt") >> 0.2
getRateFor("banana") >> 0.1
}
Mock the interactions at creation time
Overview
Overview
Test Doubles
in Spock
def "The VAT Service should be used to obtain VAT values"() {
given: "the GST rate for shirts is 10%"
seller = new Seller(vatService);
vatService.getRateFor("shirt") >> 0.1
when: "we sell a shirt"
seller.sells(1, "shirt").forANetPriceOf(10.00)
then: "the VAT service should be used to determine the GST rate"
1 * vatService.getRateFor("shirt")
}
This method should be called exactly once
Checking interactions
Overview
Overview
Interactions in
Spock
1 * vatService.getRateFor("shirt") // Exactly once with this parameter
(1.._) * vatService.getRateFor("shirt") // At least once
(_..2) * vatService.getRateFor("shirt") // No more than twice
vatService.getRateFor(_) // Called with any parameter
vatService.getRateFor({it != "banana"}) // Custom constraint
Checking interactions
Overview
Overview
Documentation
def "withdrawing funds from a current account"() {
given: "a current account with €100"
def accountNumber = accountService.createNewAccount(Current, 100.00)
when: "we withdraw €50"
accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now())
then: "the balance should be €50"
accountService.getBalance(accountNumber) == 50.00
}
Descriptive texts go after the labels
Thank You!
AUTHOR OF ‘BDD IN ACTION’
@wakaleo
www.johnfergusonsmart.com
reachme@johnfergusonsmart.com

More Related Content

What's hot

Non-blocking Michael-Scott queue algorithm
Non-blocking Michael-Scott queue algorithmNon-blocking Michael-Scott queue algorithm
Non-blocking Michael-Scott queue algorithmAlexey Fyodorov
 
7. 게임 스트리밍 서비스를 위한 아키텍처 - 언리얼 엔진을 중심으로! [레벨 300] - 발표자: 하흥수, 솔루션즈 아키텍트, AWS :...
7.	게임 스트리밍 서비스를 위한 아키텍처 - 언리얼 엔진을 중심으로! [레벨 300] - 발표자: 하흥수, 솔루션즈 아키텍트, AWS :...7.	게임 스트리밍 서비스를 위한 아키텍처 - 언리얼 엔진을 중심으로! [레벨 300] - 발표자: 하흥수, 솔루션즈 아키텍트, AWS :...
7. 게임 스트리밍 서비스를 위한 아키텍처 - 언리얼 엔진을 중심으로! [레벨 300] - 발표자: 하흥수, 솔루션즈 아키텍트, AWS :...Amazon Web Services Korea
 
Micro Service Architecture의 이해
Micro Service Architecture의 이해Micro Service Architecture의 이해
Micro Service Architecture의 이해Terry Cho
 
Shift: Real World Migration from MongoDB to Cassandra
Shift: Real World Migration from MongoDB to CassandraShift: Real World Migration from MongoDB to Cassandra
Shift: Real World Migration from MongoDB to CassandraDataStax
 
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdf
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdfDevFest 2022 - Skaffold 2 Deep Dive Taipei.pdf
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdfKAI CHU CHUNG
 
A visual introduction to Event Sourcing and CQRS
A visual introduction to Event Sourcing and CQRSA visual introduction to Event Sourcing and CQRS
A visual introduction to Event Sourcing and CQRSLorenzo Nicora
 
우아한 모노리스
우아한 모노리스우아한 모노리스
우아한 모노리스Arawn Park
 
서비스 모니터링 구현 사례 공유 - Realtime log monitoring platform-PMon을 ...
서비스 모니터링 구현 사례 공유 - Realtime log monitoring platform-PMon을 ...서비스 모니터링 구현 사례 공유 - Realtime log monitoring platform-PMon을 ...
서비스 모니터링 구현 사례 공유 - Realtime log monitoring platform-PMon을 ...Jemin Huh
 
Microservices Architecture for e-Commerce
Microservices Architecture for e-CommerceMicroservices Architecture for e-Commerce
Microservices Architecture for e-CommerceDivante
 
삶이편해지는_백엔드_개발자_지식.pdf
삶이편해지는_백엔드_개발자_지식.pdf삶이편해지는_백엔드_개발자_지식.pdf
삶이편해지는_백엔드_개발자_지식.pdfSeung kyoo Park
 
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 SangIn Choung
 
Authenticating Angular Apps with JWT
Authenticating Angular Apps with JWTAuthenticating Angular Apps with JWT
Authenticating Angular Apps with JWTJennifer Estrada
 
소프트웨어 부트캠프 설계 및 운영사례(42Seoul)
소프트웨어 부트캠프 설계 및 운영사례(42Seoul)소프트웨어 부트캠프 설계 및 운영사례(42Seoul)
소프트웨어 부트캠프 설계 및 운영사례(42Seoul)수보 김
 
[MLOps KR 행사] MLOps 춘추 전국 시대 정리(210605)
[MLOps KR 행사] MLOps 춘추 전국 시대 정리(210605)[MLOps KR 행사] MLOps 춘추 전국 시대 정리(210605)
[MLOps KR 행사] MLOps 춘추 전국 시대 정리(210605)Seongyun Byeon
 
An Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
An Introduction to JUnit 5 and how to use it with Spring boot tests and MockitoAn Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
An Introduction to JUnit 5 and how to use it with Spring boot tests and Mockitoshaunthomas999
 
Integration Testing with a Citrus twist
Integration Testing with a Citrus twistIntegration Testing with a Citrus twist
Integration Testing with a Citrus twistchristophd
 

What's hot (20)

Non-blocking Michael-Scott queue algorithm
Non-blocking Michael-Scott queue algorithmNon-blocking Michael-Scott queue algorithm
Non-blocking Michael-Scott queue algorithm
 
7. 게임 스트리밍 서비스를 위한 아키텍처 - 언리얼 엔진을 중심으로! [레벨 300] - 발표자: 하흥수, 솔루션즈 아키텍트, AWS :...
7.	게임 스트리밍 서비스를 위한 아키텍처 - 언리얼 엔진을 중심으로! [레벨 300] - 발표자: 하흥수, 솔루션즈 아키텍트, AWS :...7.	게임 스트리밍 서비스를 위한 아키텍처 - 언리얼 엔진을 중심으로! [레벨 300] - 발표자: 하흥수, 솔루션즈 아키텍트, AWS :...
7. 게임 스트리밍 서비스를 위한 아키텍처 - 언리얼 엔진을 중심으로! [레벨 300] - 발표자: 하흥수, 솔루션즈 아키텍트, AWS :...
 
Micro Service Architecture의 이해
Micro Service Architecture의 이해Micro Service Architecture의 이해
Micro Service Architecture의 이해
 
Shift: Real World Migration from MongoDB to Cassandra
Shift: Real World Migration from MongoDB to CassandraShift: Real World Migration from MongoDB to Cassandra
Shift: Real World Migration from MongoDB to Cassandra
 
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdf
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdfDevFest 2022 - Skaffold 2 Deep Dive Taipei.pdf
DevFest 2022 - Skaffold 2 Deep Dive Taipei.pdf
 
A visual introduction to Event Sourcing and CQRS
A visual introduction to Event Sourcing and CQRSA visual introduction to Event Sourcing and CQRS
A visual introduction to Event Sourcing and CQRS
 
Présentation Angular 2
Présentation Angular 2 Présentation Angular 2
Présentation Angular 2
 
우아한 모노리스
우아한 모노리스우아한 모노리스
우아한 모노리스
 
서비스 모니터링 구현 사례 공유 - Realtime log monitoring platform-PMon을 ...
서비스 모니터링 구현 사례 공유 - Realtime log monitoring platform-PMon을 ...서비스 모니터링 구현 사례 공유 - Realtime log monitoring platform-PMon을 ...
서비스 모니터링 구현 사례 공유 - Realtime log monitoring platform-PMon을 ...
 
Microservices Architecture for e-Commerce
Microservices Architecture for e-CommerceMicroservices Architecture for e-Commerce
Microservices Architecture for e-Commerce
 
삶이편해지는_백엔드_개발자_지식.pdf
삶이편해지는_백엔드_개발자_지식.pdf삶이편해지는_백엔드_개발자_지식.pdf
삶이편해지는_백엔드_개발자_지식.pdf
 
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
 
RxSwift to Combine
RxSwift to CombineRxSwift to Combine
RxSwift to Combine
 
Angular Observables & RxJS Introduction
Angular Observables & RxJS IntroductionAngular Observables & RxJS Introduction
Angular Observables & RxJS Introduction
 
Authenticating Angular Apps with JWT
Authenticating Angular Apps with JWTAuthenticating Angular Apps with JWT
Authenticating Angular Apps with JWT
 
Introduction à Angular 2
Introduction à Angular 2Introduction à Angular 2
Introduction à Angular 2
 
소프트웨어 부트캠프 설계 및 운영사례(42Seoul)
소프트웨어 부트캠프 설계 및 운영사례(42Seoul)소프트웨어 부트캠프 설계 및 운영사례(42Seoul)
소프트웨어 부트캠프 설계 및 운영사례(42Seoul)
 
[MLOps KR 행사] MLOps 춘추 전국 시대 정리(210605)
[MLOps KR 행사] MLOps 춘추 전국 시대 정리(210605)[MLOps KR 행사] MLOps 춘추 전국 시대 정리(210605)
[MLOps KR 행사] MLOps 춘추 전국 시대 정리(210605)
 
An Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
An Introduction to JUnit 5 and how to use it with Spring boot tests and MockitoAn Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
An Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
 
Integration Testing with a Citrus twist
Integration Testing with a Citrus twistIntegration Testing with a Citrus twist
Integration Testing with a Citrus twist
 

Similar to Cucumber and Spock Primer

Driving Design through Examples
Driving Design through ExamplesDriving Design through Examples
Driving Design through ExamplesCiaranMcNulty
 
Driving Design through Examples
Driving Design through ExamplesDriving Design through Examples
Driving Design through ExamplesCiaranMcNulty
 
Driving Design through Examples
Driving Design through ExamplesDriving Design through Examples
Driving Design through ExamplesCiaranMcNulty
 
Driving Design through Examples - PhpCon PL 2015
Driving Design through Examples - PhpCon PL 2015Driving Design through Examples - PhpCon PL 2015
Driving Design through Examples - PhpCon PL 2015CiaranMcNulty
 
Patterns and practices for real-world event-driven microservices by Rachel Re...
Patterns and practices for real-world event-driven microservices by Rachel Re...Patterns and practices for real-world event-driven microservices by Rachel Re...
Patterns and practices for real-world event-driven microservices by Rachel Re...Codemotion Dubai
 
Patterns and practices for real-world event-driven microservices
Patterns and practices for real-world event-driven microservicesPatterns and practices for real-world event-driven microservices
Patterns and practices for real-world event-driven microservicesRachel Reese
 
Deep Dive Into Swift
Deep Dive Into SwiftDeep Dive Into Swift
Deep Dive Into SwiftSarath C
 
Critical software developement
Critical software developementCritical software developement
Critical software developementnedseb
 
Data dictionary, domain modelling and making things easy
Data dictionary, domain modelling and making things easyData dictionary, domain modelling and making things easy
Data dictionary, domain modelling and making things easyLockheed-Martin
 
OOPS using C++
OOPS using C++OOPS using C++
OOPS using C++cpjcollege
 
Pricing Analytics: Segmenting Customers To Maximize Revenue
Pricing Analytics: Segmenting Customers To Maximize RevenuePricing Analytics: Segmenting Customers To Maximize Revenue
Pricing Analytics: Segmenting Customers To Maximize RevenueMichael Lamont
 
Code is not text! How graph technologies can help us to understand our code b...
Code is not text! How graph technologies can help us to understand our code b...Code is not text! How graph technologies can help us to understand our code b...
Code is not text! How graph technologies can help us to understand our code b...Andreas Dewes
 
Refactor your Specs - 2017 Edition
Refactor your Specs - 2017 EditionRefactor your Specs - 2017 Edition
Refactor your Specs - 2017 EditionCyrille Martraire
 
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...apidays
 
Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)James Titcumb
 
Week 1 AssignmentCIS290v61University of Phoenix Materia.docx
Week 1 AssignmentCIS290v61University of Phoenix Materia.docxWeek 1 AssignmentCIS290v61University of Phoenix Materia.docx
Week 1 AssignmentCIS290v61University of Phoenix Materia.docxcelenarouzie
 

Similar to Cucumber and Spock Primer (20)

Driving Design through Examples
Driving Design through ExamplesDriving Design through Examples
Driving Design through Examples
 
Driving Design through Examples
Driving Design through ExamplesDriving Design through Examples
Driving Design through Examples
 
Driving Design through Examples
Driving Design through ExamplesDriving Design through Examples
Driving Design through Examples
 
Driving Design through Examples - PhpCon PL 2015
Driving Design through Examples - PhpCon PL 2015Driving Design through Examples - PhpCon PL 2015
Driving Design through Examples - PhpCon PL 2015
 
Patterns and practices for real-world event-driven microservices by Rachel Re...
Patterns and practices for real-world event-driven microservices by Rachel Re...Patterns and practices for real-world event-driven microservices by Rachel Re...
Patterns and practices for real-world event-driven microservices by Rachel Re...
 
Patterns and practices for real-world event-driven microservices
Patterns and practices for real-world event-driven microservicesPatterns and practices for real-world event-driven microservices
Patterns and practices for real-world event-driven microservices
 
Lecture 1
Lecture 1Lecture 1
Lecture 1
 
Deep Dive Into Swift
Deep Dive Into SwiftDeep Dive Into Swift
Deep Dive Into Swift
 
Critical software developement
Critical software developementCritical software developement
Critical software developement
 
Data dictionary, domain modelling and making things easy
Data dictionary, domain modelling and making things easyData dictionary, domain modelling and making things easy
Data dictionary, domain modelling and making things easy
 
OOPS using C++
OOPS using C++OOPS using C++
OOPS using C++
 
Pricing Analytics: Segmenting Customers To Maximize Revenue
Pricing Analytics: Segmenting Customers To Maximize RevenuePricing Analytics: Segmenting Customers To Maximize Revenue
Pricing Analytics: Segmenting Customers To Maximize Revenue
 
Code is not text! How graph technologies can help us to understand our code b...
Code is not text! How graph technologies can help us to understand our code b...Code is not text! How graph technologies can help us to understand our code b...
Code is not text! How graph technologies can help us to understand our code b...
 
Refactor your Specs - 2017 Edition
Refactor your Specs - 2017 EditionRefactor your Specs - 2017 Edition
Refactor your Specs - 2017 Edition
 
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
 
Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)
 
C++ functions
C++ functionsC++ functions
C++ functions
 
C++ functions
C++ functionsC++ functions
C++ functions
 
Week 1 AssignmentCIS290v61University of Phoenix Materia.docx
Week 1 AssignmentCIS290v61University of Phoenix Materia.docxWeek 1 AssignmentCIS290v61University of Phoenix Materia.docx
Week 1 AssignmentCIS290v61University of Phoenix Materia.docx
 
c++ referesher 1.pdf
c++ referesher 1.pdfc++ referesher 1.pdf
c++ referesher 1.pdf
 

More from John Ferguson Smart Limited

My Reading Specs - Refactoring Patterns for Gherkin Scenarios
My Reading Specs - Refactoring Patterns for Gherkin ScenariosMy Reading Specs - Refactoring Patterns for Gherkin Scenarios
My Reading Specs - Refactoring Patterns for Gherkin ScenariosJohn Ferguson Smart Limited
 
Artisti e Condotierri - How can your team become artists of the 21st century ...
Artisti e Condotierri - How can your team become artists of the 21st century ...Artisti e Condotierri - How can your team become artists of the 21st century ...
Artisti e Condotierri - How can your team become artists of the 21st century ...John Ferguson Smart Limited
 
Engage! Bringing teams together to deliver software that makes a difference
Engage! Bringing teams together to deliver software that makes a differenceEngage! Bringing teams together to deliver software that makes a difference
Engage! Bringing teams together to deliver software that makes a differenceJohn Ferguson Smart Limited
 
Sustainable Test Automation with Serenity BDD and Screenplay
Sustainable Test Automation with Serenity BDD and ScreenplaySustainable Test Automation with Serenity BDD and Screenplay
Sustainable Test Automation with Serenity BDD and ScreenplayJohn Ferguson Smart Limited
 
Engage! Bringing teams together to deliver software that makes a difference
Engage! Bringing teams together to deliver software that makes a differenceEngage! Bringing teams together to deliver software that makes a difference
Engage! Bringing teams together to deliver software that makes a differenceJohn Ferguson Smart Limited
 
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...John Ferguson Smart Limited
 
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...John Ferguson Smart Limited
 
Screenplay - Next generation automated acceptance testing
Screenplay - Next generation automated acceptance testingScreenplay - Next generation automated acceptance testing
Screenplay - Next generation automated acceptance testingJohn Ferguson Smart Limited
 
All the world's a stage – the next step in automated testing practices
All the world's a stage – the next step in automated testing practicesAll the world's a stage – the next step in automated testing practices
All the world's a stage – the next step in automated testing practicesJohn Ferguson Smart Limited
 
It's Testing, Jim, but not as we know it - BDD for Testers
It's Testing, Jim, but not as we know it - BDD for TestersIt's Testing, Jim, but not as we know it - BDD for Testers
It's Testing, Jim, but not as we know it - BDD for TestersJohn Ferguson Smart Limited
 
BDD in Action - Automated Web Testing with WebDriver and Serenity
BDD in Action - Automated Web Testing with WebDriver and SerenityBDD in Action - Automated Web Testing with WebDriver and Serenity
BDD in Action - Automated Web Testing with WebDriver and SerenityJohn Ferguson Smart Limited
 

More from John Ferguson Smart Limited (20)

My Reading Specs - Refactoring Patterns for Gherkin Scenarios
My Reading Specs - Refactoring Patterns for Gherkin ScenariosMy Reading Specs - Refactoring Patterns for Gherkin Scenarios
My Reading Specs - Refactoring Patterns for Gherkin Scenarios
 
Artisti e Condotierri - How can your team become artists of the 21st century ...
Artisti e Condotierri - How can your team become artists of the 21st century ...Artisti e Condotierri - How can your team become artists of the 21st century ...
Artisti e Condotierri - How can your team become artists of the 21st century ...
 
Engage! Bringing teams together to deliver software that makes a difference
Engage! Bringing teams together to deliver software that makes a differenceEngage! Bringing teams together to deliver software that makes a difference
Engage! Bringing teams together to deliver software that makes a difference
 
BE A POD OF DOLPHINS, NOT A DANCING ELEPHANT
BE A POD OF DOLPHINS, NOT A DANCING ELEPHANTBE A POD OF DOLPHINS, NOT A DANCING ELEPHANT
BE A POD OF DOLPHINS, NOT A DANCING ELEPHANT
 
Sustainable Test Automation with Serenity BDD and Screenplay
Sustainable Test Automation with Serenity BDD and ScreenplaySustainable Test Automation with Serenity BDD and Screenplay
Sustainable Test Automation with Serenity BDD and Screenplay
 
Engage! Bringing teams together to deliver software that makes a difference
Engage! Bringing teams together to deliver software that makes a differenceEngage! Bringing teams together to deliver software that makes a difference
Engage! Bringing teams together to deliver software that makes a difference
 
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
 
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
 
Shift left-devoxx-pl
Shift left-devoxx-plShift left-devoxx-pl
Shift left-devoxx-pl
 
Screenplay - Next generation automated acceptance testing
Screenplay - Next generation automated acceptance testingScreenplay - Next generation automated acceptance testing
Screenplay - Next generation automated acceptance testing
 
All the world's a stage – the next step in automated testing practices
All the world's a stage – the next step in automated testing practicesAll the world's a stage – the next step in automated testing practices
All the world's a stage – the next step in automated testing practices
 
CukeUp 2016 Agile Product Planning Workshop
CukeUp 2016 Agile Product Planning WorkshopCukeUp 2016 Agile Product Planning Workshop
CukeUp 2016 Agile Product Planning Workshop
 
BDD Anti-patterns
BDD Anti-patternsBDD Anti-patterns
BDD Anti-patterns
 
Serenity and the Journey Pattern
Serenity and the Journey PatternSerenity and the Journey Pattern
Serenity and the Journey Pattern
 
BDD - Collaborate like you mean it!
BDD - Collaborate like you mean it!BDD - Collaborate like you mean it!
BDD - Collaborate like you mean it!
 
BDD-Driven Microservices
BDD-Driven MicroservicesBDD-Driven Microservices
BDD-Driven Microservices
 
BDD Anti-patterns
BDD Anti-patternsBDD Anti-patterns
BDD Anti-patterns
 
It's Testing, Jim, but not as we know it - BDD for Testers
It's Testing, Jim, but not as we know it - BDD for TestersIt's Testing, Jim, but not as we know it - BDD for Testers
It's Testing, Jim, but not as we know it - BDD for Testers
 
BDD in Action - Automated Web Testing with WebDriver and Serenity
BDD in Action - Automated Web Testing with WebDriver and SerenityBDD in Action - Automated Web Testing with WebDriver and Serenity
BDD in Action - Automated Web Testing with WebDriver and Serenity
 
BDD in Action - Devoxx 2014
BDD in Action - Devoxx 2014BDD in Action - Devoxx 2014
BDD in Action - Devoxx 2014
 

Recently uploaded

Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningVitsRangannavar
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?Watsoo Telematics
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsMehedi Hasan Shohan
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 

Recently uploaded (20)

Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learning
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software Solutions
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 

Cucumber and Spock Primer

  • 1. Cucumber and Spock Primer BDD Masterclass Building software that makes a difference, and building it well @wakaleo www.johnfergusonsmart.com reachme@johnfergusonsmart.com
  • 3. Overview Overview Basic Gherkin Feature: Earning Frequent Flyer points through flights Scenario: Economy flights earn points by distance Given the distance from London to Paris is 344 km When I fly from London to Paris in Economy Then I should earn 344 points A feature represents a deliverable piece of functionality Each feature should have a title A feature contains one or more scenarios Features and Scenarios
  • 4. Overview Overview Basic Gherkin Feature: Earning Frequent Flyer points through flights In order to encourage repeat business As an Airline Sales Manager I want customers to be able to cumulate points when they fly with us Scenario: Economy flights earn points by distance Economy class earns 1 point per kilometre Given the distance from London to Paris is 344 km When I fly from London to Paris in Economy Then I should earn 344 points Free-text description 
 (great for living documentation) You can also put a description for a Scenario Free text descriptions
  • 5. Overview Overview Basic Gherkin Scenario: Economy flights earn points by distance Economy class earns 1 point per kilometre Given the distance from London to Paris is 344 km When I fly from London to Paris in Economy Then I should earn 344 points GIVEN: Preconditions WHEN: Action to illustrate THEN: Expected outcome Scenarios
  • 6. Overview Overview Basic Gherkin Scenario: Economy flights over several legs Given the distance from London to Paris is 344 km And the distance from Paris to Krakow is 1500 km When I fly from London to Krakow via Paris in Economy Then I should earn 1844 points And I should earn 18 status points Multiple preconditions Scenarios Multiple outcomes
  • 7. Overview Overview Basic Gherkin Given steps ✓ Defines preconditions and context ✓ Typically something that happened in the past ✓ Can interact with the system ✓ Should not perform any actions being tested by the scenario Given a user registers on the site And the user logs in When the home page appears Then the user’s name should be visible Given a user has registered on the site When the user logs in Then the user’s name should be visible on the home page What are we testing here?
  • 8. Overview Overview Basic Gherkin When steps ✓ The action under test ✓ Avoid chaining too many clauses Given a user has registered on the site When the user enters 'Scott' in the user name And the user enters 'Tiger' in the password And the user selects 'UK' as the country And the user clicks on the Login button And the user validates the Cookies alert Then the user’s name should be visible on the home page Too much detail To implementation-specific
  • 9. Overview Overview Basic Gherkin Then steps ✓ The expected outcome ✓ Can query the system ✓ Should not perform actions on the system Given a batch file needs to be processed When the user uploads the batch file Then the result should be visible And a notification message should be sent to the user
  • 10. Overview Overview Basic Gherkin Background steps ✓ Common steps for all the scenarios in a feature file ✓ Avoid duplication ✓ More focused scenarios Feature: Earning Frequent Flyer points through flights In order to encourage repeat business As an Airline Sales Manager I want customers to be able to cumulate points when they fly with us Background: Given the distance from London to Paris is 344 km And the distance from Paris to Krakow is 1500km Scenario: Economy flights earn points by distance When I fly from London to Paris in Economy Then I should earn 344 points And I should earn 3 status points Scenario: Economy flights over several legs When I fly from London to Krakow via Paris in Economy Then I should earn 1844 points And I should earn 18 status points
  • 11. Overview Overview Basic Gherkin Scenario Outlines ✓ Use a table to simplify duplicated but similar scenarios Background: Given the distance from London to Paris is 344 km And the distance from Paris to Krakow is 1500km And the distance from London to Budapest is 1600km Scenario: Economy flights earn points by distance When I fly from London to Paris in Economy Then I should earn 344 points And I should earn 3 status points Scenario: Economy flights to Krakow When I fly from London to Krakow in Economy Then I should earn 1500 points And I should earn 15 status points Scenario: Economy flights to Budapest When I fly from London to Budapest in Economy Then I should earn 1600 points And I should earn 16 status points
  • 12. Overview Overview Basic Gherkin Scenario Outlines ✓ Use a table to simplify duplicated but similar scenarios Background: Given the distance from London to Paris is 344 km And the distance from Paris to Krakow is 1500km And the distance from London to Budapest is 1600km Scenario Outline: When I fly from <departure> to <destination> in Economy Then I should earn <points> points And I should earn <status-points> status points Examples: | departure | destination | points | status-points | | London | Paris | 344 | 3 | | Paris | Krakow | 1500 | 15 | | London | Budapest | 1600 | 16 |
  • 13. Overview Overview Basic Gherkin Embedded tables ✓ Use tables in steps to pass tabular data to the step Scenario: Deposit into a current account Given Joe has the following accounts: | Number | Type | Balance | | 123456 | Current | 1000 | When he deposits €100 into his Current account Then he should have the following balances: | Number | Type | Balance | | 123456 | Current | 1100 |
  • 14. Overview Overview Basic Gherkin Embedded tables ✓ Use tables in steps to pass tabular data to the step Feature: Earning Frequent Flyer points through flights In order to encourage repeat business As an Airline Sales Manager I want customers to be able to cumulate points when they fly with us Background: Given the following flight routes: | departure | destination | distance | | London | Paris | 344 | | Paris | Krakow | 1500 | | London | Budapest | 1600 | Scenario Outline: When I fly from <departure> to <destination> in Economy Then I should earn <points> points And I should earn <status-points> status points Examples: | departure | destination | points | status-points | | London | Paris | 344 | 3 | | Paris | Krakow | 1500 | 15 | | London | Budapest | 1600 | 16 |
  • 15. Overview Overview Basic Gherkin Multi-line string parameters ✓ Pass in multi-line strings as parameters Given a travel provides feedback about the flight """ It was OK The food was rubbish but the staff were nice The flight was delayed by 15 minutes """
  • 17. Step Definitions in Java with Cucumber and Serenity BDD The Cucumber Test Runner import cucumber.api.CucumberOptions; import net.serenitybdd.cucumber.CucumberWithSerenity; import org.junit.runner.RunWith; @RunWith(CucumberWithSerenity.class) @CucumberOptions(features = "src/test/resources/features/deposit_funds", glue = "com.bddinaction.serenitybank") public class DepositFunds {} A Cucumber test runner Which feature files to run Where to find the step definition classes
  • 18. Step Definitions in Java with Cucumber and Serenity BDD Step Definitions Feature: Earning Frequent Flyer points through flights Scenario: Economy flights earn points by distance Given the distance from London to Paris is 344 km When I fly from London to Paris in Economy Then I should earn 344 points @Given("^the distance from (.*) to (.*) is (d+) km$") public void pointsEarnedBetweenCities(String departure, String destination, int distance) throws Throwable { } @Given, @When, or @Then annotation Matching regular expression Matched expressions are passed in as parameters
  • 19. Step Definitions in Java with Cucumber and Serenity BDD Matching Lists Given the following possible destinations: London, Paris, Amsterdam @Given("^the following possible destinations: (.*)$") public void theFollowingPossibleDestinations(List<String> destinations) { } Declare a list of Strings Given the following possible destinations: | London | | Paris | | Amsterdam | alternative notation
  • 20. Step Definitions in Java with Cucumber and Serenity BDD Matching enums When I fly from London to Paris in Economy public enum City { London, Paris, Amsterdam } public enum CabinClass { Economy, Business, First } @When("^I fly from (.*) to (.*) in (.*)$") public void iFly(City departure, City destination, CabinClass cabinClass){ } Enums are matched automatically
  • 21. Step Definitions in Java with Cucumber and Serenity BDD Matching tables Given the following flight routes: | departure | destination | distance | | London | Paris | 344 | | Paris | Krakow | 1500 | | London | Budapest | 1600 | public void flightRoutes(Map<String, String> flightRoutes) {} Tables can be passed as a map of Strings
  • 22. Step Definitions in Java with Cucumber and Serenity BDD Transformers When I fly from San Francisco to Paris in Economy public enum City { London("London"), Paris("Paris"), SanFrancisco("San Francisco"), SaintPetersbuug("St Petersburg"); public final String name; City(String name) { this.name = name; } } @When("^I fly from (.*) to (.*) in (.*)$") public void iFly(@Transform(CityConverter.class) City departure, @Transform(CityConverter.class) City destination, CabinClass cabinClass) {} public class CityConverter extends Transformer<City> { @Override public City transform(String cityName) { return Arrays.stream(City.values()) .filter(city -> city.name.equalsIgnoreCase(cityName)) .findFirst() .orElseThrow(() -> new UnknownCityException(cityName)); } }
  • 23. BDD Unit Testing with Spock
  • 24. Overview Overview Introduction to Spock http://spockframework.org/ import spock.lang.Specification class WhenManagingAnAccount extends Specification { def "depositing a sum into the account should update the balance"() { given: def currentAccount = new BankAccount("123456", AccountType.Current) when: currentAccount.deposit(1000) then: currentAccount.balance == 1000 } } All Spock tests extend Specification Plain English test names Arrange Act Assert Acts as an assertion
  • 25. Overview Overview Using Fields class WhenWithdrawingFunds extends Specification { def accountService = new AccountService(); def "withdrawing funds from a current account"() { given: def accountNumber = accountService.createNewAccount(Current, 100.00) when: accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: accountService.getBalance(accountNumber) == 50.00 } def "withdrawing funds from a savings account"() { given: def accountNumber = accountService.createNewAccount(BigSaver, 1000.00) when: accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: thrown(MinimumBalanceRequiredException) and: accountService.getBalance(accountNumber) == 1000.00 } } Instantiated once before each test
  • 26. Overview Overview Using Fields class WhenWithdrawingFunds extends Specification { @Shared def accountService = new AccountService() def "withdrawing funds from a current account"() { given: def accountNumber = accountService.createNewAccount(Current, 100.00) when: accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: accountService.getBalance(accountNumber) == 50.00 } def "withdrawing funds from a savings account"() { given: def accountNumber = accountService.createNewAccount(BigSaver, 1000.00) when: accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: thrown(MinimumBalanceRequiredException) and: accountService.getBalance(accountNumber) == 1000.00 } } Instantiated once and shared between the tests
  • 27. Overview Overview Using Fields class WhenWithdrawingFunds extends Specification { def accountService def setup() { accountService = new AccountService() } def "withdrawing funds from a current account"() { given: def accountNumber = accountService.createNewAccount(Current, 100.00) when: accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: accountService.getBalance(accountNumber) == 50.00 } def "withdrawing funds from a savings account"() { given: def accountNumber = accountService.createNewAccount(BigSaver, 1000.00) when: accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: thrown(MinimumBalanceRequiredException) and: accountService.getBalance(accountNumber) == 1000.00 } } Runs before each test
  • 28. Overview Overview Using Fields class WhenWithdrawingFunds extends Specification { @Shared def accountService = new AccountService() def setupSpec() { accountService = new AccountService() } def "withdrawing funds from a current account"() { given: def accountNumber = accountService.createNewAccount(Current, 100.00) when: accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: accountService.getBalance(accountNumber) == 50.00 } def "withdrawing funds from a savings account"() { given: def accountNumber = accountService.createNewAccount(BigSaver, 1000.00) when: accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: thrown(MinimumBalanceRequiredException) and: accountService.getBalance(accountNumber) == 1000.00 } } Runs once at the start of the Specification See also cleanup() and cleanupSpec()
  • 29. Overview Overview Exceptions class WhenWithdrawingFunds extends Specification { @Shared def accountService = new AccountService() def "withdrawing funds from a savings account"() { given: def accountNumber = accountService.createNewAccount(BigSaver, 1000.00) when: accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: thrown(MinimumBalanceRequiredException) and: accountService.getBalance(accountNumber) == 1000.00 } } Expect this exception to be thrown Also, the balance should be unchanged
  • 30. Overview Overview Exceptions def "withdrawing funds from a savings account"() { given: def accountNumber = accountService.createNewAccount(BigSaver, 1000.00) when: accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: MinimumBalanceRequiredException exception = thrown() and: exception.message == "Minimum balance for this account is €1000.00" and: accountService.getBalance(accountNumber) == 1000.00 } Expect this exception to be thrown Check exception attributes
  • 31. Overview Overview Data-Driven Specifications class WhenCalculatingDepositFees extends Specification { def “correct deposit should be calculated"() { expect: DepositFee.forAccountType(accountType).apply(amount) == expectedDepositFee where: accountType | amount | expectedDepositFee Current | 1000.0 | 0.0 BasicSavings | 100.00 | 0.50 BigSaver | 10.00 | 0.50 BigSaver | 100.01 | 0.75 BigSaver | 1000.01 | 1.25 } } Use these variables in the test
  • 32. Overview Overview Data-Driven Specifications class WhenCalculatingDepositFees extends Specification { @Unroll def “A deposit of #amount in an #accountType account"() { expect: DepositFee.forAccountType(accountType).apply(amount) == expectedDepositFee where: accountType | amount | expectedDepositFee Current | 1000.0 | 0.0 BasicSavings | 100.00 | 0.50 BigSaver | 10.00 | 0.50 BigSaver | 100.01 | 0.75 BigSaver | 1000.01 | 1.25 } } Table variables can be placed in the test title Report a separate test for each row of data
  • 33. Overview Overview Test Doubles ✓ Test Doubles ✓ Stand-ins for dependencies ✓ Transparently replace objects used by 
 the class under test ✓ Make tests faster and easier to write
  • 34. Overview Overview Test Doubles ✓ Test Doubles stand in for objects that are ✓ Unavailable or unfinished ✓ Slow ✓ Needs something that is unavailable ✓ Hard to instantiate
  • 35. Overview Overview Test Doubles A complex remote service
  • 36. Overview Overview Test Doubles def "should apply correct discount for a valid discount code"() { given: PriceService priceService = ??? OrderProcessor processor = new OrderProcessor(priceService); and: def mouse = new Product("Wireless Mouse", 20.00); def tenPercentOffPrice = 18.00; when: def order = ProductOrder.discountedOrder(mouse, “MINUS_10_PERCENT"); def discountedPrice = processor.calculateTotalPriceFor(order) then: discountedPrice == tenPercentOffPrice; } How do we get a PriceService?
  • 37. Overview Overview Test Doubles class PriceServiceTestDouble extends PriceService { private final double discount; TestPriceService(double discount) { this.discount = discount; } @Override public double percentageDiscountForCode(String discountCode) { return discount; } } A test double
  • 38. Overview Overview Test Doubles def "should apply correct discount for a valid discount code"() { given: PriceService priceService = new PriceServiceTestDouble(0.20) OrderProcessor processor = new OrderProcessor(priceService); and: def mouse = new Product("Wireless Mouse", 20.00); def tenPercentOffPrice = 18.00; when: def order = ProductOrder.discountedOrder(mouse, “MINUS_10_PERCENT"); def discountedPrice = processor.calculateTotalPriceFor(order) then: discountedPrice == tenPercentOffPrice; } Now use the test double
  • 39. Overview Overview Test Doubles ✓ There are several types of Test Doubles ✓ Stubs ✓ Fakes ✓ Mocks
  • 40. Overview Overview Test Doubles ✓ Stubs ✓ Minimal implementation ✓ Returns hard-coded values ✓ State-based testing class PriceServiceTestDouble extends PriceService { @Override public double percentageDiscountForCode(String discountCode) { return 10; } }
  • 41. Overview Overview Test Doubles ✓ Fakes ✓ Smarter stubs ✓ Some simple behaviour ✓ State-based testing public class MockEnvironmentVariables implements EnvironmentVariables { private Properties properties = new Properties(); public String getProperty(String name) { return properties.getProperty(name); } public String getProperty(String name, String defaultValue) { return properties.getProperty(name, defaultValue); } public void setProperty(String name, String value) { properties.setProperty(name, value); } public void setValue(String name, String value) { values.setProperty(name, value); } }
  • 42. Overview Overview Test Doubles ✓ Mocks ✓ Sophisticated stubs ✓ Record and verify interactions ✓ Need a mocking framework
  • 43. Overview Overview Test Doubles ✓ Mocks ✓ Only mock what you own ✓ Verify specification, not implementation ✓ Specify as little as possible in a test ✓ Only mock your immediate neighbours ✓ Don’t mock boundary objects ✓ Don’t mock domain objects ✓ Keep it simple
  • 44. Overview Overview Test Doubles in Spock def vatService = Mock(VATService) def seller = new Seller(vatService); def “VAT should apply on ordinary articles"() { given: "the VAT rate for shirts is 20%" seller = new Seller(vatService); vatService.getRateFor("shirt") >> 0.2 and: "we are selling a shirt" def sale = seller.sells(1, "shirt").forANetPriceOf(10.00) when: "we calculate the price including VAT" def totalPrice = sale.totalPrice then: "the price should include GST of 20%" totalPrice == 12.00 } The seller thinks he is using a real VATService Create a mocked version of the VATService class Stubbed return value for the getRateFor() method
  • 45. Overview Overview Test Doubles in Spock def vatService = Mock(VATService) … VATService vatService = Mock() You can create a mock object in two ways (This way is more IDE-friendly) def vatService = Mock(VATService) … VATService vatService = Mock() Creating Mocks
  • 46. Overview Overview Test Doubles in Spock def vatService = Stub(VATService) … VATService vatService = Stub() A Stub returns empty or “dummy” responses for all method calls (This way is more IDE-friendly) Creating Stubs
  • 47. Overview Overview Test Doubles in Spock vatService.getRateFor("shirt") >> 0.2 Mock the result of a particular method call Return different values on successive calls vatService.getRateFor("shirt") >>> [0.2, 0.1] vatService.getRateFor("shirt") >> { throw new UnknownProductException()} Do something in a closure Mocking interactions VATService vatService = Mock() { getRateFor("shirt") >> 0.2 getRateFor("banana") >> 0.1 } Mock the interactions at creation time
  • 48. Overview Overview Test Doubles in Spock def "The VAT Service should be used to obtain VAT values"() { given: "the GST rate for shirts is 10%" seller = new Seller(vatService); vatService.getRateFor("shirt") >> 0.1 when: "we sell a shirt" seller.sells(1, "shirt").forANetPriceOf(10.00) then: "the VAT service should be used to determine the GST rate" 1 * vatService.getRateFor("shirt") } This method should be called exactly once Checking interactions
  • 49. Overview Overview Interactions in Spock 1 * vatService.getRateFor("shirt") // Exactly once with this parameter (1.._) * vatService.getRateFor("shirt") // At least once (_..2) * vatService.getRateFor("shirt") // No more than twice vatService.getRateFor(_) // Called with any parameter vatService.getRateFor({it != "banana"}) // Custom constraint Checking interactions
  • 50. Overview Overview Documentation def "withdrawing funds from a current account"() { given: "a current account with €100" def accountNumber = accountService.createNewAccount(Current, 100.00) when: "we withdraw €50" accountService.makeWithdrawal(accountNumber, 50.00, LocalDate.now()) then: "the balance should be €50" accountService.getBalance(accountNumber) == 50.00 } Descriptive texts go after the labels
  • 51. Thank You! AUTHOR OF ‘BDD IN ACTION’ @wakaleo www.johnfergusonsmart.com reachme@johnfergusonsmart.com