The Screenplay Pattern¶
What Is It?¶
The Screenplay pattern is an approach to writing automated acceptance tests that models your tests around Actors who perform Tasks and ask Questions about the system under test. It replaces the widely used Page Object Model with a more flexible, composable, and human-readable architecture.
In the Screenplay pattern, tests read like natural descriptions of user behavior:
ali.attempts_to(Login.with_credentials("admin", "secret123"))
ali.should_see_that(DashboardTitle(), "Welcome, Ali")
History¶
The Screenplay pattern evolved from the Journey pattern, introduced by Antony Marcano, Andy Palmer, Jan Molak, and John Ferguson Smart around 2015. It was first implemented in the Serenity BDD framework for Java and later ported to JavaScript (Serenity/JS).
Screenwright brings these ideas to the Python ecosystem, adapted to Python's conventions and integrated with pytest-bdd.
Why Screenplay Over Page Object Model?¶
The Page Object Model (POM) groups methods by page or component. This leads to several problems at scale:
| Problem | Page Object Model | Screenplay Pattern |
|---|---|---|
| God objects | Page objects accumulate dozens of methods | Tasks and Questions are small, single-purpose classes |
| Poor reuse | Logic is trapped inside a specific page object | Tasks compose other Tasks and Interactions freely |
| Unclear intent | loginPage.enterUsername("admin") describes mechanics |
actor.attempts_to(Login.with_credentials(...)) describes goals |
| Rigid coupling | Tests depend on page structure | Tests depend on business capabilities (Abilities) |
| Hard to narrate | No built-in test narration | Every action produces a domain event for reporting |
The Six Key Concepts¶
The Screenplay pattern is built around six concepts:
performs
Actor --------------------------> Task
| |
| has | composed of
v v
Ability Interaction
| |
| enables | acts on
v v
Fact System Under Test
^
| answers
Question
1. Actor¶
An Actor represents a user or external system interacting with your application. Each Actor has a name and optionally a description of their role.
2. Ability¶
An Ability is a capability that an Actor possesses -- for example, the ability to browse the web, call an API, or query a database. Abilities are granted to Actors and retrieved by type.
3. Task¶
A Task is a high-level, business-meaningful goal that an Actor wants to achieve. Tasks can be composed of other Tasks and Interactions.
4. Interaction¶
An Interaction is an atomic, low-level action. Interactions are the leaf nodes of the action tree -- they directly manipulate the system under test through an Ability.
5. Question¶
A Question queries the current observable state of the system. Actors ask Questions and verify the answers against expected values or predicates.
6. Fact¶
A Fact is a piece of information that an Actor remembers. Facts are stored as key-value pairs and recalled later during a scenario.
How Screenwright Implements It¶
Screenwright provides base classes and protocols for each concept:
| Concept | Base Class / Protocol | Module |
|---|---|---|
| Actor | Actor |
screenwright.core.actor |
| Ability | Ability |
screenwright.core.ability |
| Task | Task / @task |
screenwright.core.task |
| Interaction | Interaction |
screenwright.core.interaction |
| Question | Question / @question |
screenwright.core.question |
| Performable | Performable (Protocol) |
screenwright.core.performable |
| Answerable | Answerable (Protocol) |
screenwright.core.answerable |
| Stage | Stage |
screenwright.core.stage |
| Scene | Scene |
screenwright.core.scene |
| Spotlight | Spotlight |
screenwright.core.spotlight |
Every action an Actor takes emits a domain event (for example, TaskStarted, TaskCompleted, QuestionAnswered). These events feed into Screenwright's reporting system to produce the cinematic HTML report.