SlideShare a Scribd company logo
serenity-bdd.info#SerenityBDD @Wakaleo
Sustainable Test Automation
with Serenity BDD and Screenplay
serenity-bdd.info#SerenityBDD @Wakaleo
John Ferguson Smart
Author of ‘BDD in Action’

Lead Developer of Serenity BDD
Founder of the Serenity Dojo
serenity-bdd.info#SerenityBDD @Wakaleo
serenity-bdd.info#SerenityBDD @Wakaleo
serenity-bdd.info#SerenityBDD @Wakaleo
Want to follow along?
bit.ly/serentiy-planner
serenity-bdd.info#SerenityBDD @Wakaleo
We ❤ E2E
serenity-bdd.info#SerenityBDD @Wakaleo
We 💔 E2E
(said no one ever)
serenity-bdd.info#SerenityBDD @Wakaleo
Execution time: minutes → hours
serenity-bdd.info#SerenityBDD @Wakaleo
Execution time: minutes → hours
Writing: hours → days
serenity-bdd.info#SerenityBDD @Wakaleo
Execution time: minutes → hours
Writing: hours → days
Analysis and reporting: hours → days
serenity-bdd.info#SerenityBDD @Wakaleo
Execution time: minutes → hours
Writing: hours → days
Analysis and reporting: hours → days
Maintenance: days → weeks
serenity-bdd.info#SerenityBDD @Wakaleo
The difference between

scalable tests 

and a world of pain

is design.
serenity-bdd.info#SerenityBDD @Wakaleo
Testing the Journey Planner
#SerenityBDD @Wakaleo serenity-bdd.info
#SerenityBDD @Wakaleo serenity-bdd.info
When a commuter wants to travel 

from Waterloo to Canary Wharf 

around 9:00 AM they should be told 

about the 8:59 AM Jubilee Line train.
#SerenityBDD @Wakaleo serenity-bdd.info
Open the Journey Planner
#SerenityBDD @Wakaleo serenity-bdd.info
Open the Journey Planner

Choose origin: Waterloo
#SerenityBDD @Wakaleo serenity-bdd.info
Open the Journey Planner

Choose origin: Waterloo
Enter “Waterloo”
#SerenityBDD @Wakaleo serenity-bdd.info
Open the Journey Planner

Choose origin: Waterloo
Enter “Waterloo”
Pick the first suggestion
#SerenityBDD @Wakaleo serenity-bdd.info
Open the Journey Planner

Choose origin: Waterloo
Enter “Waterloo”
Pick the first suggestion
Wait for the suggestions
#SerenityBDD @Wakaleo serenity-bdd.info
Open the Journey Planner

Choose origin: Waterloo
Enter “Waterloo”
Pick the first suggestion
Wait for the suggestions
Press ▼
#SerenityBDD @Wakaleo serenity-bdd.info
Open the Journey Planner

Choose origin: Waterloo
Enter “Waterloo”
Pick the first suggestion
Wait for the suggestions
Press ▼

Press ↩
#SerenityBDD @Wakaleo serenity-bdd.info
Open the Journey Planner

Choose origin: Waterloo
Enter “Waterloo”
Pick the first suggestion
Wait for the suggestions
Press ▼

Press ↩
#SerenityBDD @Wakaleo serenity-bdd.info
Open the Journey Planner

Choose origin: Waterloo
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
Choose time of departure: 9:00 AM
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
Choose time of departure: 9:00 AM
Click on the “change time” link
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
Choose time of departure: 9:00 AM
Click on the “change time” link
Click on the “Leaving” button
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
Choose time of departure: 9:00 AM
Click on the “change time” link
Click on the “Leaving” button
Select “09:00”
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
Choose time of departure: 9:00 AM
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
Choose time of departure: 9:00 AM
Confirm selection
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
Choose time of departure: 9:00 AM
Confirm selection
Click on the “Plan my journey”
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
Choose time of departure: 9:00 AM
Confirm selection
Click on the “Plan my journey”
Wait for the results to load
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
Choose time of departure: 9:00 AM
Confirm selection
serenity-bdd.info#SerenityBDD @Wakaleo
Open the Journey Planner

Choose origin: Waterloo
Choose destination: Canary Wharf
Choose time of departure: 9:00 AM
Confirm selection
See a Jubilee Line train at 08:59
serenity-bdd.info#SerenityBDD @Wakaleo
At a high level,
it’s just 6 tasks
serenity-bdd.info#SerenityBDD @Wakaleo
Scripting the flow
serenity-bdd.info#SerenityBDD @Wakaleo
private final By origin = By.id("InputFrom");
private final By originSuggestions = By.cssSelector(".tt-suggestions");
private final By destination = By.id("InputTo");
private final By destinationSuggestions = By.cssSelector(".tt-suggestions");
private final By changeTimeLink = By.partialLinkText("change time");
private final By leavingButton = By.cssSelector("label[for=departing]");
private final By timeSelector = By.id("Time");
private final By planMyJourneyButton = By.cssSelector("#plan-a-journey .plan-journey-button");
private final By journeyResults = By.cssSelector(".summary-results");
private final By fastestJourney = By.cssSelector(".publictransport-box span.time");
serenity-bdd.info#SerenityBDD @Wakaleo
browser.get("https://tfl.gov.uk/");
serenity-bdd.info#SerenityBDD @Wakaleo
browser.get(“https://tfl.gov.uk/");
browser.findElement(origin).sendKeys("Waterloo");
serenity-bdd.info#SerenityBDD @Wakaleo
browser.get(“https://tfl.gov.uk/");
browser.findElement(origin).sendKeys(“Waterloo");
WebDriverWait wait = new WebDriverWait(browser, 10);
wait.until(visibilityOfElementLocated(originSuggestions));
serenity-bdd.info#SerenityBDD @Wakaleo
browser.get(“https://tfl.gov.uk/");
browser.findElement(origin).sendKeys(“Waterloo");
WebDriverWait wait = new WebDriverWait(browser, 10);
wait.until(visibilityOfElementLocated(originSuggestions));
browser.findElement(originSuggestions).sendKeys(ARROW_DOWN);
browser.findElement(originSuggestions).sendKeys(ENTER);
serenity-bdd.info#SerenityBDD @Wakaleo
browser.get(“https://tfl.gov.uk/");
browser.findElement(origin).sendKeys(“Waterloo");
WebDriverWait wait = new WebDriverWait(browser, 10);
wait.until(visibilityOfElementLocated(originSuggestions));
browser.findElement(originSuggestions).sendKeys(ARROW_DOWN);
browser.findElement(originSuggestions).sendKeys(ENTER);
browser.findElement(destination).sendKeys("Canary Wharf");
serenity-bdd.info#SerenityBDD @Wakaleo
browser.get(“https://tfl.gov.uk/");
browser.findElement(origin).sendKeys(“Waterloo");
WebDriverWait wait = new WebDriverWait(browser, 10);
wait.until(visibilityOfElementLocated(originSuggestions));
browser.findElement(originSuggestions).sendKeys(ARROW_DOWN);
browser.findElement(originSuggestions).sendKeys(ENTER);
browser.findElement(destination).sendKeys("Canary Wharf”);
wait.until(visibilityOfElementLocated(destinationSuggestions));
browser.findElement(destinationSuggestions).sendKeys(ARROW_DOWN);
browser.findElement(destinationSuggestions).sendKeys(ENTER);
serenity-bdd.info#SerenityBDD @Wakaleo
…
browser.findElement(changeTimeLink).click();
browser.findElement(leavingButton).click();
new Select(browser.findElement(timeSelector))
.selectByVisibleText("09:00");
serenity-bdd.info#SerenityBDD @Wakaleo
…
browser.findElement(changeTimeLink).click();
browser.findElement(leavingButton).click();
new Select(browser.findElement(timeSelector))
.selectByVisibleText(“09:00");
browser.findElement(planMyJourneyButton).click();
wait.until(visibilityOfElementLocated(journeyResults));
serenity-bdd.info#SerenityBDD @Wakaleo
…
String fastestDepartureTime =
startTimeOf(browser.findElement(fastestJourney).getText());
assertThat(fastestDepartureTime).isEqualTo("08:59");
serenity-bdd.info#SerenityBDD @Wakaleo
private final By origin = By.id("InputFrom");
private final By originSuggestions = By.cssSelector(".tt-suggestions");
private final By destination = By.id("InputTo");
private final By destinationSuggestions = By.cssSelector(".tt-suggestions");
private final By changeTimeLink = By.partialLinkText("change time");
private final By leavingButton = By.cssSelector("label[for=departing]");
private final By timeSelector = By.id("Time");
private final By planMyJourneyButton = By.cssSelector("#plan-a-journey .plan-journey-button");
private final By journeyResults = By.cssSelector(".summary-results");
private final By fastestJourney = By.cssSelector(".publictransport-box span.time");
private WebDriver browser;
@Before
public void openBrowser() {
browser = new FirefoxDriver();
}
@After
public void closeBrowser() {
browser.quit();
}
@Test
public void planning_a_journey() {
browser.get("https://tfl.gov.uk/");
browser.findElement(origin).sendKeys("Waterloo");
WebDriverWait wait = new WebDriverWait(browser, 10);
wait.until(visibilityOfElementLocated(originSuggestions));
browser.findElement(originSuggestions).sendKeys(ARROW_DOWN);
browser.findElement(originSuggestions).sendKeys(ENTER);
browser.findElement(destination).sendKeys("Canary Wharf");
wait.until(visibilityOfElementLocated(destinationSuggestions));
browser.findElement(destinationSuggestions).sendKeys(ARROW_DOWN);
browser.findElement(destinationSuggestions).sendKeys(ENTER);
browser.findElement(changeTimeLink).click();
browser.findElement(leavingButton).click();
new Select(browser.findElement(timeSelector)).selectByVisibleText("09:00");
browser.findElement(planMyJourneyButton).click();
wait.until(visibilityOfElementLocated(journeyResults));
String fastestDepartureTime = startTimeOf(browser.findElement(fastestJourney).getText());
6 tasks ?
serenity-bdd.info#SerenityBDD @Wakaleo
6 tasks buried in
36 lines of noise
private final By origin = By.id("InputFrom");
private final By originSuggestions = By.cssSelector(".tt-suggestions");
private final By destination = By.id("InputTo");
private final By destinationSuggestions = By.cssSelector(".tt-suggestions");
private final By changeTimeLink = By.partialLinkText("change time");
private final By leavingButton = By.cssSelector("label[for=departing]");
private final By timeSelector = By.id("Time");
private final By planMyJourneyButton = By.cssSelector("#plan-a-journey .plan-journey-button");
private final By journeyResults = By.cssSelector(".summary-results");
private final By fastestJourney = By.cssSelector(".publictransport-box span.time");
private WebDriver browser;
@Before
public void openBrowser() {
browser = new FirefoxDriver();
}
@After
public void closeBrowser() {
browser.quit();
}
@Test
public void planning_a_journey() {
browser.get("https://tfl.gov.uk/");
browser.findElement(origin).sendKeys("Waterloo");
WebDriverWait wait = new WebDriverWait(browser, 10);
wait.until(visibilityOfElementLocated(originSuggestions));
browser.findElement(originSuggestions).sendKeys(ARROW_DOWN);
browser.findElement(originSuggestions).sendKeys(ENTER);
browser.findElement(destination).sendKeys("Canary Wharf");
wait.until(visibilityOfElementLocated(destinationSuggestions));
browser.findElement(destinationSuggestions).sendKeys(ARROW_DOWN);
browser.findElement(destinationSuggestions).sendKeys(ENTER);
browser.findElement(changeTimeLink).click();
browser.findElement(leavingButton).click();
new Select(browser.findElement(timeSelector)).selectByVisibleText("09:00");
browser.findElement(planMyJourneyButton).click();
wait.until(visibilityOfElementLocated(journeyResults));
String fastestDepartureTime = startTimeOf(browser.findElement(fastestJourney).getText());
#SerenityBDD @Wakaleo
“
serenity-bdd.info
If you have WebDriver APIs
in your test methods,
You’re Doing It Wrong!
- Simon Stewart, creator of WebDriver
serenity-bdd.info#SerenityBDD @Wakaleo
A test system needs design
serenity-bdd.info#SerenityBDD @Wakaleo
Page Objects to the rescue?
serenity-bdd.info#SerenityBDD @Wakaleo
serenity-bdd.info#SerenityBDD @Wakaleo
@DefaultUrl(“https://tfl.gov.uk")
public class JourneyPlannerPage extends PageObject {
// Locators
// Actions
}
serenity-bdd.info#SerenityBDD @Wakaleo
@DefaultUrl(“https://tfl.gov.uk")
public class JourneyPlannerPage extends PageObject {
// Locators
@FindBy(id = "InputFrom")
private WebElementFacade origin;
@FindBy(className = "tt-suggestions")
private WebElementFacade originSuggestions;
@FindBy(id = “InputTo")
private WebElementFacade destination;
@FindBy(className = “tt-suggestions")
private WebElementFacade destinationSuggestions;
@FindBy(partialLinkText = "change time”)
private WebElementFacade changeTimeLink;
…
serenity-bdd.info#SerenityBDD @Wakaleo
@DefaultUrl(“https://tfl.gov.uk")
public class JourneyPlannerPage extends PageObject {
// Locators
…
// Actions
public void chooseOriginOf(String originValue) {
origin.sendKeys(originValue);
waitFor(visibilityOf(originSuggestions));
originSuggestions.sendKeys(Keys.ARROW_DOWN);
originSuggestions.sendKeys(Keys.ENTER);
}
public void chooseDestinationOf(String destinationValue) {…}

public void confirmSelection() {…}
}
serenity-bdd.info#SerenityBDD @Wakaleo
@RunWith(SerenityRunner.class)
public class JourneyPlannerWithPageObjectsTest {


serenity-bdd.info#SerenityBDD @Wakaleo
@RunWith(SerenityRunner.class)
public class JourneyPlannerWithPageObjectsTest {
@Managed WebDriver driver;


serenity-bdd.info#SerenityBDD @Wakaleo
@RunWith(SerenityRunner.class)
public class JourneyPlannerWithPageObjectsTest {
@Managed WebDriver driver;
JourneyPlannerPage journeyPlanner;
JourneyResultsPage journeyResults;


serenity-bdd.info#SerenityBDD @Wakaleo
JourneyPlannerPage journeyPlanner;
JourneyResultsPage journeyResults;
journeyPlanner.open();
journeyPlanner.chooseOriginOf(“Waterloo");
journeyPlanner.chooseDestinationOf("Canary Wharf”);
journeyPlanner.chooseTimeOfDeparture(“09:00”);
journeyPlanner.confirmSelection();


serenity-bdd.info#SerenityBDD @Wakaleo
JourneyPlannerPage journeyPlanner;
JourneyResultsPage journeyResults;
journeyPlanner.open();
journeyPlanner.chooseOriginOf(“Waterloo");
journeyPlanner.chooseDestinationOf("Canary Wharf”);
journeyPlanner.chooseTimeOfDeparture(“09:00”);
journeyPlanner.confirmSelection();
assertThat(journeyResults.getFastestJourneyDepartureTime())
.isEqualTo(“08:59");
serenity-bdd.info#SerenityBDD @Wakaleo
@RunWith(SerenityRunner.class)
public class JourneyPlannerWithPageObjectsTest {
@Managed
WebDriver driver;
JourneyPlannerPage journeyPlanner;
JourneyResultsPage journeyResults;
@Test
public void planning_a_journey() {
journeyPlanner.open();
journeyPlanner.chooseOriginOf("Waterloo");
journeyPlanner.chooseDestinationOf("Canary Wharf");
journeyPlanner.chooseTimeOfDeparture("09:00");
journeyPlanner.confirmSelection();
assertThat(journeyResults.getFastestJourneyDepartureTime())
.isEqualTo("08:59");
}
}
not bad!
serenity-bdd.info#SerenityBDD @Wakaleo
not bad?
@RunWith(SerenityRunner.class)
public class JourneyPlannerWithPageObjectsTest {
@Managed
WebDriver driver;
JourneyPlannerPage journeyPlanner;
JourneyResultsPage journeyResults;
@Test
public void planning_a_journey() {
journeyPlanner.open();
journeyPlanner.chooseOriginOf("Waterloo");
journeyPlanner.chooseDestinationOf("Canary Wharf");
journeyPlanner.chooseTimeOfDeparture("09:00");
journeyPlanner.confirmSelection();
assertThat(journeyResults.getFastestJourneyDepartureTime())
.isEqualTo("08:59");
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
@DefaultUrl("https://tfl.gov.uk")
public class JourneyPlannerPage extends PageObject {
@FindBy(id = "InputFrom")
private WebElementFacade origin;
@FindBy(className = "tt-suggestions")
private WebElementFacade originSuggestions;
@FindBy(id = "InputTo")
private WebElementFacade destination;
@FindBy(className = "tt-suggestions")
private WebElementFacade destinationSuggestions;
@FindBy(partialLinkText = "change time")
private WebElementFacade changeTimeLink;
@FindBy(css = "label[for=departing]")
private WebElementFacade leavingButton;
@FindBy(id = "Time")
private WebElement timeSelector;
@FindBy(css = "#plan-a-journey .plan-journey-button")
private WebElementFacade planMyJourneyButton;
@FindBy(className = "summary-results")
private WebElementFacade journeyResults;
public void chooseOriginOf(String originValue) {
origin.sendKeys(originValue);
waitFor(visibilityOf(originSuggestions));
originSuggestions.sendKeys(Keys.ARROW_DOWN);
originSuggestions.sendKeys(Keys.ENTER);
}
public void chooseDestinationOf(String destinationValue) {
destination.sendKeys(destinationValue);
waitFor(visibilityOf(destinationSuggestions));
destinationSuggestions.sendKeys(Keys.ARROW_DOWN);
destinationSuggestions.sendKeys(Keys.ENTER);
}
public void chooseTimeOfDeparture(String timeOfDeparture) {
changeTimeLink.click();
leavingButton.click();
selectFromDropdown(timeSelector, timeOfDeparture);
}
public void confirmSelection() {
planMyJourneyButton.click();
waitFor(visibilityOf(journeyResults));
}
large classes
serenity-bdd.info#SerenityBDD @Wakaleo
large classes
bloated methods
@DefaultUrl("https://tfl.gov.uk")
public class JourneyPlannerPage extends PageObject {
@FindBy(id = "InputFrom")
private WebElementFacade origin;
@FindBy(className = "tt-suggestions")
private WebElementFacade originSuggestions;
@FindBy(id = "InputTo")
private WebElementFacade destination;
@FindBy(className = "tt-suggestions")
private WebElementFacade destinationSuggestions;
@FindBy(partialLinkText = "change time")
private WebElementFacade changeTimeLink;
@FindBy(css = "label[for=departing]")
private WebElementFacade leavingButton;
@FindBy(id = "Time")
private WebElement timeSelector;
@FindBy(css = "#plan-a-journey .plan-journey-button")
private WebElementFacade planMyJourneyButton;
@FindBy(className = "summary-results")
private WebElementFacade journeyResults;
public void chooseOriginOf(String originValue) {
origin.sendKeys(originValue);
waitFor(visibilityOf(originSuggestions));
originSuggestions.sendKeys(Keys.ARROW_DOWN);
originSuggestions.sendKeys(Keys.ENTER);
}
public void chooseDestinationOf(String destinationValue) {
destination.sendKeys(destinationValue);
waitFor(visibilityOf(destinationSuggestions));
destinationSuggestions.sendKeys(Keys.ARROW_DOWN);
destinationSuggestions.sendKeys(Keys.ENTER);
}
public void chooseTimeOfDeparture(String timeOfDeparture) {
changeTimeLink.click();
leavingButton.click();
selectFromDropdown(timeSelector, timeOfDeparture);
}
public void confirmSelection() {
planMyJourneyButton.click();
waitFor(visibilityOf(journeyResults));
}
serenity-bdd.info#SerenityBDD @Wakaleo
large classes
bloated methods
difficult to compose
@DefaultUrl("https://tfl.gov.uk")
public class JourneyPlannerPage extends PageObject {
@FindBy(id = "InputFrom")
private WebElementFacade origin;
@FindBy(className = "tt-suggestions")
private WebElementFacade originSuggestions;
@FindBy(id = "InputTo")
private WebElementFacade destination;
@FindBy(className = "tt-suggestions")
private WebElementFacade destinationSuggestions;
@FindBy(partialLinkText = "change time")
private WebElementFacade changeTimeLink;
@FindBy(css = "label[for=departing]")
private WebElementFacade leavingButton;
@FindBy(id = "Time")
private WebElement timeSelector;
@FindBy(css = "#plan-a-journey .plan-journey-button")
private WebElementFacade planMyJourneyButton;
@FindBy(className = "summary-results")
private WebElementFacade journeyResults;
public void chooseOriginOf(String originValue) {
origin.sendKeys(originValue);
waitFor(visibilityOf(originSuggestions));
originSuggestions.sendKeys(Keys.ARROW_DOWN);
originSuggestions.sendKeys(Keys.ENTER);
}
public void chooseDestinationOf(String destinationValue) {
destination.sendKeys(destinationValue);
waitFor(visibilityOf(destinationSuggestions));
destinationSuggestions.sendKeys(Keys.ARROW_DOWN);
destinationSuggestions.sendKeys(Keys.ENTER);
}
public void chooseTimeOfDeparture(String timeOfDeparture) {
changeTimeLink.click();
leavingButton.click();
selectFromDropdown(timeSelector, timeOfDeparture);
}
public void confirmSelection() {
planMyJourneyButton.click();
waitFor(visibilityOf(journeyResults));
}
serenity-bdd.info#SerenityBDD @Wakaleo
Four Software Engineering Principles can help
you write more maintainable tests
serenity-bdd.info#SerenityBDD @Wakaleo
1) Separation of Concerns
Hide complexity through layers of abstraction
serenity-bdd.info#SerenityBDD @Wakaleo
2) Single Responsibility Principle
A class should have only one reason to change
serenity-bdd.info#SerenityBDD @Wakaleo
3) Open-Closed Principle
Green diffs
serenity-bdd.info#SerenityBDD @Wakaleo
4) Narrative coding style
Express your intent
serenity-bdd.info#SerenityBDD @Wakaleo
Serenity BDD and
the Screenplay Pattern
#SerenityBDD @Wakaleo
“
serenity-bdd.info
Your test framework should not
model how your system behaves.
It should model how your user
behaves.
serenity-bdd.info#SerenityBDD @Wakaleo
serenity-bdd.info#SerenityBDD @Wakaleo
Goals
What are you trying to achieve?
serenity-bdd.info#SerenityBDD @Wakaleo
Goals
What are you trying to achieve?
Tasks
What do you need to do to
achieve this goal?
serenity-bdd.info#SerenityBDD @Wakaleo
Goals
What are you trying to achieve?
Tasks
What do you need to do to
achieve this goal?
Interactions
What interactions with the
system do you need for each
task?
serenity-bdd.info#SerenityBDD @Wakaleo
Actor
Connor the
commuter
serenity-bdd.info#SerenityBDD @Wakaleo
Plan my journey
Actor Goals
Connor the
commuter
serenity-bdd.info#SerenityBDD @Wakaleo
Plan my journey
Actor Goals Tasks
Choose Destination
Choose Origin
Choose time of departure
Confirm selection
Connor the
commuter
serenity-bdd.info#SerenityBDD @Wakaleo
Plan my journey
Actor Goals Tasks Interactions
Press “Down”
Type “Waterloo”
Choose Destination
Choose Origin
Choose time of departure
Press “Enter”
Confirm selection
Connor the
commuter
serenity-bdd.info#SerenityBDD @Wakaleo
Say what you mean
serenity-bdd.info#SerenityBDD @Wakaleo


Open the Journey Planner

Choose origin of Waterloo
Choose destination of Canary Wharf
Choose time of departure: 09:00
Confirm selection
See if the fastest train departs at 08:59
serenity-bdd.info#SerenityBDD @Wakaleo


OpenApplication.onTheJourneyPlannerPage(),
ChooseOrigin.of("Waterloo"),
ChooseDestination.of("Canary Wharf"),
ChooseTimeOfDeparture.of("09:00"),
Confirm.journeyDetails(),
seeThat(TheFastest.departureTime(), is("08:59"))
serenity-bdd.info#SerenityBDD @Wakaleo
Designing a task
serenity-bdd.info#SerenityBDD @Wakaleo
ChooseOrigin.of("Waterloo")
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Override
public <T extends Actor> void performAs(T actor) {}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
);

}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Enter.theValue(station).into(JourneyPlanner.ORIGIN)
);

}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Enter.theValue(station).into(JourneyPlanner.ORIGIN),
WaitUntil.the(JourneyPlanner.ORIGIN_SUGGESTIONS, isVisible())
);

}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Enter.theValue(station).into(JourneyPlanner.ORIGIN),
WaitUntil.the(JourneyPlanner.ORIGIN_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
);

}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Enter.theValue(station).into(JourneyPlanner.ORIGIN),
WaitUntil.the(JourneyPlanner.ORIGIN_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
PickFirstSuggestion.from(JourneyPlanner.ORIGIN)
);

}
private final String station;
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Enter.theValue(station).into(JourneyPlanner.ORIGIN),
WaitUntil.the(JourneyPlanner.ORIGIN_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
PickFirstSuggestion.from(JourneyPlanner.ORIGIN)
);

}
private final String station;
public ChooseOrigin(String origin) { this.station = origin;}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Enter.theValue(station).into(JourneyPlanner.ORIGIN),
WaitUntil.the(JourneyPlanner.ORIGIN_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
PickFirstSuggestion.from(JourneyPlanner.ORIGIN)
);

}
private final String station;
public ChooseOrigin(String origin) { this.station = origin;}
public static Performable of(String station) {
return instrumented(ChooseOrigin.class, station); 

}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Step("{0} selects origin station of #station")
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Enter.theValue(station).into(JourneyPlanner.ORIGIN),
WaitUntil.the(JourneyPlanner.ORIGIN_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
PickFirstSuggestion.from(JourneyPlanner.ORIGIN)
);

}
private final String station;
public ChooseOrigin(String origin) { this.station = origin;}
public static Performable of(String station) {
return instrumented(ChooseOrigin.class, station); 

}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Step("{0} selects origin station of #station")
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Enter.theValue(station).into(JourneyPlanner.ORIGIN),
WaitUntil.the(JourneyPlanner.ORIGIN_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
PickFirstSuggestion.from(JourneyPlanner.ORIGIN)
);

}
private final String station;
public ChooseOrigin(String origin) { this.station = origin;}
public static Performable of(String station) {
return instrumented(ChooseOrigin.class, station); 

}
}
How the step appears in the reports
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Step("{0} selects origin station of #station")
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Enter.theValue(station).into(JourneyPlanner.ORIGIN),
WaitUntil.the(JourneyPlanner.ORIGIN_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
PickFirstSuggestion.from(JourneyPlanner.ORIGIN)
);

}
private final String station;
public ChooseOrigin(String origin) { this.station = origin;}
public static Performable of(String station) {
return instrumented(ChooseOrigin.class, station); 

}
}
The name of the actor
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseOrigin implements Task {
@Step("{0} selects origin station of #station")
@Override
public <T extends Actor> void performAs(T actor) {
actor.attemptsTo(
Enter.theValue(station).into(JourneyPlanner.ORIGIN),
WaitUntil.the(JourneyPlanner.ORIGIN_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
PickFirstSuggestion.from(JourneyPlanner.ORIGIN)
);

}
private final String station;
public ChooseOrigin(String origin) { this.station = origin;}
public static Performable of(String station) {
return instrumented(ChooseOrigin.class, station); 

}
}
A member variable
serenity-bdd.info#SerenityBDD @Wakaleo
Or…
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseDestination {
/**
* Usage: ChooseDestination.of("Canary Wharf")
*/
public static Task of(String station) {
return Task.where("{0} selects origin station of #station",
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseDestination {
/**
* Usage: ChooseDestination.of("Canary Wharf")
*/
public static Task of(String station) {
return Task.where("{0} selects origin station of #station",
Enter.theValue(station).into(JourneyPlanner.DESTINATION),
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseDestination {
/**
* Usage: ChooseDestination.of("Canary Wharf")
*/
public static Task of(String station) {
return Task.where("{0} selects origin station of #station",
Enter.theValue(station).into(JourneyPlanner.DESTINATION),
WaitUntil.the(JourneyPlanner.DESTINATION_SUGGESTIONS, isVisible())
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseDestination {
/**
* Usage: ChooseDestination.of("Canary Wharf")
*/
public static Task of(String station) {
return Task.where("{0} selects origin station of #station",
Enter.theValue(station).into(JourneyPlanner.DESTINATION),
WaitUntil.the(JourneyPlanner.DESTINATION_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseDestination {
/**
* Usage: ChooseDestination.of("Canary Wharf")
*/
public static Task of(String station) {
return Task.where("{0} selects origin station of #station",
Enter.theValue(station).into(JourneyPlanner.DESTINATION),
WaitUntil.the(JourneyPlanner.DESTINATION_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
PickFirstSuggestion.from(JourneyPlanner.DESTINATION))
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class ChooseDestination {
/**
* Usage: ChooseDestination.of("Canary Wharf")
*/
public static Task of(String station) {
return Task.where("{0} selects origin station of #station",
Enter.theValue(station).into(JourneyPlanner.DESTINATION),
WaitUntil.the(JourneyPlanner.DESTINATION_SUGGESTIONS, isVisible())
.forNoMoreThan(10).seconds(),
PickFirstSuggestion.from(JourneyPlanner.DESTINATION))
.with(“station").of(station);
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
Interactions talk to the system
serenity-bdd.info#SerenityBDD @Wakaleo
Most WebDriver interactions come bundled with Serenity Screenplay
Enter.theValue(station).into(JourneyPlanner.ORIGIN)
Click.on(JourneyPlanner.PLAN_MY_JOURNEY)
SelectFromOptions.byVisibleText(timeOfDeparture)
.from(JourneyPlanner.SELECTED_DEPARTURE_TIME)
WaitUntil.the(JourneyResults.RESULTS_LIST, isVisible())
Scroll.to(JourneyResults.RESULTS_LIST)
serenity-bdd.info#SerenityBDD @Wakaleo
Actors perform tasks
serenity-bdd.info#SerenityBDD @Wakaleo
import net.serenitybdd.screenplay.Actor;
Actor connie = Actor.named("Connie");
serenity-bdd.info#SerenityBDD @Wakaleo
import net.serenitybdd.screenplay.Actor;
Actor connie = Actor.named("Connie");
connie.attemptsTo(
//…
);
serenity-bdd.info#SerenityBDD @Wakaleo
Actor connie = Actor.named("Connie");
connie.attemptsTo(
OpenApplication.onTheJourneyPlannerPage(),
ChooseOrigin.of("Waterloo"),
ChooseDestination.of("Canary Wharf"),
ChooseTimeOfDeparture.of(“09:00"),
Confirm.journeyDetails()
serenity-bdd.info#SerenityBDD @Wakaleo
Actors have abilities 

that enable interactions
with the system
serenity-bdd.info#SerenityBDD @Wakaleo
@Managed WebDriver browser;
Actor connie = Actor.named("Connie");
connie.can(BrowseTheWeb.with(browser));
serenity-bdd.info#SerenityBDD @Wakaleo
But where did the Page Objects go?
serenity-bdd.info#SerenityBDD @Wakaleo
public class JourneyPlanner {
public static final Target ORIGIN = Target.the("Departure station")
.locatedBy("#InputFrom");
public static final Target ORIGIN_SUGGESTIONS = Target.the("Origin Suggestions")
.locatedBy("//*[input[@id='InputFrom']]/*[contains(@class, 'tt-dropdown-menu')]");
public static final Target DESTINATION = Target.the("Destination station")
.locatedBy("#InputTo");
public static final Target DESTINATION_SUGGESTIONS = Target.the("Destination Suggestions")
.locatedBy("//*[input[@id='InputTo']]/*[contains(@class, 'tt-dropdown-menu')]");
public static final Target CHANGE_TIME = Target.the("Change Time")
.located(By.partialLinkText("change time"));
public static final Target LEAVING_BUTTON = Target.the("Leaving")
.located(By.cssSelector("label[for=departing]"));
public static final Target SELECTED_DEPARTURE_TIME = Target.the("Departure Time")
.located(By.id("Time"));
public static final Target SELECTED_DEPARTURE_DROPDOWN = Target.the("Departure Time")
.located(By.cssSelector(".hours"));
public static final Target PLAN_MY_JOURNEY = Target.the("Plan my journey")
.locatedBy("#plan-a-journey .plan-journey-button");;
}
serenity-bdd.info#SerenityBDD @Wakaleo
Target.the("Departure station").locatedBy("#InputFrom");
serenity-bdd.info#SerenityBDD @Wakaleo
Target.the("Departure station").locatedBy("#InputFrom");
How should this element be named in the reports?
serenity-bdd.info#SerenityBDD @Wakaleo
Target.the("Departure station").locatedBy("#InputFrom");
How should we locate it?
serenity-bdd.info#SerenityBDD @Wakaleo
What about more complicated cases?
serenity-bdd.info#SerenityBDD @Wakaleo
Target FILTER = Target.the(“filter")
.locatedBy("//*[@class='filters']//a[.='{0}']");
This value will be provided
serenity-bdd.info#SerenityBDD @Wakaleo
theActor.attemptsTo(FilterItems.toShow(“Completed"));
serenity-bdd.info#SerenityBDD @Wakaleo
public class FilterItems implements Task {
private final String filter;
public <T extends Actor> void performAs(T theActor) {
}
public static FilterItems toShow(String filter) {
return instrumented(FilterItems.class, status);
}
public FilterItems(TodoStatusFilter filter) { this.filter = filter; }
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class FilterItems implements Task {
private final String filter;
public <T extends Actor> void performAs(T theActor) {
theActor.attemptsTo(
Click.on(TodoList.FILTER
);
}
public static FilterItems toShow(String filter) {
return instrumented(FilterItems.class, status);
}
public FilterItems(TodoStatusFilter filter) { this.filter = filter; }
}
Click on the filter button
serenity-bdd.info#SerenityBDD @Wakaleo
public class FilterItems implements Task {
private final String filter;
public <T extends Actor> void performAs(T theActor) {
theActor.attemptsTo(
Click.on(TodoList.FILTER.of(filter)
);
}
public static FilterItems toShow(String filter) {
return instrumented(FilterItems.class, status);
}
public FilterItems(TodoStatusFilter filter) { this.filter = filter; }
}
Pass in the name of the filter
serenity-bdd.info#SerenityBDD @Wakaleo
public class FilterItems implements Task {
private final String filter;
public <T extends Actor> void performAs(T theActor) {
theActor.attemptsTo(
Click.on(TodoList.FILTER.of(filter)
.called(“filter by "+ filter))
);
}
public static FilterItems toShow(String filter) {
return instrumented(FilterItems.class, status);
}
public FilterItems(TodoStatusFilter filter) { this.filter = filter; }
How will this interaction appear in the reports?
serenity-bdd.info#SerenityBDD @Wakaleo
public class FilterItems implements Task {
private final String filter;
@Step("{0} filters items by #filter")
public <T extends Actor> void performAs(T theActor) {
theActor.attemptsTo(
Click.on(TodoList.FILTER.of(filter)
.called(“filter by "+ filter))
);
}
public static FilterItems toShow(String filter) {
return instrumented(FilterItems.class, status);
}
How will this task appear in the reports
serenity-bdd.info#SerenityBDD @Wakaleo
Actors ask questions
and verify the answers
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat(the(JourneyResults.HEADER), isVisible())
);
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat(the(JourneyResults.HEADER), isVisible())
);
A Consequence
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat(the(JourneyResults.HEADER), isVisible())
);
A Question
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat(the(JourneyResults.HEADER), isVisible())
);
A Hamcrest Matcher
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat(the(JourneyResults.HEADER), isVisible())
);
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat(textOf(JourneyResults.HEADER), is("Journey Results"))
);
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat(selectedValueOf(JourneyPlanner.SELECTED_DEPARTURE_TIME),
is("Journey Results"))
);
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat("the fastest tube line”, TheFastest.tubeLine(),
is("Jubilee line to Canary Wharf”))
);
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat("the fastest tube line", TheFastest.tubeLine(),
is("Jubilee line to Canary Wharf")),
seeThat("the departure time", TheFastest.departureTime(),
is("08:59")),
seeThat("the arrival time", TheFastest.arrivalTime(),
is(“09:09"))
);
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat("the fastest tube line”, TheFastest.tubeLine(),
is("Jubilee line to Canary Wharf”))
);
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
return new FastestTubeLineQuestion();
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
return new FastestTubeLineQuestion();
}
}
public class FastestTubeLineQuestion implements Question<String> {
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
return new FastestTubeLineQuestion();
}
}
public class FastestTubeLineQuestion implements Question<String> {
@Override
public String answeredBy(Actor actor) {
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
return new FastestTubeLineQuestion();
}
}
public class FastestTubeLineQuestion implements Question<String> {
@Override
public String answeredBy(Actor actor) {
return Text.of(JourneyResults.ITINERARY)
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
return new FastestTubeLineQuestion();
}
}
public class FastestTubeLineQuestion implements Question<String> {
@Override
public String answeredBy(Actor actor) {
return Text.of(JourneyResults.ITINERARY)
.viewedBy(actor)
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
return new FastestTubeLineQuestion();
}
}
public class FastestTubeLineQuestion implements Question<String> {
@Override
public String answeredBy(Actor actor) {
return Text.of(JourneyResults.ITINERARY)
.viewedBy(actor)
.asString();
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
return new FastestTubeLineQuestion();
}
}
@Subject("the fastest tube line")
public class FastestTubeLineQuestion implements Question<String> {
@Override
public String answeredBy(Actor actor) {
return Text.of(JourneyResults.ITINERARY)
.viewedBy(actor)
.asString();
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
Or…
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
return actor -> Text.of(JourneyResults.ITINERARY)
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
return actor -> Text.of(JourneyResults.ITINERARY)
.viewedBy(actor)
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class TheFastest {
public static Question<String> tubeLine() {
return actor -> Text.of(JourneyResults.ITINERARY)
.viewedBy(actor)
.asString();
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
connie.should(
seeThat(“all the tube lines”, AllThe.tubeLines(),
contains("Northern line to Moorgate”))
);
serenity-bdd.info#SerenityBDD @Wakaleo
public class AllThe {
public static Question<String> tubeLine() {
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class AllThe {
public static Question<String> tubeLine() {
return actor -> Text.of(JourneyResults.ITINERARY)
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class AllThe {
public static Question<String> tubeLine() {
return actor -> Text.of(JourneyResults.ITINERARY)
.viewedBy(actor)
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class AllThe {
public static Question<List<String>> tubeLine() {
return actor -> Text.of(JourneyResults.ITINERARY)
.viewedBy(actor)
.asList();
}
}
serenity-bdd.info#SerenityBDD @Wakaleo
The end result
serenity-bdd.info#SerenityBDD @Wakaleo
@Managed WebDriver browser;
@Test
public void should_show_the_soonest_departure_time_close_to_the_requested_time() {
Actor connie = Actor.named("Connie");
connie.can(BrowseTheWeb.with(browser));
connie.attemptsTo(
OpenApplication.onTheJourneyPlannerPage(),
ChooseOrigin.of("Waterloo"),
ChooseDestination.of("Canary Wharf"),
ChooseTimeOfDeparture.of("09:00"),
Confirm.journeyDetails()
);
connie.should(
seeThat("the fastest tube line", TheFastest tubeLine(),
is("Jubilee line to Canary Wharf")),
seeThat("the departure time", TheFastest.departureTime(), is("08:59")),
seeThat("the arrival time", TheFastest.arrivalTime(), is("09:09"))
);
}
serenity-bdd.info#SerenityBDD @Wakaleo
But wait! There’s more!
serenity-bdd.info#SerenityBDD @Wakaleo
@Managed WebDriver browser;
@Test
public void should_show_the_soonest_departure_time_close_to_the_requested_time() {
Actor connie = Actor.named("Connie");
connie.can(BrowseTheWeb.with(browser));
connie.attemptsTo(
OpenApplication.onTheJourneyPlannerPage(),
ChooseOrigin.of("Waterloo"),
ChooseDestination.of("Canary Wharf"),
ChooseTimeOfDeparture.of("09:00"),
Confirm.journeyDetails()
);
connie.should(
seeThat("the fastest tube line", TheFastest tubeLine(),
is("Jubilee line to Canary Wharf")),
seeThat("the departure time", TheFastest.departureTime(), is("08:59")),
seeThat("the arrival time", TheFastest.arrivalTime(), is("09:09"))
);
}
serenity-bdd.info#SerenityBDD @Wakaleo
@Managed WebDriver browser;
@Test
public void should_show_the_soonest_departure_time_close_to_the_requested_time() {
Actor connie = Actor.named("Connie");
connie.can(BrowseTheWeb.with(browser));
connie.attemptsTo(
PlanAJourney.from("Waterloo").to("Canary Wharf").departingAt("09:00")
);
connie.should(
seeThat("the fastest tube line", TheFastest tubeLine(),
is("Jubilee line to Canary Wharf")),
seeThat("the departure time", TheFastest.departureTime(), is("08:59")),
seeThat("the arrival time", TheFastest.arrivalTime(), is("09:09"))
);
}
serenity-bdd.info#SerenityBDD @Wakaleo
Working with Cucumber
serenity-bdd.info#SerenityBDD @Wakaleo
Feature: Plan a new journey
Scenario: Plan a new journey
Given that Connie is a London commuter
When she plans a journey from Waterloo to Canary Wharf departing at 09:00
Then she should see that the fastest train departs at 08:59
serenity-bdd.info#SerenityBDD @Wakaleo
public class PlanAJourneyStepDefinitions {
@Before
public void set_the_stage() {
OnStage.setTheStage(new OnlineCast());
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class PlanAJourneyStepDefinitions {
@Before
public void set_the_stage() {
OnStage.setTheStage(new OnlineCast());
}
@Given("^that (.*) is a London commuter$")
public void a_london_commuter_named(String commuterName) throws Throwable {
theActorCalled(commuterName);
}
serenity-bdd.info#SerenityBDD @Wakaleo
public class PlanAJourneyStepDefinitions {
@Before
public void set_the_stage() {
OnStage.setTheStage(new OnlineCast());
}
@Given("^that (.*) is a London commuter$")
public void a_london_commuter_named(String commuterName) throws Throwable {
theActorCalled(commuterName);
}
serenity-bdd.info#SerenityBDD @Wakaleo
Feature: Plan a new journey
Scenario: Plan a new journey
Given that Connie is a London commuter
When she plans a journey from Waterloo to Canary Wharf departing at 09:00
Then she should see that the fastest train departs at 08:59
serenity-bdd.info#SerenityBDD @Wakaleo
public class PlanAJourneyStepDefinitions {
@Before
public void set_the_stage() {
OnStage.setTheStage(new OnlineCast());
}
@Given("^that (.*) is a London commuter$")
public void a_london_commuter_named(String commuterName) throws Throwable {
theActorCalled(commuterName);
}
@When("^(.*) plans a journey from (.*) to (.*) departing at (.*)$")
public void plan_a_journeys(String name, String departure, String destination,
String departureTime) throws Throwable {
theActorCalled(name).attemptsTo(
PlanAJourney.from(departure).to(destination).departingAt(departureTime)
);
}
serenity-bdd.info#SerenityBDD @Wakaleo
Feature: Plan a new journey
Scenario: Plan a new journey
Given that Connie is a London commuter
When she plans a journey from Waterloo to Canary Wharf departing at 09:00
Then she should see that the fastest train departs at 08:59
serenity-bdd.info#SerenityBDD @Wakaleo
public class PlanAJourneyStepDefinitions {
@Before
public void set_the_stage() {
OnStage.setTheStage(new OnlineCast());
}
@Given("^that (.*) is a London commuter$")
public void a_london_commuter_named(String commuterName) throws Throwable {…}
@When("^(.*) plans a journey from (.*) to (.*) departing at (.*)$")
public void plan_a_journeys(String name, String departure, String destination,
String departureTime) throws Throwable {…}
@Then("^(.*) should see that the fastest train departs at (.*)$")
public void should_see_departure_time(String name,
String expectedDepartureTime) throws Throwable {
theActorCalled(name).should(
seeThat("the departure time", TheFastest.departureTime(),
is(expectedDepartureTime))
);
serenity-bdd.info#SerenityBDD @Wakaleo
Cucumber gives us flexibility
serenity-bdd.info#SerenityBDD @Wakaleo
Feature: Plan a new journey
Scenario Outline: Plan many a journey
Given that Connie is a London commuter
When she plans a journey from <departure> to <destination> departing at <plannedDepartureTime>
Then she should see a trip on the <line> line departing at <departureTime>
Examples:
| departure | destination | line | plannedDepartureTime | departureTime |
| Waterloo | Canary Wharf | Jubilee line to Canary Wharf | 09:00 | 08:59 |
| London Bridge | Moorgate | Northern line to Moorgate | 10:00 | 09:59 |
serenity-bdd.info#SerenityBDD @Wakaleo
Feature: Plan a new journey
Scenario Outline: Plan many a journey
Given that Connie is a London commuter
When she plans a journey from <departure> to <destination> departing at <plannedDepartureTime>
Then she should see a trip on the <line> line departing at <departureTime>
Examples:
| departure | destination | line | plannedDepartureTime | departureTime |
| Waterloo | Canary Wharf | Jubilee line to Canary Wharf | 09:00 | 08:59 |
| London Bridge | Moorgate | Northern line to Moorgate | 10:00 | 09:59 |
serenity-bdd.info#SerenityBDD @Wakaleo
@Then("^(.*) should see a trip on the (.*) line departing at (.*)")
public void should_see_trip(String name, String line, String departureTime) {
theActorCalled(name).should(
seeThat("the fastest tube line”, TheFastest.tubeLine(),
is(line)),
seeThat("the departure time", TheFastest.departureTime(),
is(departureTime))
);
}
serenity-bdd.info#SerenityBDD @Wakaleo
Scenario: Coordinating journeys
Given that Connie is a London commuter
And that Charles is a London commuter
When Connie plans a journey from Waterloo to Canary Wharf departing at 09:00
And Charles plans a journey from London Bridge to Moorgate departing at 10:00
Then Connie should see a trip on the Jubilee line to Canary Wharf line departing at 08:59
And Charles should see a trip on the Northern line to Moorgate line departing at 09:59
serenity-bdd.info#SerenityBDD @Wakaleo
Obsess about reporting!
serenity-bdd.info#SerenityBDD @Wakaleo
Levels of communication
-
+
serenity-bdd.info#SerenityBDD @Wakaleo
-
+
10,000 ft

Release Readiness
serenity-bdd.info#SerenityBDD @Wakaleo
-
+
1000 ft

Capabilities and Features
serenity-bdd.info#SerenityBDD @Wakaleo
-
+
100 ft

Scenarios and Steps
serenity-bdd.info#SerenityBDD @Wakaleo
-
+
Release
Readiness
serenity-bdd.info#SerenityBDD @Wakaleo
-
+
Release
Readiness
Capabilities
serenity-bdd.info#SerenityBDD @Wakaleo
-
+
Release
Readiness
Capabilities
Features
serenity-bdd.info#SerenityBDD @Wakaleo
-
+
Release
Readiness
Capabilities
Features
Scenarios
serenity-bdd.info#SerenityBDD @Wakaleo
Questions to ask:
- How much time do I spend maintaining the tests?
- Am I modelling user’s interactions with the system, 

or how the system is built?
- Can I share elements of my testing framework with others?
- How much duplication and dead code is there in my tests?
- How long would it take me to find the issue if a test fails?
- How long to change the tests when the system changes?
- Can I use my tests to drive the design of the system?
serenity-bdd.info#SerenityBDD @Wakaleo
Make your tests

scalable by design
serenity-bdd.info#SerenityBDD @Wakaleo
Prefer JavaScript?
Try
http://serenity-js.org
serenity-bdd.info#SerenityBDD @Wakaleo
Jan Molak
Original slides and demonstration in JavaScript designed by
consultant, trainer, lead developer of Serenity/JS
serenity-bdd.info#SerenityBDD @Wakaleo
Thank you!
Learn more at serenity-bdd.info



Source code:
How we can help:

Get in touch:
Learn Serenity BDD online




bit.ly/serentiy-planner
johnfergusonsmart.com

reachme@johnfergusonsmart.com
http://serenity-dojo.com

More Related Content

What's hot

angular fundamentals.pdf
angular fundamentals.pdfangular fundamentals.pdf
angular fundamentals.pdf
NuttavutThongjor1
 
Refactoring page objects The Screenplay Pattern
Refactoring page objects   The Screenplay Pattern Refactoring page objects   The Screenplay Pattern
Refactoring page objects The Screenplay Pattern
RiverGlide
 
Understanding Unit Testing
Understanding Unit TestingUnderstanding Unit Testing
Understanding Unit Testing
ikhwanhayat
 
An Introduction to Test Driven Development
An Introduction to Test Driven Development An Introduction to Test Driven Development
An Introduction to Test Driven Development
CodeOps Technologies LLP
 
BDD for APIs
BDD for APIsBDD for APIs
BDD for APIs
Jason Harmon
 
Writing Test Cases in Agile
Writing Test Cases in AgileWriting Test Cases in Agile
Writing Test Cases in Agile
Saroj Singh
 
Java Unit Testing
Java Unit TestingJava Unit Testing
Java Unit Testing
Nayanda Haberty
 
Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)
Lars Thorup
 
Cucumber and Spock Primer
Cucumber and Spock PrimerCucumber and Spock Primer
Cucumber and Spock Primer
John Ferguson Smart Limited
 
Selenium Tutorial For Beginners | What Is Selenium? | Selenium Automation Tes...
Selenium Tutorial For Beginners | What Is Selenium? | Selenium Automation Tes...Selenium Tutorial For Beginners | What Is Selenium? | Selenium Automation Tes...
Selenium Tutorial For Beginners | What Is Selenium? | Selenium Automation Tes...
Edureka!
 
Types of testing
Types of testingTypes of testing
Types of testing
Valarmathi Srinivasan
 
Cucumber & gherkin language
Cucumber & gherkin languageCucumber & gherkin language
Cucumber & gherkin language
selvanathankapilan
 
BDD WITH CUCUMBER AND JAVA
BDD WITH CUCUMBER AND JAVABDD WITH CUCUMBER AND JAVA
BDD WITH CUCUMBER AND JAVA
Srinivas Katakam
 
[AUG]개발자와 QA가 상생하는 테스트 프로세스
[AUG]개발자와 QA가 상생하는 테스트 프로세스[AUG]개발자와 QA가 상생하는 테스트 프로세스
[AUG]개발자와 QA가 상생하는 테스트 프로세스
철민 신
 
Perils of Page-Object Pattern
Perils of Page-Object PatternPerils of Page-Object Pattern
Perils of Page-Object Pattern
Anand Bagmar
 
BDD with Cucumber
BDD with CucumberBDD with Cucumber
BDD with Cucumber
Knoldus Inc.
 
Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010
guest5639fa9
 
C++ Unit Test with Google Testing Framework
C++ Unit Test with Google Testing FrameworkC++ Unit Test with Google Testing Framework
C++ Unit Test with Google Testing Framework
Humberto Marchezi
 
Unit and integration Testing
Unit and integration TestingUnit and integration Testing
Unit and integration Testing
David Berliner
 
TDD refresher
TDD refresherTDD refresher
TDD refresher
Kerry Buckley
 

What's hot (20)

angular fundamentals.pdf
angular fundamentals.pdfangular fundamentals.pdf
angular fundamentals.pdf
 
Refactoring page objects The Screenplay Pattern
Refactoring page objects   The Screenplay Pattern Refactoring page objects   The Screenplay Pattern
Refactoring page objects The Screenplay Pattern
 
Understanding Unit Testing
Understanding Unit TestingUnderstanding Unit Testing
Understanding Unit Testing
 
An Introduction to Test Driven Development
An Introduction to Test Driven Development An Introduction to Test Driven Development
An Introduction to Test Driven Development
 
BDD for APIs
BDD for APIsBDD for APIs
BDD for APIs
 
Writing Test Cases in Agile
Writing Test Cases in AgileWriting Test Cases in Agile
Writing Test Cases in Agile
 
Java Unit Testing
Java Unit TestingJava Unit Testing
Java Unit Testing
 
Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)
 
Cucumber and Spock Primer
Cucumber and Spock PrimerCucumber and Spock Primer
Cucumber and Spock Primer
 
Selenium Tutorial For Beginners | What Is Selenium? | Selenium Automation Tes...
Selenium Tutorial For Beginners | What Is Selenium? | Selenium Automation Tes...Selenium Tutorial For Beginners | What Is Selenium? | Selenium Automation Tes...
Selenium Tutorial For Beginners | What Is Selenium? | Selenium Automation Tes...
 
Types of testing
Types of testingTypes of testing
Types of testing
 
Cucumber & gherkin language
Cucumber & gherkin languageCucumber & gherkin language
Cucumber & gherkin language
 
BDD WITH CUCUMBER AND JAVA
BDD WITH CUCUMBER AND JAVABDD WITH CUCUMBER AND JAVA
BDD WITH CUCUMBER AND JAVA
 
[AUG]개발자와 QA가 상생하는 테스트 프로세스
[AUG]개발자와 QA가 상생하는 테스트 프로세스[AUG]개발자와 QA가 상생하는 테스트 프로세스
[AUG]개발자와 QA가 상생하는 테스트 프로세스
 
Perils of Page-Object Pattern
Perils of Page-Object PatternPerils of Page-Object Pattern
Perils of Page-Object Pattern
 
BDD with Cucumber
BDD with CucumberBDD with Cucumber
BDD with Cucumber
 
Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010
 
C++ Unit Test with Google Testing Framework
C++ Unit Test with Google Testing FrameworkC++ Unit Test with Google Testing Framework
C++ Unit Test with Google Testing Framework
 
Unit and integration Testing
Unit and integration TestingUnit and integration Testing
Unit and integration Testing
 
TDD refresher
TDD refresherTDD refresher
TDD refresher
 

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 Scenarios
John 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 difference
John Ferguson Smart Limited
 
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
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 difference
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
 
Shift left-devoxx-pl
Shift left-devoxx-plShift left-devoxx-pl
Shift left-devoxx-pl
John 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 practices
John Ferguson Smart Limited
 
CukeUp 2016 Agile Product Planning Workshop
CukeUp 2016 Agile Product Planning WorkshopCukeUp 2016 Agile Product Planning Workshop
CukeUp 2016 Agile Product Planning Workshop
John Ferguson Smart Limited
 
BDD Anti-patterns
BDD Anti-patternsBDD Anti-patterns
BDD Anti-patterns
John Ferguson Smart Limited
 
BDD - Collaborate like you mean it!
BDD - Collaborate like you mean it!BDD - Collaborate like you mean it!
BDD - Collaborate like you mean it!
John Ferguson Smart Limited
 
BDD-Driven Microservices
BDD-Driven MicroservicesBDD-Driven Microservices
BDD-Driven Microservices
John Ferguson Smart Limited
 
BDD Anti-patterns
BDD Anti-patternsBDD Anti-patterns
BDD Anti-patterns
John 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 Testers
John 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 Serenity
John Ferguson Smart Limited
 
BDD in Action - Devoxx 2014
BDD in Action - Devoxx 2014BDD in Action - Devoxx 2014
BDD in Action - Devoxx 2014
John Ferguson Smart Limited
 
BDD in Action: Building Software Right and Building the Right Software
BDD in Action: Building Software Right and Building the Right SoftwareBDD in Action: Building Software Right and Building the Right Software
BDD in Action: Building Software Right and Building the Right Software
John Ferguson Smart Limited
 
BDD: The unit test of the product owner
BDD: The unit test of the product ownerBDD: The unit test of the product owner
BDD: The unit test of the product owner
John Ferguson Smart Limited
 
Its testing-jim-but-not-as-we-know-it-devoxx
Its testing-jim-but-not-as-we-know-it-devoxxIts testing-jim-but-not-as-we-know-it-devoxx
Its testing-jim-but-not-as-we-know-it-devoxx
John Ferguson Smart Limited
 
BDD in Action - building software that matters
BDD in Action - building software that mattersBDD in Action - building software that matters
BDD in Action - building software that matters
John 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
 
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...
 
Shift left-devoxx-pl
Shift left-devoxx-plShift left-devoxx-pl
Shift left-devoxx-pl
 
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
 
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
 
BDD in Action: Building Software Right and Building the Right Software
BDD in Action: Building Software Right and Building the Right SoftwareBDD in Action: Building Software Right and Building the Right Software
BDD in Action: Building Software Right and Building the Right Software
 
BDD: The unit test of the product owner
BDD: The unit test of the product ownerBDD: The unit test of the product owner
BDD: The unit test of the product owner
 
Its testing-jim-but-not-as-we-know-it-devoxx
Its testing-jim-but-not-as-we-know-it-devoxxIts testing-jim-but-not-as-we-know-it-devoxx
Its testing-jim-but-not-as-we-know-it-devoxx
 
BDD in Action - building software that matters
BDD in Action - building software that mattersBDD in Action - building software that matters
BDD in Action - building software that matters
 

Recently uploaded

Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
Bhaskar Mitra
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
Abida Shariff
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
Product School
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
DianaGray10
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
Fwdays
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 

Recently uploaded (20)

Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 

Sustainable Test Automation with Serenity BDD and Screenplay