Playwright with Java-TestNG in POM

In this section we are going to see how to automation Playwright-Jave with TestNG in Page Object Model (POM). 

Playwright automation in real-world projects follows the Page Object Model (POM) to keep test code clean, scalable, and maintainable. As applications grow and UI changes become frequent, POM helps separate page interactions from test logic, making updates easier and reducing maintenance effort.

The Page Object Model (POM) is one of the most commonly used design patterns in Playwright-based automation frameworks for production-level projects.

Before proceeding, make sure Playwright with Java and TestNG is set up correctly. Refer to the following link for the complete setup guide: QA Feast Link

Page Object Model

Page Object Model means creating a separate Java class for each web page in the application. That page class contains only the locators and actions related to that page. The test classes call methods from the page classes and form test cases that run in automation.

In simple terms, page classes handle how to interact with the page, and test classes handle what needs to be tested. This separation makes the test code easier to read and easier to maintain.

POM Project Structure

Inside the src/test/java folder, the project is divided into three main packages: pages, testScripts, and utils. Each package has a specific responsibility, which keeps the framework clean and organized.

The pages package contains all the page classes. Each class represents a specific web page and includes only locators and actions for that page.

The testScripts package contains the test classes. These classes define test scenarios and validations by using methods from the page classes.

The utils package contains reusable framework-level code such as browser setup, teardown, and common helper methods.

BaseTest Class

The BaseTest class is responsible for setting up and closing Playwright. It initializes Playwright, launches the browser, creates a browser context, and opens a page before the test execution begins. It also closes the browser and releases resources after the test execution completes.

All test classes extend BaseTest, which means this setup code is written only once and reused across all tests.

File: utils/BaseTest.java

package utils;
import com.microsoft.playwright.*;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
/**
 * BaseTest handles browser setup and teardown.
 * All test classes should extend this class.
 */

public class BaseTest {
    // Core Playwright objects shared across tests
    protected Playwright playwright;
    protected Browser browser;
    protected BrowserContext context;
    protected Page page;
    /**
     * Initializes Playwright, launches the browser,
     * and navigates to the application before each test.
     */

    @BeforeMethod
    public void setUp() {
        // Create a Playwright instance
        playwright = Playwright.create();
        // Launch Chromium browser in non-headless mode for visibility
        browser = playwright.chromium().launch(
                new BrowserType.LaunchOptions().setHeadless(false)
        );
        // Create an isolated browser context for the test
        context = browser.newContext();
        // Open a new page within the context
        page = context.newPage();
        // Navigate to the application under test
        page.navigate("https://www.qafeast.com/");
    }
    /**
     * Closes all Playwright resources after each test
     * to avoid memory leaks and session conflicts.
     */

    @AfterMethod
    public void tearDown() {
        if (page != null) page.close();
        if (context != null) context.close();
        if (browser != null) browser.close();
        if (playwright != null) playwright.close();
    }
}


BasePage Class

The BasePage class contains common helper methods that can be reused by all page classes. Instead of writing Playwright actions like click() and fill() repeatedly in every page class, we define them once here.

All page classes extend BasePage, which keeps page classes simple and focused only on page-specific actions.

File: utils/BasePage.java

package utils;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
/**
 * BasePage acts as a parent class for all page classes.
 * It provides common Playwright actions that can be reused across pages.
 */

public class BasePage {
    // Playwright Page instance used by all child page classes
    protected final Page page;
    /**
     * Constructor to initialize the Playwright Page.
     * This ensures every page object has access to the same browser page.
     */

    public BasePage(Page page) {
        this.page = page;
    }
     // Clicks on an element identified by the given selector.
    protected void click(String selector) {
        page.locator(selector).click();
    }
    // Fills the given value into an input field identified by the selector.
    protected void fill(String selector, String value) {
        page.locator(selector).fill(value);
    }
    // Returns a Locator object for the given selector.
    protected Locator locator(String selector) {
        return page.locator(selector);
    }
}


HomePage Class

The HomePage class represents the Home page of the application. It contains only the actions that can be performed on the Home page, such as accepting cookies, clicking the Tools menu, and navigating to the Demo Site page.

This class does not contain any test logic or assertions. Its only responsibility is to interact with the UI of the Home page

File: pages/HomePage.java

package pages;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import utils.BasePage;
/**
 * HomePage contains actions and validations related to the home page.
 */

public class HomePage extends BasePage {
    /**
     * Initializes HomePage with the current Playwright page.
     */

    public HomePage(Page page) {
        super(page);
    }
    // Accepts the GDPR cookie consent banner
    public void acceptCookies() {
        click("#gdpr-cookie-accept");
    }
    // Clicks on the Tools menu in the navigation bar
    public void clickTools() {
        click("li[class='tut_ fr_tls']>a");
    }
    // Navigates to the Demo Site page from the Tools menu
    public void gotoDemoSitePage() {
        click("//li/a[text()='Demo Site']");
    }
    /**
     * Verifies whether the Demo Site page is opened.
     * Uses the presence of the Textbox label as a page identifier.
     */

    public boolean isDemoSiteOpened() {
        Locator textbox = page.locator("//li/label[text()='Textbox']");
        textbox.waitFor();
        return textbox.isVisible();
    }
}


HomePage Test Class

The HomePageTest class contains the actual test scenario. It extends BaseTest, so the browser setup and teardown are handled automatically.

The test method creates an object of HomePage and calls its methods to perform actions. Finally, it validates the result using a TestNG assertion. Because the test uses page methods, the test code is clean, readable, and easy to understand.

File: testScripts/HomePageTest.java

package testScripts;
import org.testng.Assert;
import org.testng.annotations.Test;
import pages.HomePage;
import utils.BaseTest;
/**
 * Test class to validate navigation from Home page to Demo Site page.
 */

public class HomePageTest extends BaseTest {
    /**
     * Verifies that the user can navigate to the Demo Site page
     * using the Tools menu from the home page.
     */

    @Test(groups = "smoke")
    public void shouldNavigateToDemoSite() {
        // Initialize HomePage with the active Playwright page
        HomePage homePage = new HomePage(page);
        // Perform actions required to reach the Demo Site page
        homePage.acceptCookies();
        homePage.clickTools();
        homePage.gotoDemoSitePage();
        // Validate that the Demo Site page is successfully opened
        Assert.assertTrue(
                homePage.isDemoSiteOpened(),
                "Demo Site page is not opened"
        );
    }
}

 

TestNG XML Execution

So far, we have created our Playwright automation framework using Java + TestNG with the Page Object Model (POM). Now let’s see how to execute the tests using testng.xml, which is the standard and preferred way to run TestNG-based automation in real-world projects.

testng.xml Configuration

Create an xml file named testng in the project root folder. Below example testng.xml file configured for this example framework:

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">

<suite name="Playwright Smoke Test Suite">

<test name="Smoke Tests">

<groups>
<run>
<include name="smoke"/>
</run>
</groups>

<classes>
<class name="testScripts.HomePageTest"/>
</classes>

</test>

</suite>


Explanation

The <suite> tag defines a TestNG test suite named Playwright Smoke Test Suite.
Inside the suite, the <test> tag groups related tests under Smoke Tests.

The <groups> section ensures that only tests marked with the smoke group are executed. This matches the @Test(groups = "smoke") annotation used in HomePageTest.

The <classes> section points to the test class using its fully qualified name, which in this case is testScripts.HomePageTest, exactly matching the package structure inside src/test/java.

How to Execute Tests Using testng.xml

You can run the tests in two simple ways:

From IntelliJ IDEA

     - Right-click on testng.xml
     - Select Run 'testng.xml'

Using Maven

Run this command: mvn test -Dsurefire.suiteXmlFiles=testng.xml

Read this link to know for complete testng execution tutorial: https://www.qafeast.com/java-testng/testng_script_execution

 

Related Tutorials