skip to content

The screenplay (actor and task) style models an end-to-end test as an actor performing composable tasks rather than as calls on page objects. What does it change compared with page objects, and how would you decide whether adopting it is worth it for a growing suite?

level: principalimportance: nice to knowfreq 22%

answer

  1. reuse by goal, not by place
  2. tasks are values, so they compose
  3. actor can hold more than one ability
  4. vocabulary is the real cost
  5. incremental adoption or none

basics

~20 s

Screenplay reuses tasks organised around user goals instead of classes organised around screens, and composes them from small interactions. It buys composability and readable narration at the cost of more indirection, more concepts and a steeper onboarding curve.

solid answer

~60 s

Screenplay keeps the same goal as page objects — one owner for UI knowledge — but changes the unit. Instead of a class per screen holding methods, you have an actor with abilities (a browser, an API client) who performs tasks, and tasks are built from smaller interactions and questions. Reuse then follows user goals, which cross screens, rather than URLs, which do not. In practice you get three things: composition, because a task is a value you can build from other tasks; narration, because tasks are named after intent and can be reported that way; and a clean seam for non-UI abilities, so the same actor can set state through an API and then act in the browser. The costs are real: a vocabulary the team must learn, more files per behaviour, and failures that pass through more layers unless you narrate deliberately. I would adopt it for a large, long-lived suite with many cross-screen journeys and people who will maintain it, and stay with shallow component-scoped helpers otherwise.

go deeper

for a junior

Know that screenplay describes tests as an actor performing named tasks rather than as calls on per-screen classes, and that both aim to keep UI knowledge in one place.

for a middle

Explain the mechanics: tasks are composable values built from smaller tasks and interactions, so reuse follows user goals across screens instead of being confined to a single screen's class.

for a senior

Weigh the costs concretely — extra vocabulary, more files, deeper failure paths — and point out that a shallow component-scoped helper layer solves much of the same problem far more cheaply.

for a principal

Own the adoption decision: judge it on suite size, how often journeys cross screens, who maintains the tests, and whether it can land incrementally with narration wired into the report from the start.

## What the pattern actually proposes The screenplay style — sometimes called the actor or journey style — reorganises a test around four ideas: - **Actor**: who is doing this. A named participant, often with a role ("Sam, an administrator"). - **Ability**: what the actor can do. Drive a browser, call an HTTP API, read a mailbox. Abilities are how the actor reaches the system. - **Task**: a unit of user intent — "place an order", "apply a discount" — composed from smaller tasks and from primitive interactions like clicking or typing. - **Question**: something the actor can find out, whose answer a test asserts on. A test reads as `actor.attemptsTo(placeAnOrder(...))` followed by an assertion about a question. The mechanics differ between implementations, and the pattern is language-agnostic — the shape is what matters here, not any library's API. ## The real difference from page objects Both patterns exist to give UI knowledge one owner. What differs is **the axis of reuse**. A page object is organised by *place*. Reuse works when two tests visit the same screen. But real journeys cross screens — a checkout touches a catalogue page, a cart, an address form and a confirmation — and page objects give you no unit for the journey, so the composition ends up duplicated in each test or in a grab-bag "flows" helper with no design rules. A task is organised by *goal*. Because a task is a first-class value rather than a method on a class, tasks compose: `placeAnOrder` is literally built from `addToCart`, `enterShippingAddress` and `confirm`. Composition is the one capability the page object pattern does not have an answer for, and it is why the style keeps reappearing in large suites. ## Secondary benefits **Narration.** Because every task carries a name in the user's vocabulary, the executed test can be reported as a sequence of intents. That is the same diagnosability concern that hurts deep page-object hierarchies, addressed structurally rather than by convention. **Multiple abilities.** An actor can hold a browser ability and an API ability at once, so a test can arrange state through the fastest available channel and then act through the UI, without the arrangement being smuggled into a page class that has no business making HTTP calls. **Roles as data.** "An administrator" and "a read-only viewer" become actors rather than parameters threaded through helper methods, which keeps permission-shaped scenarios readable. ## The costs, stated honestly **Conceptual load.** Four new nouns, and a way of writing tests that looks unlike anything most frontend engineers have seen. On a team where e2e tests are maintained by whoever broke them, that is a genuine tax. **File count and indirection.** A behaviour that was five lines in a page object becomes a task file plus interactions. For a suite of forty tests this is pure overhead. **Failure depth.** Composition means more layers, and layers are exactly what makes a failure hard to attribute. The pattern's narration offsets this only if the team actually names tasks well and reports them. **Ecosystem risk.** The style has fewer maintained implementations than the page object approach in the JavaScript world, and adopting a thin library is a dependency decision, not just a style choice. Where support is thin, teams end up maintaining their own framework — which is a real cost to weigh, not a fatal objection. ## How I would decide I would treat it as an architecture decision with an explicit test: 1. **Do journeys cross screens often?** If most tests exercise one screen, page or component helpers already fit and screenplay buys little. 2. **How large and how long-lived is the suite?** The composition benefit scales with the number of overlapping journeys; below a few hundred tests it rarely pays back the learning curve. 3. **Who maintains it?** A dedicated quality-engineering group can absorb a vocabulary; a rotation of product engineers touching tests occasionally usually cannot. 4. **What is the failure story?** Adopt it only with narration wired into the report from day one, or you have traded one opaque abstraction for a deeper one. 5. **Can it be introduced incrementally?** Convert one journey-heavy area, keep the rest as is, and review after a quarter. A style migration that must be all-or-nothing is a bad bet. ## The answer that shows seniority The weak answer treats screenplay as an upgrade — a newer, better pattern. The strong answer identifies the *specific* deficiency it addresses (page objects have no unit for a cross-screen journey), acknowledges that a shallow component-scoped helper layer solves much of the same problem at a fraction of the cost, and makes the adoption decision on suite size, journey shape and who will maintain it — not on which pattern is more fashionable.

  • What problem do page objects genuinely have no unit for?
    The cross-screen journey. A page object gives reuse per screen, but a checkout spans several screens, so the composition of those steps has no home and gets duplicated in each test or dumped in an unstructured flows helper. Screenplay makes the journey itself a composable value, which is its core structural claim.
  • Could you get most of the benefit without adopting the full pattern?
    Often yes. Plain composable functions that take an actor-like context and return promises give you goal-shaped reuse and narration without new nouns or a framework. That middle ground captures the composition benefit at far lower conceptual cost, and is usually the right first move for a team that has outgrown page objects.
  • What would make you reject the migration outright?
    A small or short-lived suite, tests that mostly exercise one screen, or a maintenance model where product engineers touch e2e tests only when they break. In those conditions the vocabulary is never internalised, half the suite ends up in each style, and you have added indirection without collecting the composition benefit.

Page objects give you a map of the building; screenplay gives you the errands someone runs through it. When most of your tests are errands that cross several rooms, the errand is the better unit.

saying these in an interview costs you the question

  • Screenplay is simply the modern replacement for page objects
  • It removes the need to think about selectors
  • More abstraction layers always improve maintainability
  • Adopt it suite-wide in one migration for consistency
  • Any suite with more than ten tests should switch

context