Utility class of POM: Screenplay Pattern

Utility class of POM: Screenplay Pattern

posted 4 min read

Understanding the Screenplay Pattern in Test Automation

Test automation often starts simple a few UI actions, maybe a Page Object or two. But as the system grows, maintaining and scaling those tests becomes a real challenge.

Enter the Screenplay Pattern: a powerful, actor-based model for writing clean, reusable, and maintainable tests.

What is the Screenplay Pattern?

The Screenplay Pattern is a test automation design pattern that models test scripts like a movie script involving Actors, Tasks, Abilities, Interactions, and Questions.

It encourages us to:

  • Think in terms of what the actor does, not how
  • Build modular, readable, and reusable test logic
  • Focus on behavior rather than implementation

Key Building Blocks

Actor

Represents the user or persona interacting with the system.

Actor yusuf = Actor.named("Yusuf").whoCan(BrowseTheWeb.with(driver));

Task

A meaningful action or series of steps the actor performs.

public class Login implements Task {
    public static Login withCredentials(String username, String password) {
        return instrumented(Login.class, username, password);
    }

    public <T extends Actor> void performAs(T actor) {
        actor.attemptsTo(
            Enter.theValue(username).into(USERNAME_FIELD),
            Enter.theValue(password).into(PASSWORD_FIELD),
            Click.on(LOGIN_BUTTON)
        );
    }
}

Usage:

yusuf.attemptsTo(Login.withCredentials("admin", "1234"));

Question

Used to extract information from the system, like validations or assertions.

public class WelcomeMessage implements Question<String> {
    public String answeredBy(Actor actor) {
        return Text.of(WELCOME_MESSAGE_LOCATOR).viewedBy(actor).asString();
    }
}

Usage:

String message = yusuf.asksFor(new WelcomeMessage());

Ability

Defines what the actor can do. For example, browse the web or call APIs.

BrowseTheWeb.with(driver); // Enables web interactions

Target: Screenplay’s Way of Handling Locators

If you stuck with POM and cant quit completely(like me) you can still integrate it to your POM too. Instead of using Page Object Model and WebElements, the Screenplay Pattern uses Target objects to define locators.

In traditional POM:

@AndroidFindBy(accessibility = "Login Screen")
public WebElement loginScreen;

In Screenplay:

public final class LandingPage {

    private LandingPage() {} // Prevent instantiation

    public static final Target LOGIN_SCREEN = Target.the("Login screen")
        .locatedByAccessibilityId("Login Screen");

    public static final Target ECHO_BOX_SCREEN = Target.the("Echo Box screen")
        .locatedByAccessibilityId("Echo Box");

    public static final Target LIST_DEMO_SCREEN = Target.the("List Demo screen")
        .locatedByAccessibilityId("List Demo");

    public static final Target LIST_DATE_SCREEN = Target.the("Date Picker screen")
        .locatedByAccessibilityId("Picker Demo");

    public static final Target WEBVIEW_SCREEN = Target.the("WebView screen")
        .locatedByAccessibilityId("Webview Demo");
}

And in your tasks:

actor.attemptsTo(
    Click.on(LandingPage.LOGIN_SCREEN)
);

Benefits:

  • No need for PageFactory or WebElement instantiation
  • Targets are static, so they can be reused anywhere
  • Fully integrates with Screenplay’s task-based structure

If you're using Appium with Serenity, you can also use:

Target LOGIN_SCREEN = Target.the("Login screen")
    .located(MobileBy.AccessibilityId("Login Screen"));

Benefits of Screenplay Pattern

  • Improved readability (tests look like real scenarios)
  • High reusability (Tasks & Questions are shared across tests)
  • Better scalability for growing test suites
  • Strong adherence to SOLID principles

If you notice classes not using extends keyword for inheritance.(Congrats you are detail-oriented person) Because Screenplay prefers Composition over Inheritance.

Inheritance in Page Object Model vs. Implementation in Screenplay Pattern

One of the key architectural differences between the Page Object Model (POM) and the Screenplay Pattern lies in their use of object-oriented principles—specifically, inheritance versus implementation.

Page Object Model: Inheritance-Based Structure

In POM, it is common to use inheritance via the extends keyword. Typically, a base class (e.g., BasePage) is created to house shared functionalities such as clicking elements, sending input, or waiting for elements. All page classes then extend this base class to inherit these methods. This approach promotes code reuse but can lead to tightly coupled and less flexible designs.

public class BasePage {
    public void click(WebElement element) {
        element.click();
    }
}

public class LoginPage extends BasePage {
    WebElement loginButton;
}

Screenplay Pattern: Interface Implementation

Screenplay, on the other hand, follows a more composition-driven design by using interfaces like Task, Question, or Interaction, which are implemented rather than extended. This provides greater flexibility and promotes the principle of "composition over inheritance."

Each Actor performs actions by executing these Tasks or Questions, making the codebase more modular and maintainable.

public class Login implements Task {
    private final String username;
    private final String password;

    public static Login withCredentials(String username, String password) {
        return Tasks.instrumented(Login.class, username, password);
    }

    @Override
    public <T extends Actor> void performAs(T actor) {
        actor.attemptsTo(
            Enter.theValue(username).into(LoginPage.USERNAME_FIELD),
            Enter.theValue(password).into(LoginPage.PASSWORD_FIELD),
            Click.on(LoginPage.LOGIN_BUTTON)
        );
    }
}

While POM is easier to grasp and implement for smaller test suites, the Screenplay Pattern offers a more scalable and maintainable architecture for complex testing needs.


Comparison: POM vs Screenplay

Feature Page Object Model Screenplay Pattern
Structure Page-based Actor-based
Code Reuse Inheritance Composition
Reusability Moderate High
Readability Good Excellent
MaintainabilityChallenging in large projects Easier due to modularity
Test Style Imperative Declarative
Design Focus Pages & Elements Tasks & Behaviors

Final Thoughts

The Screenplay Pattern takes a bit of setup at the beginning, because its a approach rather than ready-to-use methods.(Serenity Library comes with that methods!) but the benefits in clarity, reusability, and scalability are huge especially in large automation projects. If you're building or maintaining a serious test framework, it's worth giving Screenplay a try!

Thanks for reading.

If you read this far, tweet to the author to show them you care. Tweet a Thanks

Really nice write-up! You explained the Screenplay Pattern in a way that actually makes sense without overcomplicating it. Quick question—have you ever hit any roadblocks while switching from POM to Screenplay in a real project? Would love to hear how you handled that.

Yes and i dont suggest transition, especially if you have hundreds of test cases.

The main challenge is changing your mindset, rather than change your OOP(interfaces, static fields). Code is more abstract and can be challenging to understand backend of the method chain like which part comes from where.

Also documentation and support is really low if you struggle with anything, so you need to have good AI prompt skills.

And lastly your team probably wont adapt and will try to give up.

If you are going to start from scratch then you can do it with less headache.

More Posts

3 Pillars of Testing: How to be a good tester?

bugnificent - Apr 7

How to use Builder design Pattern for test data generation in automation testing

Faisal khatri - Oct 14, 2024

How to Achieve Automated Testing Within Sprint?

Shivam Bharadwaj - Feb 6

Facade Pattern provides a simplified interface to complex subsystems, hiding implementation details behind a clean API.

Hussein Mahdi - Apr 9

Understanding the Observer Pattern in C# with IObservable and IObserver

Spyros - Mar 11
chevron_left