As automation projects grow, writing standalone Playwright scripts becomes difficult to maintain. Enterprise teams use testing frameworks like TestNG to organize test execution, manage test suites, perform assertions, generate reports, and execute tests in parallel.
In this guide, we'll build a Playwright TestNG framework from scratch using Java and follow industry best practices.
Why Use TestNG with Playwright?
TestNG offers several features that complement Playwright:
- Test annotations (
@Test,@BeforeMethod,@AfterMethod) - Test grouping
- Parallel execution
- Parameterized tests
- Test dependencies
- HTML reports
- Easy integration with CI/CD tools
Combining Playwright with TestNG results in a scalable and maintainable automation framework.
Prerequisites
Before starting, ensure you have:
- Java 17 or later
- Maven installed
- IntelliJ IDEA or Eclipse
- Basic knowledge of Playwright
- Browser binaries installed
Step 1: Create a Maven Project
Create a new Maven project in your IDE.
Suggested structure:
playwright-testng-framework
│
├── src
│ ├── main
│ │ └── java
│ │ ├── pages
│ │ ├── utils
│ │ └── base
│ │
│ └── test
│ └── java
│ └── tests
│
├── testng.xml
├── pom.xml
└── README.mdStep 2: Add Dependencies
Add the required dependencies to your pom.xml.
<dependencies>
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>1.55.0</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.11.0</version>
<scope>test</scope>
</dependency>
</dependencies>Refresh the Maven project after saving the file.
Step 3: Create the BaseTest Class
The BaseTest class is responsible for browser setup and cleanup.
public class BaseTest {
protected Playwright playwright;
protected Browser browser;
protected BrowserContext context;
protected Page page;
@BeforeMethod
public void setup() {
playwright = Playwright.create();
browser = playwright.chromium().launch(
new BrowserType.LaunchOptions()
.setHeadless(false));
context = browser.newContext();
page = context.newPage();
}
@AfterMethod
public void tearDown() {
context.close();
browser.close();
playwright.close();
}
}This ensures every test starts with a fresh browser session.
Step 4: Create a Page Object
Example LoginPage.java.
public class LoginPage {
private final Page page;
public LoginPage(Page page) {
this.page = page;
}
public void login(String username, String password) {
page.fill("#username", username);
page.fill("#password", password);
page.click("#loginButton");
}
}Keeping page interactions separate improves maintainability.
Step 5: Create Your First Test
Create a TestNG test class.
public class LoginTest extends BaseTest {
@Test
public void verifySuccessfulLogin() {
page.navigate("https://example.com/login");
LoginPage loginPage =
new LoginPage(page);
loginPage.login(
"admin",
"password123");
assertThat(page)
.hasTitle("Dashboard");
}
}Notice how the test focuses only on business logic while setup is handled by BaseTest.
Step 6: Create testng.xml
TestNG uses an XML file to define test suites.
<!DOCTYPE suite SYSTEM
"https://testng.org/testng-1.0.dtd">
<suite name="Playwright Suite">
<test name="Smoke Tests">
<classes>
<class name="tests.LoginTest"/>
</classes>
</test>
</suite>You can execute all tests by running this suite file.
Step 7: Execute Tests
You can run tests in several ways:
- Directly from IntelliJ IDEA
- Using Eclipse
- From Maven
- Through Jenkins or another CI/CD pipeline
Example Maven command:
mvn testParallel Execution
TestNG supports parallel execution through testng.xml.
Example:
<suite name="Playwright Suite"
parallel="methods"
thread-count="4">
</suite>This executes four test methods simultaneously, reducing execution time.
Adding Groups
TestNG groups help organize test cases.
Example:
@Test(groups = {"Smoke"})
public void loginTest() {
}You can create groups such as:
- Smoke
- Regression
- Sanity
- API
- UI
Generating Reports
After execution, TestNG automatically creates reports inside the test-output folder.
Common reports include:
- HTML report
- Failed test report
- Execution summary
These reports provide quick insight into test results.
Recommended Framework Structure
As your project grows, consider organizing it like this:
src
├── main
│ ├── base
│ ├── pages
│ ├── utils
│ ├── constants
│ └── listeners
│
├── test
│ ├── tests
│ ├── testdata
│ └── resources
│
├── reports
├── screenshots
├── videos
└── testng.xmlThis structure is easy to maintain and scales well for enterprise projects.
Best Practices
Keep Test Logic Separate
Business actions belong in page classes, not in test methods.
Reuse Browser Initialization
Initialize Playwright once in the base class instead of repeating code.
Use Assertions Wisely
Verify business outcomes rather than implementation details.
Examples:
- User logged in successfully
- Order created
- Invoice downloaded
Capture Screenshots on Failure
Integrate screenshot capture inside the @AfterMethod hook for failed tests.
Store Test Data Separately
Avoid hardcoding values.
Instead, use:
- JSON
- Excel
- CSV
- Properties files
Common Interview Questions
Why combine Playwright with TestNG?
TestNG provides test lifecycle management, reporting, grouping, parameterization, and parallel execution, making Playwright projects easier to manage.
What is the purpose of @BeforeMethod?
It runs before every test method and is commonly used to initialize the browser and create a new page.
What is the role of BaseTest?
BaseTest centralizes browser setup and cleanup, reducing code duplication across test classes.
Can Playwright tests run in parallel with TestNG?
Yes. By configuring parallel and thread-count in testng.xml, multiple tests can run simultaneously.
Conclusion
Using Playwright with TestNG is an excellent choice for building robust and maintainable Java automation frameworks.
In this tutorial, you learned how to:
- Create a Maven project
- Add Playwright and TestNG dependencies
- Build a reusable
BaseTest - Implement the Page Object Model
- Configure
testng.xml - Execute tests
- Enable parallel execution
- Apply framework best practices
With this foundation, you're ready to build enterprise-grade automation frameworks that are scalable, reusable, and easy to integrate with CI/CD pipelines.