Playwright-Java (Part-1): Getting Started with TestNg and Gradle

Sudarshan
5 min readMay 12, 2022

--

What is Playwright?

Playwright is a framework for web testing and automation. It allows testing Chromium, Firefox, and Webkit with a single API. It’s built to enable cross-browser automation that is reliable and fast.

Why Playwright?

There are N number of automation libraries being built and used, why should someone choose playwright over them? Rather than comparing Playwright with some of the popular alternatives, check out Why Playwright to understand the capabilities offered by Playwright.

How to configure Playwright and make the tests Thread-Safe?

Playwright-Java is not thread-safe. Read more about this here. Let’s try to solve this with a different approach using Google Guice dependency injection and TestNg hooks.

  • If you are not familiar with Google Guice, watch this awesome playlist on YouTube. Read more about dependency injection with Guice here.
  • Read about TestNg hooks/annotations here.

Playwright is distributed as a set of Maven modules and the easiest way to use it is to add the dependency to the project’s build.gradle. Let’s add the required dependencies to our build.gradle

To initialize Playwright and launch a browser, below are the essential modules to be aware of:

  • Playwright: Playwright module provides a method to launch a browser instance. Dive into the details here.
  • Browser: Playwright.create(), playwright.chromium(), playwright.firefox() or playwright.webkit() method launches the playwright driver process and returns an instance of BrowserType upon which the launch method can be called to launch the browser. Read more here.
  • BrowserContext: A browser context is an isolated incognito-like session within a browser instance, which helps to isolate the browser state between the tests. It can also be used to emulate multi-page scenarios. Read about this module from the official documentation here.
  • Page: Page provides methods to interact with a single tab in a browser. One browser instance can have multiple Page instances. More details here.

Let’s create Providers (objects capable of providing instances of the implemented type) for Playwright, Browser, BrowserContext, and Page.

PlaywrightProvider created above will be responsible for providing the playwright instance and we can inject it as shown in the snippet below.

BrowserProvider is responsible for providing the browser instance and can be injected as shown in the snippet below

BrowserContextProvider created above will provide the instance of context and can be injected as shown in the snippet below.

Note: Guice uses bindings to map object types to their actual implementations. These bindings are defined in a module.

Let’s create PlaywrightModule and add bindings to Playwright, Browser, BrowserContext, and Page.

Singelton binding ensures there will only be one instance of the object, which is passed around to all dependants (PageObjects, Components, utilities, etc). This ensures all playwright methods and methods on all objects created by it (such as BrowserContext, Browser, Page, etc.) are called on the same thread where the Playwright object was created.

Let’s write some sample tests for the SwagLab application using the PageObject pattern.

Note: The Playwright Page Class provides methods to interact with the browser.

Let’s create a class WebPage that serves as the base page for all the PageObjects and let’s inject Playwright Page as shown in the snippet below.

Let’s create LoginPage by extending the WebPage.

Let’s create WebTest that serves as a base class for all the tests and let’s implement TestNg hooks to initialize and dispose of Playwright objects respectively. An Injector for the PlaywrightModule is created in the BeforeMethod hook and this Injector can be used to get the playwright object instances as shown in the snippet below.

Note: Guice will fill in this object’s dependencies and any of its dependencies while constructing the object for us.

The webPageInstance method in the snippet below is a sugar-coated method to avoid Page Objects creation in Tests using the new keyword.

Let’s write a LoginTest by extending the WebTest and using the Page Objects created above.

Let’s configure the test task in build.gradle as shown below.

We can now execute the tests using the command:

Please find the source code of this blog here.

Shout out to Krishnanand B for introducing the Guice concept to me. 👏🏽

Further reading:

Check out my blog on Component driven approach here:
Playwright-Java (Part-2): Component driven pattern

--

--

Sudarshan

SDET by Profession, Passionate Coder and Technology Enthusiast