The
Screenplay
Pattern
A SOLID alternative
@AntonyMarcano
riverglide.com
Contributions, quotations & references in:
2
All code is…
Seriously
Hindered
In
Testing?
Inspired by Simon Stewart’s opening keynote at Selenium Conf 2016…
Knowledge of programming
All code is…
Seriously
Hindered
In
Translation?
Inspired by Simon Stewart’s opening keynote at Selenium Conf 2016…
Expressing intent
All code is…
Seriously
Hindered
In
Transformation?
Inspired by Simon Stewart’s opening keynote at Selenium Conf 2016…
Ease of refactoring
Just enough to give confidence
that the product hangs together
for the key usage examples
DON’T try to prove that
absolutely everything
works together in
absolutely every way
that the whole product
is supposed to
The Screenplay pattern is as a way of
separating any kind of interactions with your
product, including RESTful APIs, Web or
any form of interaction.
For the purposes of this talk, we’re going to
focus on page objects…
http://bit.ly/rg-todomvc
Support code using Page
Objects
Todo List Page
newTodo
todoItems
todosRemaining
toggleAllButton
clearCompletedButton
filterTodos
…
addATodoItem()
addTodoItems()
toggleAllCompleted()
filterItems()
…
Responsibilities
How to find page elements
How a user completes given tasks
Let’s go back in
time…
“Selenium is not unstable, and your tests
don’t need to be flaky. […] When your tests
are flaky, do some root cause analysis to
understand why they’re flaky. It’s very
seldom because you’ve uncovered a bug in
the test framework.”
-Simon Stewart, Google Testing Blog 2009, “My Selenium Tests Aren't
Stable!”
http://bit.ly/rg-pageobject-example
What’s wrong with this?
“A code smell is a surface indication that
usually corresponds to a deeper problem in
the system. The term was first coined by
Kent Beck while helping me with my
Refactoring book.”
-Martin Fowler
Code Smell:
“Large Class”
What can help us refactor
to a better design?
SOLID
Single Responsibility Principle
Open Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Let’s focus on…
Single Responsibility Principle
Open Closed Principle
Single Responsibility Principle
“If a class has more than one responsibility,
then the responsibilities become coupled.
Changes to one responsibility may impair or
inhibit the class’ ability to meet the others.
This kind of coupling leads to fragile designs
that break in unexpected ways when
changed.”
-Robert Martin, Agile Principles, Patterns & Practices
Open Closed Principle
The Open Closed Principle (coined by
Bertrand Meyer in Object-Oriented Software
Construction) states that a class should be
open for extension, but closed for
modification. This means that it should be
possible to extend behaviour by writing a
new class without changing existing,
working code.
http://bit.ly/rg-todomvc
Todo List Page
newTodo
todoItems
todosRemaining
toggleAllButton
clearCompletedButton
filterTodos
…
addATodoItem()
addTodoItems()
toggleAllCompleted()
filterItems()
…
Responsibilities
How to find page elements
How a user completes given tasks
Todo List Page
newTodo
todoItems
todosRemaining
toggleAllButton
clearCompletedButton
filterTodos
…
addATodoItem()
addTodoItems()
toggleAllCompleted()
filterItems()
…
TodoListPage
newTodo
todoItems
todosRemaining
toggleAllButton
clearCompletedButton
filterTodos
…
TodoListTasks
addATodoItem()
addTodoItems()
toggleAllCompleted()
filterItems()
…
Extract Class
Extract Class
Todo List Page
newTodo
todoItems
todosRemaining
toggleAllButton
clearCompletedButton
filterTodos
…
addATodoItem()
addTodoItems()
toggleAllCompleted()
filterItems()
…
AddNewTodo
newTodo
addTodoItem ()
addTodoItems()
MaintainTodos
toggleAllButton
clearCompletedButton
toggleAllCompleted()
clearAllCompletedTodos()
Extract Class
Extract Class
Todo List Page
newTodo
todoItems
todosRemaining
toggleAllButton
clearCompletedButton
filterTodos
…
addATodoItem()
addTodoItems()
toggleAllCompleted()
filterItems()
…
TodoListPage
newTodo
todoItems
todosRemaining
toggleAllButton
clearCompletedButton
filterTodos
…
AddATodoItem
perform()
Extract Class
Replace Method
with Method Object
AddTodoItems
perform()
ToggleAllCompleted
perform()
What are we modeling?
Modelling the problem
Not the solution
The Screenplay Pattern
There are actors.
Actors have abilities.
Actors perform tasks…
Tasks involve ‘actions’
Things we interact with are just data
Instead of a few
large classes,
you have more
smaller classes.
When you identify
a new task an
actor must
perform, just add
a new task class.
You don’t have to use cucumber for this either…
Example using Screenplay implementation in Serenity-BDD
Your scenario is a narrative for a cast of
actors, each playing a different role. Each
actor has the task of performing action to
the best of their ability…
The Screenplay Pattern
The Screenplay Pattern
Before you begin
Don’t aim to refactor all of your support
code.
Try an experiment alongside what you have.
See how it feels and if you like it, look at
how to use the approach with new
scenarios.
In Summary
• As any support code grows, ask first “are
we testing too much here?”
• Big classes with interaction methods (like
PageObjects) are useful as training
wheels
• As we try to go faster, training wheels
make us less stable
• The Screenplay Pattern allows us to ride
more safely, at speed, from the start
Links
Full article: bit.ly/rg-screenplay
Examples on Github: bit.ly/rg-serenity-eg
using Serenity
Acknowledgements
Andy Palmer
John Ferguson Smart & Jan Molak
Contact: antony@riverglide.com
http://antonymarcano.com/blog
@AntonyMarcano
Materials created with the time, love and attention of
Antony Marcano and Andy Palmer

Refactoring page objects The Screenplay Pattern