ThisCalculator

Everyday

Screenplay Pattern: Test Automation Guide

Updated · Standard formula, shown below

The Screenplay Pattern structures automated UI tests around actors, tasks, and interactions, making tests more readable, maintainable, and scalable than traditional page-object models. You’ll define who does what, how they do it, and what they expect to see, then reuse those pieces across scenarios. This guide walks you through converting an existing test suite or starting fresh with Screenplay.

What You’ll Need

  • A test automation framework (e.g., Selenium WebDriver, Playwright, Cypress) with support for your chosen language (Java, C#, JavaScript, etc.)
  • An existing test project or a new one set up with your preferred build tool (Maven, Gradle, npm)
  • Basic familiarity with your testing framework’s API and with writing test cases
  • Optional: a Screenplay library such as Serenity BDD for Java, Boa for C#, or Screenplay for JavaScript (or build your own with simple classes)

Step-by-Step

  1. Define your actors. An actor represents a user role (e.g., “Customer”, “Admin”). Create an Actor class that holds a name and a reference to the browser/driver. In code, instantiate an actor with a given name and assign a WebDriver instance.
  2. Create ability classes. Abilities let an actor perform actions. For example, a “BrowseTheWeb” ability wraps the WebDriver. Implement it as a class that stores the driver and exposes methods like getDriver(). Attach abilities to actors via a method like actor.can(BrowseTheWeb.with(driver)).
  3. Implement interactions. Interactions are low-level actions like clicking a button, entering text, or waiting for an element. Create an interface Interaction with a method performAs(Actor actor). Then implement concrete classes: EnterText, ClickOn, WaitForElement. Each class takes the necessary locator or value in its constructor.
  4. Build tasks. Tasks are higher-level business actions composed of interactions. For example, “Login” might involve entering username, entering password, and clicking submit. Create a Task interface (similar to Interaction) and implement Login that takes credentials and calls the interactions in sequence.
  5. Create questions. Questions retrieve data from the UI to verify expected outcomes. Define a Question interface with a method answeredBy(Actor actor) that returns a value (e.g., String, boolean). Implement TextOf to read an element’s text, or VisibilityOf to check if an element is displayed.
  6. Write the test scenario. In your test method, instantiate an actor, give them an ability, then use actor.attemptsTo(loginTask, addToCartTask) and actor.should(seeThat(question, matcher)) to assert outcomes. Use your framework’s assertion library (e.g., Hamcrest, Jest expect) for matchers.
  7. Organize with a step library. Group your tasks and questions into reusable classes by feature area (e.g., LoginTasks, CartQuestions). This keeps the test code clean and avoids duplication.
  8. Run and iterate. Execute your tests, debug failures, and refine your interactions/tasks. As the app changes, update only the affected interaction or task, not every test.

Common Mistakes

  • Making tasks too granular – if a task only wraps a single interaction, it adds little value; keep tasks at the business level.
  • Mixing responsibilities – actors should not directly access WebDriver; that’s the job of abilities and interactions.
  • Hard-coding locators inside tests – always put locators in interactions or page components, not in the test method.
  • Forgetting to clean up state – ensure tests are independent by resetting data or using fresh browser sessions.
  • Overusing questions for everything – some checks (like page title) are better done with simple assertions in the test.

Tips

  • Start small: convert one or two test cases to Screenplay before migrating the whole suite.
  • Use naming conventions that read like natural language: LoginWithCredentials, SeeProductInCart.
  • Leverage existing Screenplay libraries to avoid reinventing the wheel, but understand the underlying concepts.
  • Keep your interactions and tasks stateless where possible – pass all data via constructor parameters.
  • Write a short README explaining how to create new actors, tasks, and questions for your team.

Troubleshooting

  • Tests fail with “element not found” – your locator may be wrong or the element appears after a delay. Add explicit waits inside the interaction (e.g., WebDriverWait) rather than in tests.
  • Actors can’t perform an action – ensure you’ve called actor.can(ability) in the test setup. Check that the ability class is correctly implemented and attached.
  • Tasks are too long or complex – break them into smaller sub-tasks. For example, a “Checkout” task can delegate to “EnterShippingInfo” and “EnterPaymentInfo”.
  • Tests are slow – review your interactions for unnecessary waits or redundant steps. Consider using a faster locator strategy (IDs over XPath).
  • Parallel execution issues – if running tests in parallel, ensure each actor gets its own WebDriver instance (thread-local).

Frequently Asked Questions

What is the difference between a task and an interaction?

An interaction is a single, low-level action (click, type, wait). A task is a sequence of interactions that accomplishes a business goal (login, add to cart, checkout). Tasks can also call other tasks.

Do I need a Screenplay library to use this pattern?

No, you can implement the core interfaces yourself. Libraries like Serenity BDD provide conveniences, but the pattern is just about organizing code with actors, tasks, and questions.

How do I handle page navigation in Screenplay?

Create a task like OpenTheApplication that uses an interaction to navigate to a URL. The actor performs that task at the start of the scenario.

Can Screenplay be used with API testing?

Yes, you can extend the pattern by giving actors an ability to call APIs (e.g., CallAnApi) and creating tasks that send requests and questions that validate responses.

Is Screenplay better than Page Object Model?

Screenplay often leads to more readable tests and better separation of concerns, but it has a steeper learning curve. For small projects, Page Object may be simpler. For large, long-lived suites, Screenplay scales well.

How do I manage test data in Screenplay?

Use a separate data layer or fixtures. Actors can be given abilities to access test data repositories, or tasks can accept data objects as parameters. Avoid hard-coding data inside tasks.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.