How To Automate: Understanding Screenplay – Myths & Fundamentals

Welcome to our latest series of How To articles on EuroSTAR Huddle. This three part series is on Screenplay and is brought to you by Matt Wynne, one of the world’s leading BDD practitioners and co-founder of Cucumber.

Part 1

Once you’ve decided to invest in test automation, sooner or later you’ll begin to realise that you need to care about the maintainability of that test automation code just as much as you do about the implementation code itself.

For acceptance tests this problem is particularly acute: driving the application from its outside edges involves connecting to APIs, databases, web UIs etc., and this code can quickly get out of hand. Having tried several different approaches myself over the years, I’ve come to believe that the Screenplay pattern is the best technique we have today.

But it doesn’t get the attention it deserves.

If you’ve never heard of Screenplay, or have heard of it but never tried it, this series of posts is for you. They will be technical posts, with a good deal of code in them. The code will be in JavaScript, but I hope you’ll be able to follow it if you’re familiar with coding in any other language too.

In this first post I want to start by addressing a couple of popular misconceptions about the pattern, and give you a quick view of the fundamentals, to help frame the rest of the series.


Myth #1: Screenplay is for testing screens

Many people I’ve talked to about Screenplay have heard the word “screen”, or read the blog posts contrasting it with the page object pattern, and assumed it must be only for UI testing. That’s not the case.

The folks behind the screenplay pattern love a metaphor.

The metaphor here is not about screens from the user interface of your app, no! The metaphor is that each of your scenarios is like a little stage-play, with actors performing actions.


In fact, as we’ll see through this series, the whole idea is to get away from thinking about interaction details, and focus on behaviour and intent.

In retrospect, maybe something like Playwright might have made a better name for this pattern to avoid any confusion caused by conflated interpretations of the word “screen”. Anyway, it’s too late for that now.

So let’s be totally clear. The Screenplay pattern does not have anything to say about whether you test through your UI or not. In fact, Screenplay can help free you up from this hideous bind, and give you more choices about where to connect to your app, and keep your code better organised.

Myth #2: Screenplay is over-complicated

I’ll admit that this was my reaction at first. Even though I had a strong feeling there was something useful in this pattern, I found all the early examples I read to be quite hard to fathom, with a lot of new concepts to understand. It all made me feel a bit stupid.

Having got my head around it now, I can tell you for sure that there’s a super-simple core idea here. Essentially, Screenplay is just the command pattern applied in the specific context of organising test automation code.

In fact, I bet that if you’ve worked on a test automation suite of any reasonable size, you’ll know exactly what over-complicated feels like. Massive classes heaving with too many methods. Awkward hierarchies of objects to try and avoid duplication. A maze of different files.

This pattern is a way out of that.

If I’ve done my job right, then by the end of this series you’ll see that it’s really not that complicated at all.

The fundamentals of Screenplay

The fundamental element of the Screenplay pattern is an Interaction. Instead of having the code that interacts with our app littered around in helper methods or page objects, we separate and encapsulate each tiny granule of work as an individual object, each with the same interface: a single method that allows us to run that action against our app.

For example, you might have an Interaction like InsertInto which knows how to insert a record into an SQL database table. Or you might have an Interaction like WriteTo that can write to a text file on disk. Or an Interaction like FillIn which can put text into a field in a browser. Or an Interaction like PostJson that sends a payload to an API endpoint.

Then, we express the behaviour we want in our tests by creating lists of these Interaction objects that we want to execute, like:

cucumber studio understanding screenplay

We can create factory DSLs to make this code read better:

cucumber studio understanding screenplay

The sweet thing about breaking down our automation into these tiny pieces is that it allows us to compose these little Interactions into bigger chunks (called Tasks) that make sense in our particular problem domain:

cucumber studio understanding screenplay

The basic shift in thinking that you’ll need to grasp in order to understand the Screenplay pattern is this: all of your automation behaviour is going to be organised into little elemental pieces instead of being in methods on helper classes.

Screenplay doesn’t have to be something you can only introduce into your next greenfield project. We’ve successfully introduced Screenplay side-by-side with existing automation code, gradually refactoring towards it.

Over the course of this series of posts, we’ll refactor take a typical Cucumber codebase and refactor it towards this pattern, extracting and develop our own little Screenplay library as we go. In doing this, you’ll get a firm handle on how to apply the pattern yourself.

Stay tuned!

In the Understanding Screenplay series:

Part 1: Myths & Fundamentals

Part 2: Help! Maybe my helpers aren’t so helpful after all?

Part 3: Refactoring to Screenplay

See other Test Automation Resources on EuroSTAR Huddle.

About the Author

Matt Wynne

In 2008 Matt joined the Cucumber open source project as a developer. In 2011 The Cucumber Book was published which he co-authored with Aslak Hellesøy. In 2013 he co-founded Cucumber Ltd, dedicated to inspiring meaningful and effective collaboration in every software organisation. Cucumber Ltd was acquired by SmartBear in June 2019, and Matt now works as a BDD Advocate, working to spread good software development and agile testing practices around the world.
Find out more about @mattwynne