Every test tells a story, but some tell a better story than others. Every test illustrates a specific path through the system to achieve a specific goal, but some paths are clearer than others. Valuable tests are the ones that tell a compelling story.
Come on a journey of discovery to learn how to write such tests, and witness a demonstration of these principles in action, with live coding of Serenity BDD automated tests.
4. @wakaleo
How much are your tests worth?
Weekly cost
vs
weekly savings
$0
$20,000
$40,000
$60,000
$80,000
$100,000
$120,000
$140,000
$160,000
$180,000
1/09/2015 1/10/2015 1/11/2015 1/12/2015
Test0suite0cost0vs0savings0(per0week)
Cost0saved0par0week Test0suite0cost0per0week
5. @wakaleo
How much are your tests worth?
Weekly cost
vs
weekly savings
$0
$20,000
$40,000
$60,000
$80,000
$100,000
$120,000
$140,000
$160,000
$180,000
1/09/2015 1/10/2015 1/11/2015 1/12/2015
Test0suite0cost0vs0savings0(per0week)
Cost0saved0par0week Test0suite0cost0per0week
Team cost is constant
6. @wakaleo
How much are your tests worth?
Weekly cost
vs
weekly savings
$0
$20,000
$40,000
$60,000
$80,000
$100,000
$120,000
$140,000
$160,000
$180,000
1/09/2015 1/10/2015 1/11/2015 1/12/2015
Test0suite0cost0vs0savings0(per0week)
Cost0saved0par0week Test0suite0cost0per0week
Team cost is constant
Time saved increases with the
number of executed
7. @wakaleo
How much are your tests worth?
$0
$200,000
$400,000
$600,000
$800,000
$1,000,000
$1,200,000
1/09/2015 1/10/2015 1/11/2015 1/12/2015
What0is0your0test0suite0worth?
Test0suite0ROI Test0suite0cost
Cumulated cost
vs
cumulated savings
8. @wakaleo
How much are your tests worth?
$0
$200,000
$400,000
$600,000
$800,000
$1,000,000
$1,200,000
1/09/2015 1/10/2015 1/11/2015 1/12/2015
What0is0your0test0suite0worth?
Test0suite0ROI Test0suite0cost
Cumulated cost
vs
cumulated savings
Cumulated value should increase
faster than cumulated cost
9. @wakaleo
Now factor in high maintenance
40-60%
Typical maintenance overhead
for poorly-written test suites
21. @wakaleo
Separation of Concerns - Layers
Goals
Tasks
Actions
What are you trying to achieve?
What do you need to do to achieve
this goal?
22. @wakaleo
Separation of Concerns - Layers
Goals
Tasks
Actions
What are you trying to achieve?
What do you need to do to achieve
this goal?
What interactions with the
system do you need for each
task?
23. @wakaleo
Separation of Concerns - Layers
Scenario: Add a new todo entry on the todo home page
Given I am on the Todo application home page
When I enter 'Buy some milk' into the New Todo field
And I press ENTER
Then the todo list box should contain 'Buy some milk'
24. @wakaleo
Separation of Concerns - Layers
Scenario: Record a new todo action for future use
Given I need to buy some milk
When I add the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in my todo list
32. @wakaleo
The Serenity layered architecture
Goals
Tasks
Interactions
Tests or scenarios
“Steps”
Page Objects or other technical
components
33. @wakaleo
The Serenity layered architecture
Feature: Add new todos
James needs to be able to jot down actions he needs to do as he
thinks of them
Scenario: Record a new todo action for future use
Given James needs to buy some milk
When James adds the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in his todo list
34. @wakaleo
The Serenity layered architecture
Feature: Add new todos
James needs to be able to jot down actions he needs to do as he
thinks of them
Scenario: Record a new todo action for future use
Given James needs to buy some milk
When James adds the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in his todo list
A goal
35. @wakaleo
The Serenity layered architecture
Feature: Add new todos
James needs to be able to jot down actions he needs to do as he
thinks of them
Scenario: Record a new todo action for future use
Given James needs to buy some milk
When James adds the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in his todo list
A goal
A task
36. @wakaleo
The Serenity layered architecture
Feature: Add new todos
James needs to be able to jot down actions he needs to do as he
thinks of them
Scenario: Record a new todo action for future use
Given James needs to buy some milk
When James adds the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in his todo list
A goal
A task
@Steps ATodoUser james;
@When(“^(?:.*) (?:adds|has added) the todo action '(.*)'$")
public void i_add_the_todo_action(String actionName) {
james.adds_an_action_called(actionName);
}
37. @wakaleo
The Serenity layered architecture
Feature: Add new todos
James needs to be able to jot down actions he needs to do as he
thinks of them
Scenario: Record a new todo action for future use
Given James needs to buy some milk
When James adds the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in his todo list
A goal
A task
@Steps ATodoUser james;
@When(“^(?:.*) (?:adds|has added) the todo action '(.*)'$")
public void i_add_the_todo_action(String actionName) {
james.adds_an_action_called(actionName);
}
The task definition
38. @wakaleo
The Serenity layered architecture
Feature: Add new todos
James needs to be able to jot down actions he needs to do as he
thinks of them
Scenario: Record a new todo action for future use
Given James needs to buy some milk
When James adds the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in his todo list
A goal
A task
@Steps ATodoUser james;
@When(“^(?:.*) (?:adds|has added) the todo action '(.*)'$")
public void i_add_the_todo_action(String actionName) {
james.adds_an_action_called(actionName);
}
The task definition
TodoPage onTheTodoHomePage;
@Step
public void adds_an_action_called(String actionName) {
onTheTodoHomePage.addAnActionCalled(actionName);
}
39. @wakaleo
The Serenity layered architecture
Feature: Add new todos
James needs to be able to jot down actions he needs to do as he
thinks of them
Scenario: Record a new todo action for future use
Given James needs to buy some milk
When James adds the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in his todo list
A goal
A task
@Steps ATodoUser james;
@When(“^(?:.*) (?:adds|has added) the todo action '(.*)'$")
public void i_add_the_todo_action(String actionName) {
james.adds_an_action_called(actionName);
}
The task definition
TodoPage onTheTodoHomePage;
@Step
public void adds_an_action_called(String actionName) {
onTheTodoHomePage.addAnActionCalled(actionName);
}
An interaction
40. @wakaleo
Serenity for Living Documentation
Feature: Add new todos
I need to be able to jot down actions I need to do as fast as I think of them
Scenario: Record a new todo action for future use
Given I need to buy some milk
When I add the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in my todo list
41. @wakaleo
Serenity for Living Documentation
Feature: Add new todos
I need to be able to jot down actions I need to do as fast as I think of them
Scenario: Record a new todo action for future use
Given I need to buy some milk
When I add the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in my todo list
46. @wakaleo
Origins of the Journey Pattern in Serenity
Antony Marcano
2007
*
* Based on actual events
47. @wakaleo
Origins of the Journey Pattern in Serenity
Antony Marcano
“Page Objects kinda suck. Why
not try this pattern instead?”
Agile Alliance Functional Test Tools Workshop 2007
2007
*
* Based on actual events
49. @wakaleo
Origins of the Journey Pattern in Serenity
Antony Marcano
2007 2009
More people should know
about this pattern
Andy Palmer
50. @wakaleo
Origins of the Journey Pattern in Serenity
Antony Marcano
2007 2009
More people should know
about this pattern
JNarrate
Andy Palmer
Let’s write a reference
implementation!
51. @wakaleo
Origins of the Journey Pattern in Serenity
Antony Marcano
2007 2009
“Coronation Street
rocks
2012
Andy Palmer
52. @wakaleo
Origins of the Journey Pattern in Serenity
Antony Marcano
2007 2009
“Coronation Street
rocks
2012
Andy Palmer
Eureka! “Soap Opera Personas”
54. @wakaleo
Andy Palmer
Origins of the Journey Pattern in Serenity
Antony Marcano
2007 2009 2012
Jan Molak
You should call this “The
Journey Pattern”
55. @wakaleo
Andy Palmer
Origins of the Journey Pattern in Serenity
Antony Marcano
2007 2009 2012
Jan Molak
You should call this “The
Journey Pattern”
Damn!
56. @wakaleo
Andy Palmer
Origins of the Journey Pattern in Serenity
Antony Marcano
2007 2009 2012
Jan Molak
You should call this “The
Journey Pattern”
Damn!
Why didn’t we
think of that!
59. @wakaleo
Andy
Palmer
Origins of the Journey Pattern in Serenity
Antony
Marcano
2007 2009 2012
Jan Molak
2015
John Smart
Serenity is cool
But it needs the
Journey Pattern
60. @wakaleo
Andy
Palmer
Origins of the Journey Pattern in Serenity
Antony
Marcano
2007 2009 2012
Jan Molak
2015
John Smart
Serenity is cool
So let’s make it
happen!
But it needs the
Journey Pattern
66. @wakaleo
The Journey Pattern - A User-Centric model
Actors have abilities I can browse the web with my
browser
I can also query REST services
67. @wakaleo
I’d like to be able to recall all
the things I need to do
The Journey Pattern - A User-Centric model
Actors perform tasks
68. @wakaleo
I’d like to be able to recall all
the things I need to do
The Journey Pattern - A User-Centric model
Actors perform tasks
I’ll add ‘Buy some milk’ to my
todo list
69. @wakaleo
I’d like to be able to recall all
the things I need to do
The Journey Pattern - A User-Centric model
Actors may interact with the system to
perform these tasks
I’ll add ‘Buy some milk’ to my
todo list
70. @wakaleo
I’d like to be able to recall all
the things I need to do
The Journey Pattern - A User-Centric model
Actors may interact with the system to
perform these tasks
I’ll add ‘Buy some milk’ to my
todo list
71. @wakaleo
I’d like to be able to recall all
the things I need to do
The Journey Pattern - A User-Centric model
Actors may interact with the system to
perform these tasks
I’ll add ‘Buy some milk’ to my
todo list
Type ‘Buy the milk’
72. @wakaleo
I’d like to be able to recall all
the things I need to do
The Journey Pattern - A User-Centric model
Actors may interact with the system to
perform these tasks
I’ll add ‘Buy some milk’ to my
todo list
Type ‘Buy the milk’
73. @wakaleo
I’d like to be able to recall all
the things I need to do
The Journey Pattern - A User-Centric model
Actors may interact with the system to
perform these tasks
I’ll add ‘Buy some milk’ to my
todo list
Type ‘Buy the milk’
Press ‘ENTER’
74. @wakaleo
I’d like to be able to recall all
the things I need to do
The Journey Pattern - A User-Centric model
Actors may interact with the system to
perform these tasks
I’ll add ‘Buy some milk’ to my
todo list
Type ‘Buy the milk’
Press ‘ENTER’
75. @wakaleo
The Journey Pattern in Serenity
Actors have goals I’d like to be able to recall all
the things I need to do
76. @wakaleo
The Journey Pattern in Serenity
Actors have goals
Feature: Add new todos
James would like to be able to recall all the things he needs to do
Scenario: Record a new todo action for future use
Given James needs to buy some milk
When James adds the todo action 'Buy some milk'
Then 'Buy some milk' should be recorded in his todo list
I’d like to be able to recall all
the things I need to do
77. @wakaleo
A User-Centric model
Actors have abilities I can browse the web with my
browser
Actor james = Actor.named(“James");
@Managed
WebDriver hisBrowser;
…
james.can(BrowseTheWeb.with(hisBrowser));
79. @wakaleo
A User-Centric model
Actors perform tasks I’ll add ‘Buy some milk’ to my
todo list
@Steps
AddItem addATodoItem;
…
james.attemptsTo(addATodoItem.called("Buy some milk"));
80. @wakaleo
A User-Centric model
Actors perform tasks
@Steps
AddItem addATodoItem;
…
james.attemptsTo(addATodoItem.called("Buy some milk"));
actor.attemptsTo(
Enter.theValue(thingToDo).into(ToDoList.NEW_TODO_FIELD),
Hit.the(RETURN).keyIn(ToDoList.NEW_TODO_FIELD)
);
81. @wakaleo
A User-Centric model
Actors perform tasks I’ll add ‘Buy some milk’ to my
todo list
@Steps
AddItem addATodoItem;
…
james.attemptsTo(addATodoItem.called("Buy some milk"));
actor.attemptsTo(
Enter.theValue(thingToDo).into(ToDoList.NEW_TODO_FIELD),
Hit.the(RETURN).keyIn(ToDoList.NEW_TODO_FIELD)
);
82. @wakaleo
A User-Centric model
Actors perform tasks I’ll add ‘Buy some milk’ to my
todo list
@Steps
AddItem addATodoItem;
…
james.attemptsTo(addATodoItem.called("Buy some milk"));
actor.attemptsTo(
Enter.theValue(thingToDo).into(ToDoList.NEW_TODO_FIELD),
Hit.the(RETURN).keyIn(ToDoList.NEW_TODO_FIELD)
);
Type ‘Buy the milk’
83. @wakaleo
A User-Centric model
Actors perform tasks I’ll add ‘Buy some milk’ to my
todo list
@Steps
AddItem addATodoItem;
…
james.attemptsTo(addATodoItem.called("Buy some milk"));
actor.attemptsTo(
Enter.theValue(thingToDo).into(ToDoList.NEW_TODO_FIELD),
Hit.the(RETURN).keyIn(ToDoList.NEW_TODO_FIELD)
);
Type ‘Buy the milk’
Press ‘ENTER’