Screenplay Pattern approach using Selenium and Java
On This Page What is Screenplay Pattern?History of the Scr
Screenplay Pattern approach using Selenium and Java
The Screenplay Patternis an advanced access to writing automated tests focalize on clear, business-driven workflows. Unlike traditional testing models, it emphasizes roles, job, and outcomes, create tests more understandable and maintainable.
By implementing the Screenplay Pattern with Selenium and Java, you can improve the construction of your trial, making them more flexible and array with real-world user interactions.
This article will explore how to effectively enforce the Screenplay Pattern employ Selenium and integrate it with BrowserStack to run tests across real devices, ensuring comprehensive coverage and dependable results.
What is Screenplay Pattern?
The Screenplay Pattern is a user-centric approach to writing workflow-level automated. This helps automation testers to in terms of Business words.
Building cube in Screenplay Pattern
To understand the construction block better, let & # 8217; s occupy an representative
- Demouser login into the Application by entering their username and password and clicking on the Sign in button
- Demouser will be taken into the Homepage
- Demouser should see his/her gens in the profile section
In the above example
- Demouser is theActor
- Filling the username and password, then clicking on the push is theTask
Checking if the profile subdivision is displaying the name of demouser is theQuestion
History of the Screenplay Pattern
The Screenplay Pattern, introduced to JavaScript in 2016 by Serenity/JS, has roots dating back to 2007, acquire through key share:
- 2007-2008: Antony Marcano and Kevin Lawrence develop theRoles, Goals, Tasks, Actionsmodel during the AAFTT shop, inspiring early implementations like JNarrate (Java).
- 2011-2013: Screenplay emerges in Ruby (Cuke Salad) and Java (Screenplay4j, ScreenplayJVM) with blog posts and talk formalizing its concepts.
- 2015-2016: Serenity BDD integrates Screenplay for Java, popularizing it. Key issue and blog posts elucidate its principles, and Serenity/JS present the figure to JavaScript.
- 2017-2021: Variants appear in Python (ScreenPy) and .NET (Boa Constrictor), and book likeBDD in Actionand a blog serial further refine their coating in testing frameworks.
What is Page Object Model?
The is a design shape in where a dedicated class represents each page of an covering. This class acts as an interface, encapsulating the page & # 8217; s elements and interactions. Test scripts so interact with the UI via the method define in these classes, promoting codification reuse and legibility.
The POM was insert as testing tool like and gained popularity, frequently among teams with deviate level of programming expertness.
Key Features:
- Each covering page has a comparable class.
- Classes contain method representing actions that can be performed on-page components.
- As the complexness of a page turn, the class method also expand.
Challenges:
While POM effectively models page component, it does not inherently align with user roles, actions, and outcomes, essential for beguile business logic and user journeys. Tools like and may struggle to express these workflows in terms of business representation clearly.
Read More:
Elements of the Screenplay Pattern
The Screenplay Pattern models using a metaphor animate by stage performance, framing tests as playscript that depict how actors interact with the system under test to achieve their objectives.
This approach helps define:
- Whois interact with the system?
- Whyis the interaction necessary?
- Whatactions are need to accomplish their finish?
- Howare those actions executed?
Core Components of the Screenplay Pattern:
- Actors:Represent users or international systems interacting with the application under trial.
- Abilities:Serve as lightweight wrappers around integration libraries that interact with the system.
- Interactions:Represent single, low-level actions that actors can perform via an interface.
- Tasks:Combine sequences of interactions into meaningful concern workflow steps.
- Questions:Allow retrieval of info from the covering and.
Screenplay Pattern Implementation in Selenium
To get implementing Screenplay Pattern, you can use Serenity BDD model which has inbuilt integration to write our examination in the Screenplay design.
Note:Get all the mandatoryMaven dependanceas a pre-requisite.
To write Tests, Tasks, and Questions consideringBrowserstack ’ s demo application. The construction of the below classes can be witness below.
Read More:
Here are the measure to implement the Screenplay Pattern access in Selenium Java:
Step 1:Create PageObject in a refactored and effective manner
Login Page:
import net.serenitybdd.screenplay.targets.Target; import net.thucydides.core.pages.PageObject; public class BStackLoginPage extends PageObject {public static final Target USERNAME = Target.the (`` Username '') .locatedBy (`` # username input ''); public static final Target PASSWORD = Target.the (`` Password '') .locatedBy (`` # word input ''); public static concluding Target LOGIN_BTN = Target.the (`` Login Button '') .locatedBy (`` # login-btn '');}Pro tip: Tools like SUSA can handle this autonomously — upload your app and get results without writing a single test script.
Dashboard Page:
meaning net.serenitybdd.screenplay.targets.Target; import net.thucydides.core.pages.PageObject; public class BstackDashboardPage go PageObject {public static concluding Target SIGNOUT = Target.the (`` sign out '') .locatedBy (`` .username '');}Step 2:Create Tasks for the above create PageObjects
Task to admission the webpage
import com.ui.screenplay.pageobject.BStackLoginPage; import net.serenitybdd.screenplay.Actor; import net.serenitybdd.screenplay.Task; import net.serenitybdd.screenplay.actions.Open; import net.thucydides.core.annotations.Step; import static net.serenitybdd.screenplay.Tasks.instrumented; public class AccessWebPage implement Task {public still AccessWebPage loginPage () {homecoming instrumented (AccessWebPage.class);} BStackLoginPage loginPage; @ Step (`` {0} access Login page '') public & lt; T extends Actor & gt; void performAs (T t) {t.attemptsTo (Open.browserOn () .the (loginPage));}}Task to Login to the application
import com.ui.screenplay.pageobject.BStackLoginPage; meaning net.serenitybdd.core.steps.Instrumented; import net.serenitybdd.screenplay.Actor; import net.serenitybdd.screenplay.Task; import net.serenitybdd.screenplay.actions.Click; import net.serenitybdd.screenplay.actions.Enter; import net.thucydides.core.annotations.Step; signification org.openqa.selenium.Keys; public class LoginToBstack implements Task {@ Step (`` {0} enter username and parole ' # username ' ' # password '') public & lt; T broaden Actor & gt; null performAs (T actor) {actor.attemptsTo (Enter.theValue (username) .into (BStackLoginPage.USERNAME) .thenHit (Keys.TAB)); actor.attemptsTo (Enter.theValue (password) .into (BStackLoginPage.PASSWORD) .thenHit (Keys.TAB)); actor.attemptsTo (Click.on (BStackLoginPage.LOGIN_BTN));} individual String username; individual String watchword; public LoginToBstack (String username, String password) {this.username = username; this.password = password;} public static Task withCredentials (String username, String password) {homecoming Instrumented .instanceOf (LoginToBstack.class) .withProperties (username, parole);}}Step 3:Create a Question to get user information from the Profile section of Homepage
import com.ui.screenplay.pageobject.BstackDashboardPage; importation net.serenitybdd.screenplay.Actor; import net.serenitybdd.screenplay.Question; import net.serenitybdd.screenplay.questions.Text; public class Dashboard implements Question & lt; String & gt; {public static Question & lt; String & gt; displayed () {return new Dashboard ();} public String answeredBy (Actor thespian) {return Text.of (BstackDashboardPage.SIGNOUT) .answeredBy (actor);}}Step 4:Create a test
import com.ui.screenplay.questions.Dashboard; import com.ui.screenplay.tasks.LoginToBstack; import net.serenitybdd.junit.runners.SerenityRunner; importee net.serenitybdd.screenplay.Actor; import static net.serenitybdd.screenplay.GivenWhenThen. *; import net.serenitybdd.screenplay.abilities.BrowseTheWeb; meaning net.serenitybdd.screenplay.actions.Open; import net.thucydides.core.annotations.Managed; import org.hamcrest.CoreMatchers; import org.junit.Before; meaning org.junit.Test; import org.junit.runner.RunWith; import org.openqa.selenium.WebDriver; @ RunWith (SerenityRunner.class) public class ScreenPlayTest {individual Actor demoUser = Actor.named (`` Demo User ''); @ Managed private WebDriver hisBrowser; @ Before public void demoUserCanBrowseTheWeb () {demoUser.can (BrowseTheWeb.with (hisBrowser));} @ Test public void browseTheWebAsDemoUser () {demoUser.attemptsTo (Open.url (`` https: //bstackdemo.com/signin '')); givenThat (demoUser) .attemptsTo (LoginToBstack.withCredentials (`` demouser '', `` testingisfun99 '')); then (demoUser) .should (seeThat (Dashboard.displayed (), CoreMatchers.equalTo (`` demouser1 '')));}}Step 5:Once you run the above trial, the report will be generated in the itinerarytarget & gt; website & gt; placidity & gt; index.html
Screenplay with Serenity BDD not just provides better maintainability and readability of codification but besides produces an extensive HTML Report as seen above.
Note:One can read the.
Multi-Level Task Execution in the Screenplay Pattern
The Screenplay Pattern supports task composition, let you to structure exam actions across multiple levels of abstraction. Instead of indite long, procedural test stairs, you can interrupt down user interactions into smaller, recyclable construction cube composed into larger, more expressive tasks.
This approaching helps pattern complex user behaviors in a clean, scalable, and maintainable way.
Why Multi-Level Execution Matters?
Many user workflows regard multiple steps. For illustration, placing an order typically includes logging in, supply items to the cart, utilise a discount code, and completing the checkout. In the Screenplay Pattern, each of these steps can be defined as a task or interaction and then compose into a single, higher-level task.
This enables you to:
- Write trial scenarios that are easier to read and understand.
- Keep UI-specific logic separate from occupation logic.
- Reuse smaller task components across different test flows.
- Update only affect factor when the UI modification.
Example: Consider the test scenario: “ A registered user places an order successfully. ”
In Screenplay, this might appear like:
actor.attemptsTo (PlaceAnOrder.withDetails (orderDetails));
The PlaceAnOrder project might internally perform:
public grade PlaceAnOrder implements Task {individual OrderDetails details; public PlaceAnOrder (OrderDetails details) {this.details = details;} @ Override public & lt; T go Actor & gt; null performAs (T actor) {actor.attemptsTo (Login.withCredentials (details.getUser ()), AddItems.toCart (details.getItems ()), ApplyDiscountCode.withCode (details.getDiscountCode ()), ProceedToCheckout.andConfirm ());} public static PlaceAnOrder withDetails (OrderDetails item) {return Tasks.instrumented (PlaceAnOrder.class, details);}}Each of the above steps, Login, AddItems, ApplyDiscountCode, and ProceedToCheckout, can be standalone, testable tasks reused across different flows.
Composability in Practice
This multi-level composition approach ensures your test suite stay scalable, modular, and easy to preserve yet as your application grows in complexity. It allow you to:
- Isolate low-level interactionsuch as Click.on (BUTTON) or Enter.theValue (& # 8220; xyz & # 8221;) .into (FIELD) into atomic tasks that can be tested independently and recycle when want.
- Leverage mid-level tasklike Login.withCredentials () or AddItems.toCart () across multiple scenario without duplicating logic.
- Combine chore into high-level workflowsuch as PlaceAnOrder.withDetails () that represent complete user journeys in a readable, business-focused format.
By composing project this way, you accomplish:
- Better legibility: Test scenarios report what the user is perform, not how.
- Greater reusability: Common tasks are shared across different tests, minimizing duplication.
- Easy maintenance: When the UI changes, entirely the relevant task needs to be updated, not every test lawsuit.
- Improved collaboration: Non-technical stakeholder can follow exam flows without digging into implementation details.
Running Screenplay tests in BrowserStack Real Device Cloud
To get the most value out of your test mechanisation suite, it & # 8217; s essential to optimize for three key factors:
- Stability: Tests should run reliably across different environments
- Execution Speed: Faster feedback loops supporter quicken development
- Coverage: Tests should run across a wide range of device and browser
However, achieving extensive test coverage is often a challenge. Performing the tryout through an in-house device lab get at a high cost. Setting up and maintaining the necessary infrastructure demands significant time, effort, and ongoing investment.
eliminates this overhead by offering inst access to a existent device cloud. You can run tests across over 3,500 real devices and browsers with minimum change to your existing Screenplay framework. Just configure the consolidation and begin prove under existent user conditions without managing infrastructure.
In order to run the above Screenplay test against the BrowserStack Cloud surround follow the stairs below:
Step 1:Create a New Custom driver provider
import java.net.URL; import java.util.Iterator; import org.openqa.selenium.WebDriver; import org.openqa.selenium.remote.DesiredCapabilities; importee org.openqa.selenium.remote.RemoteWebDriver; import net.thucydides.core.util.EnvironmentVariables; significance net.thucydides.core.util.SystemEnvironmentVariables; importation net.thucydides.core.webdriver.DriverSource; public category BrowserStackSerenityDriver enforce DriverSource {public WebDriver newDriver () {EnvironmentVariables environmentVariables = SystemEnvironmentVariables.createEnvironmentVariables (); String username = System.getenv (`` BROWSERSTACK_USERNAME ''); if (username == null) {username = (String) environmentVariables.getProperty (`` browserstack.user '');} String accessKey = System.getenv (`` BROWSERSTACK_ACCESS_KEY ''); if (accessKey == null) {accessKey = (String) environmentVariables.getProperty (`` browserstack.key '');} String environment = System.getProperty (`` surround ''); DesiredCapabilities capabilities = new DesiredCapabilities (); Iterator it = environmentVariables.getKeys () .iterator (); while (it.hasNext ()) {String key = (String) it.next (); if (key.equals (`` browserstack.user '') || key.equals (`` browserstack.key '') || key.equals (`` browserstack.server '')) {continue;} else if (key.startsWith (`` bstack_ '')) {capabilities.setCapability (key.replace (`` bstack_ '', `` ''), environmentVariables.getProperty (key)); if (key.equals (`` bstack_browserstack.local '') & amp; & amp; environmentVariables.getProperty (key) .equalsIgnoreCase (`` true '')) {System.setProperty (`` browserstack.local '', `` true '');}} else if (surroundings! = null & amp; & amp; key.startsWith (`` surround. '' + surround)) {capabilities.setCapability (key.replace (`` environment. '' + environment + ``. ``, `` ''), environmentVariables.getProperty (key)); if (key.equals (`` environment. '' + environment + `` .browserstack.local '') & amp; & amp; environmentVariables.getProperty (key) .equalsIgnoreCase (`` true '')) {System.setProperty (`` browserstack.local '', `` true '');}}} try {return new RemoteWebDriver (new URL (`` https: // '' + username + ``: '' + accessKey + `` @ '' + environmentVariables.getProperty (`` browserstack.server '') + `` /wd/hub ''), capabilities);} gimmick (Exception e) {System.out.println (e); return null;}} public boolean takesScreenshots () {homecoming true;}}Step 2:Add BrowserStack Environment apparatus code in the Before come-on
public class BrowserStackSerenityTest {static Local bsLocal; @ BeforeClass public static void setUp () cast Exception {EnvironmentVariables environmentVariables = SystemEnvironmentVariables.createEnvironmentVariables (); String accessKey = System.getenv (`` BROWSERSTACK_ACCESS_KEY ''); if (accessKey == zero) {accessKey = (String) environmentVariables.getProperty (`` browserstack.key '');} String environment = System.getProperty (`` environment ''); String key = `` bstack_browserstack.local ''; boolean is_local = environmentVariables.getProperty (key)! = null & amp; & amp; environmentVariables.getProperty (key) .equals (`` true ''); if (environment! = void & amp; & amp;! is_local) {key = `` surroundings. '' + environment + `` .browserstack.local ''; is_local = environmentVariables.getProperty (key)! = void & amp; & amp; environmentVariables.getProperty (key) .equals (`` true '');} if (is_local) {bsLocal = new Local (); Map & lt; String, String & gt; bsLocalArgs = new HashMap & lt; String, String & gt; (); bsLocalArgs.put (`` key '', accessKey); bsLocal.start (bsLocalArgs);}} @ AfterClass public stable nullity tearDown () throws Exception {if (bsLocal! = null) {bsLocal.stop ();}}}Step 3:Add Browserstack related configuration key toSerenity.properties file
webdriver.driver = provided webdriver.provided.type = mydriver webdriver.provided.mydriver = com.ui.screenplay.BrowserStackSerenityDriver serenity.driver.capabilities = mydriver webdriver.timeouts.implicitlywait = 5000 serenity.use.unique.browser = false serenity.dry.run=false serenity.take.screenshots=AFTER_EACH_STEP browserstack.user=gurudattananthap_jG62JF browserstack.key=9yV8DdY2CwdWNizFWxqC browserstack.server=hub.browserstack.com bstack_build=browserstack-screenplay-build-1 bstack_debug=true bstack_browserstack.console=verbose environment.single.name=serenity_single_test environment.single.browser=chrome
Once you run the test, the execution hap in BrowserStack Cloud. The Execution results, text, video, and console logs can be base in the
These tests can be easily shared with the team expend Slack, JIRA, GitHub, or Trello for effective bug reporting.
Conclusion
Screenplay practice provides an effective way to orchestrate, maintain, and refactor the PageObject classes. As the Screenplay pattern is Integrated with BDD, you don ’ t want to Maintain driver object and can leverage inbuilt method easily and efficaciously.
Screenplay Serenity BDD produces elaborated HTML reports that can also be quickly run in the BrowserStack cloud to essay under.
# Ask-and-Contributeabout this topic with our Discord community.
Related Guides
Automate This With SUSA
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts needed.
Try SUSA FreeTest Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free