Testing REST APIs with Playwright in Java

HOME

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>Playwright_API_Demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Playwright_API_Demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <playwright.version>1.57.0</playwright.version>
    <testng.version>7.11.0</testng.version>
    <maven.compiler.plugin.version>3.15.0</maven.compiler.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
  </properties>

  <dependencies>

    <!-- Playwright -->
    <dependency>
      <groupId>com.microsoft.playwright</groupId>
      <artifactId>playwright</artifactId>
      <version>${playwright.version}</version>
    </dependency>

    <!-- TestNG -->
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>

  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source.version}</source>
          <target>${maven.compiler.target.version}</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>testng.xml</suiteXmlFile>
          </suiteXmlFiles>
        </configuration>
        <dependencies>
        </dependencies>
      </plugin>
    </plugins>
  </build>
</project>

 @BeforeMethod
    void setUp() {
        createPlaywright();
        createAPIRequestContext();
    }

 void createPlaywright() {
        playwright = Playwright.create();
    }

void createAPIRequestContext() {
        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json");

        request = playwright.request().newContext(new APIRequest.NewContextOptions()
                .setBaseURL("https://jsonplaceholder.typicode.com")
                .setExtraHTTPHeaders(headers));
    }

  @AfterMethod
    void tearDown() {
        if (request != null) {
            request.dispose();
        }
        if (playwright != null) {
            playwright.close();
        }
    }

 @Test
    public void getUserById() {
        APIResponse response = request.get("/posts/1");
        System.out.println("GET Response :" + response.text());
        Assert.assertEquals(response.status(), 200, "Expected 200 for GET /posts/1");

        Gson gson = new Gson();
        JsonObject jsonResponse = gson.fromJson(response.text(), JsonObject.class);
        Assert.assertEquals(jsonResponse.get("userId").getAsInt(), 1, "Expected userId=1 in response body");
        Assert.assertEquals(jsonResponse.get("id").getAsInt(), 1, "Expected id=1 in response body");
    }

POST Request

{
    "title": "architect",
    "body": "post test",
    "userId": 100
}

 @Test
    public void createUser() {
        Map<String, Object> payload = new HashMap<>();
        payload.put("title", "architect");
        payload.put("body", "post test");
        payload.put("userId", 100);

        APIResponse response = request.post("/posts", RequestOptions.create().setData(payload));
        System.out.println("POST Response :" + response.text());
        Assert.assertEquals(response.status(), 201, "Expected 201 for POST /users");

        Gson gson = new Gson();
        JsonObject body = gson.fromJson(response.text(), JsonObject.class);
        Assert.assertEquals(body.get("title").getAsString(), "architect");
        Assert.assertEquals(body.get("body").getAsString(), "post test");
        Assert.assertEquals(body.get("userId").getAsInt(), 100);
        Assert.assertNotNull(body.get("id"), "Expected id in create response");
    }

{
    "id": 1, 
    "title": "business manager",
    "body": "Implementing DataWareHouse Migration Project",
    "userId": 50
}
 @Test
    public void updateUser() {

        APIResponse response = request.get("/posts/1");
        System.out.println("GET Response before PUT Request:" + response.text());
        Assert.assertEquals(response.status(), 200, "Expected 200 for GET /posts/1");


        Map<String, Object> payload = new HashMap<>();
        payload.put("id", 1);
        payload.put("title", "business manager");
        payload.put("body", "Implementing DataWareHouse Migration Project");
        payload.put("userId", 50);

        APIResponse response1 = request.put("/posts/1", RequestOptions.create().setData(payload));
        System.out.println("PUT Response :" + response1.text());
        Assert.assertEquals(response1.status(), 200, "Expected 200 for PUT /posts/1");

        Gson gson = new Gson();
        JsonObject body = gson.fromJson(response1.text(), JsonObject.class);
        Assert.assertEquals(body.get("title").getAsString(), "business manager");
        Assert.assertEquals(body.get("body").getAsString(), "Implementing DataWareHouse Migration Project");
        Assert.assertEquals(body.get("userId").getAsInt(), 50);
        Assert.assertNotNull(body.get("id"), "Expected id in create response");

    }

   @Test
    public void deleteUser() {
        APIResponse response = request.delete("/posts/1");
        System.out.println("DELETE Response :" + response.text());
        Assert.assertEquals(response.status(), 200, "Expected 200 for DELETE /posts/1");
    }

mvn clean test

Integrate Allure Report with Playwright with Java, Cucumber, and TestNG

Last Updated On

HOME

In this tutorial, I will explain how to Integrate Allure Report 3 with Playwright, Java Cucumber,  and TestNG.

Before starting, make sure to install Allure on your machine. Refer to this tutorial to install allure – What is Allure Report?.

Table of Contents

System requirements

  1. Java 17 installed
  2. Maven installed
  3. Eclipse or IntelliJ installed
  4. Allure installed
  5. Browsers on which tests need to be run, like Chrome, Firefox, etc.

Dependency List

  1. Playwright – 1.57.0
  2. Java 17
  3. Cucumber – 7.33.0
  4. Maven – 3.9.6
  5. TestNG – 7.11.0
  6. Allure Report – 2.32.0
  7. Aspectj – 1.9.25.1
  8. Maven Compiler Plugin – 3.13.0
  9. Maven Surefire Plugin – 3.5.4

Implementation Steps

Step 1 – Update the Properties section in Maven pom.xml
 <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <playwright.version>1.57.0</playwright.version>
        <testng.version>7.11.0</testng.version>
        <allure.version>2.32.0</allure.version>
        <aspectj.version>1.9.25</aspectj.version>
        <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
        <maven.compiler.source.version>17</maven.compiler.source.version>
        <maven.compiler.target.version>17</maven.compiler.target.version>
        <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
</properties>

Step 2 – Add dependencies to pom.xml

Add Cucumber, TestNG, Allure-Cucumber, and Allure-TestNG dependencies to pom.xml (Maven Project).

  <!-- Add allure-bom to dependency management to ensure correct versions of all the dependencies are used -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-bom</artifactId>
        <version>${allure.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>

    <!-- Cucumber with Java -->
    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- Cucumber with TestNG -->
    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-testng</artifactId>
      <version>${cucumber.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- TestNG -->
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- Playwright -->
    <dependency>
      <groupId>com.microsoft.playwright</groupId>
      <artifactId>playwright</artifactId>
      <version>${playwright.version}</version>
    </dependency>

    <!-- Add necessary Allure dependencies -->
      <dependency>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-cucumber7-jvm</artifactId>
        <scope>test</scope>
      </dependency>

      <dependency>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-testng</artifactId>
        <scope>test</scope>
      </dependency>
    
  </dependencies>

Step 3 – Update the Build Section of pom.xml in the Allure Report Project
<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source.version}</source>
          <target>${maven.compiler.target.version}</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>testng.xml</suiteXmlFile>
          </suiteXmlFiles>
          <argLine>
            -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
          </argLine>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
            <scope>runtime</scope>
          </dependency>
        </dependencies>
      </plugin>
      <plugin>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-maven</artifactId>
        <version>${allure.maven}</version>
        <configuration>
          <reportVersion>${allure.maven}</reportVersion>
        </configuration>
      </plugin>
    </plugins>
  </build>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>Playwright_PageObjectModel</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>Playwright_PageObjectModel</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <playwright.version>1.57.0</playwright.version>
        <testng.version>7.11.0</testng.version>
        <allure.version>2.32.0</allure.version>
        <aspectj.version>1.9.25</aspectj.version>
        <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
        <maven.compiler.source.version>17</maven.compiler.source.version>
        <maven.compiler.target.version>17</maven.compiler.target.version>
        <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
    </properties>

    <!-- Add allure-bom to dependency management to ensure correct versions of all the dependencies are used -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-bom</artifactId>
                <version>${allure.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <!-- Playwright -->
        <dependency>
            <groupId>com.microsoft.playwright</groupId>
            <artifactId>playwright</artifactId>
            <version>${playwright.version}</version>
        </dependency>

        <!-- TestNG -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Allure-TestNG -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-testng</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source.version}</source>
                    <target>${maven.compiler.target.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <suiteXmlFiles>
                        <suiteXmlFile>testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                    <argLine>
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    </argLine>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjweaver</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>


2. Create a Feature file

Create a folder – features within src/test/resources to create test scenarios in the Feature file.

Feature file should be saved as an extension of .feature. Add the test scenarios in this feature file. I have added sample test scenarios. In this feature file. The test scenarios are written in Gherkins language.

@allure.label.parent_suite:WebInterface
@allure.label.sub_suite:Login Page
@allure.label.owner:Vibha

Feature: Login to HRM Application

  Background:
    Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"

  @ValidCredentials @Critical
  Scenario: Login with valid credentials

    When User enters username as "Admin" and password as "admin123"
    Then User should be able to login successfully and new page opens with heading "Dashboard"

  @InvalidCredentials @High
  Scenario Outline: Login with invalid credentials

    When User enters username as "<username>" and password as "<password>"
    Then User should be able to see error message "<errorMessage>"

    Examples:
      | username   | password  | errorMessage           |
      | Admin      | admin12$$ | Invalid credentials    |
      | admin$$    | admin123  | Invalid credentials    |
      | abc123     | xyz$$     | Invalid credentials    |

  @MissingUsername @Medium
  Scenario: Login with blank username

    When User enters username as " " and password as "admin123"
    Then User should be able to see a message "Required1" below Username

7. Create the step definition class in src/test/java

8. Create a TestNG Cucumber Runner class

We need to create a class called Runner class to run the tests. This class will use the TestNG annotation @Test, which tells TestNG what is the test runner class.

package com.example.runner;

import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;

@CucumberOptions(features = "src/test/resources/features/LoginPage.feature",
        glue = {"com.example.hooks","com.example.definitions"},
        plugin = { "io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm",
                "pretty",
        }
)

public class RunnerTests extends AbstractTestNGCucumberTests {

}

Note:- @Test annotation marks this class as part of the test. So, if we will remove this annotation, the Allure Report executes CucumberRunnerTests as a separate test suite, so there will be duplicate results.

9. Create testng.xml for the project

<?xml version = "1.0"encoding = "UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name = "Suite1">
    <test name = "Test Demo">
        <classes>
            <class name = "com.example.runner.CucumberRunnerTests"/>
        </classes>
    </test>
</suite>

#allure.properties
allure.results.directory=build/allure-results

11. Run the Test and Generate Allure Report

To run the tests, use the below command

mvn clean test

In the image below, we can see that one test failed and four passed out of five tests.

This will create the allure-results folder with all the test reports within build folder. These files will be used to generate Allure Report.

12. How to Generate a Report

Use the command below to generate the Allure Report

 allure serve build/allure-results

This will generate the beautiful Allure Test Report as shown below.

Graphs in Allure Report

Graphs allow you to see different statistics collected from the test data: status breakdown or severity and duration diagrams.

Timeline in Allure Report

The timeline tab visualizes retrospective test execution, allure adaptors collect precise timings of tests, and here on this tab, they are arranged accordingly to their sequential or parallel timing structure.

 allure awesome build/allure-results

Congratulations!! We have integrated an allure report with Playwright, Java Cucumber, and TestNG. I hope this tutorial is useful to you.

Additional Tutorials on Allure Reports

Integration of Allure Report with Selenium and JUnit4
Integration of Allure Report with Selenium and TestNG
Gradle – Allure Report for Selenium and JUnit4
Gradle – Allure Report for Cucumber, Selenium and TestNG
Integration of Allure Report with Rest Assured and JUnit4

Integrate Allure Report with Playwright with Java and TestNG

Last Updated On

HOME

In this tutorial, I will explain how to Integrate Allure Report 3 with Playwright, Java and TestNG.

Refer to this tutorial to install allure – What is Allure Report?.

Table of Contents

System requirements

  1. Java 17 installed
  2. Maven installed
  3. Eclipse or IntelliJ installed
  4. Allure installed
  5. Browsers on which tests need to be run, like Chrome, Firefox, etc.

Dependency List

  1. Playwright – 1.57.0
  2. Java 17
  3. Maven – 3.9.6
  4. Allure Report – 2.32.0
  5. Aspectj – 1.9.25
  6. Maven Compiler Plugin – 3.13.0
  7. Maven Surefire Plugin – 3.5.4

High-Level Execution Flow

Implementation Steps

Step 1 – Update the Properties section in Maven pom.xml
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <playwright.version>1.57.0</playwright.version>
    <testng.version>7.11.0</testng.version>
    <allure.version>2.32.0</allure.version>
    <aspectj.version>1.9.25</aspectj.version>
    <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
  </properties>

Step 2 – Add dependencies to pom.xml

Add Playwright, TestNG, and Allure-TestNG dependencies to pom.xml (Maven Project).

 <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-bom</artifactId>
                <version>${allure.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <!-- Playwright -->
        <dependency>
            <groupId>com.microsoft.playwright</groupId>
            <artifactId>playwright</artifactId>
            <version>${playwright.version}</version>
        </dependency>

        <!-- TestNG -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Allure-TestNG -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-testng</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

Step 3 – Update the Build Section of pom.xml in the Allure Report Project
 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source.version}</source>
                    <target>${maven.compiler.target.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <suiteXmlFiles>
                        <suiteXmlFile>testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                    <argLine>
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    </argLine>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjweaver</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>Playwright_PageObjectModel</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>Playwright_PageObjectModel</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <playwright.version>1.57.0</playwright.version>
        <testng.version>7.11.0</testng.version>
        <allure.version>2.32.0</allure.version>
        <aspectj.version>1.9.25</aspectj.version>
        <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
        <maven.compiler.source.version>17</maven.compiler.source.version>
        <maven.compiler.target.version>17</maven.compiler.target.version>
        <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
    </properties>

    <!-- Add allure-bom to dependency management to ensure correct versions of all the dependencies are used -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-bom</artifactId>
                <version>${allure.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <!-- Playwright -->
        <dependency>
            <groupId>com.microsoft.playwright</groupId>
            <artifactId>playwright</artifactId>
            <version>${playwright.version}</version>
        </dependency>

        <!-- TestNG -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Allure-TestNG -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-testng</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source.version}</source>
                    <target>${maven.compiler.target.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <suiteXmlFiles>
                        <suiteXmlFile>testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                    <argLine>
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    </argLine>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjweaver</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>


2. Project Structure for Maintainability

Creating a well-organized project structure is crucial for maintaining a scalable and efficient automation framework.

3. Creating Page Object Classes in src/test/java

package com.example.utils;

import io.qameta.allure.Attachment;

public abstract class AllureAttachments {

    @Attachment(value = "Failure Screenshot", type = "image/png")
    public static byte[] attachScreenshot(byte[] screenshot) {
        return screenshot;
    }
}

package com.example.utils;

import com.microsoft.playwright.*;
import org.testng.annotations.*;

public class BaseClass {

    // Shared between all tests in this class.
    Playwright playwright;
    Browser browser = null;

    // New instance for each test method.
    BrowserContext context;
    public Page page;

    public Page getPage() {
        return page;
    }

    @BeforeClass
    public void launchBrowser() {
        playwright = Playwright.create();
        browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
    }

    @BeforeMethod
    public void createContextAndPage() {
        context = browser.newContext();
        page = context.newPage();
        page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    }

    @AfterMethod
    public void closeContext() {
        context.close();
    }

    @AfterClass
    public void closeBrowser() {
        playwright.close();
    }
}

package com.example.utils;

import com.microsoft.playwright.Page;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class TestListener implements ITestListener {

     @Override
    public void onTestFailure(ITestResult result) {
        System.out.println("❌ onTestFailure triggered");
        Page page = BaseClass.getPage();
        if (page != null) {
            byte[] screenshot = page.screenshot();
            AllureAttachments.attachScreenshot(screenshot);
        }
    }
}

package com.example.tests;

import com.example.pages.DashboardPage;
import com.example.pages.LoginPage;
import com.example.utils.BaseClass;
import com.example.utils.TestListener;
import io.qameta.allure.Description;
import io.qameta.allure.Owner;
import io.qameta.allure.Severity;
import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import static io.qameta.allure.SeverityLevel.*;

public class LoginTests extends BaseClass {

    @Test
    @Description("This test attempts to log into the website using a invalid login and a password that result in error")
    @Severity(NORMAL)
    @Owner("Vibha Singh")
    public void unsuccessfulLogin() {
        LoginPage loginPage = new LoginPage(page);
        loginPage.login("abc","abc");
        String actualErrorMessage = loginPage.getErrorMessage();
        Assert.assertEquals(actualErrorMessage, "Invalid credentials");
   }

    @Test
    @Description("This test attempts to log into the website using a valid login and a password")
    @Severity(CRITICAL)
    @Owner("Vibha Singh")
    public void successfulLogin() {
        LoginPage loginPage = new LoginPage(page);
        loginPage.login("Admin","admin123");
        DashboardPage dashboardPage = new DashboardPage(page);
        String actualHeading = dashboardPage.getDashboardPageHeading();
        Assert.assertEquals(actualHeading, "Dashboard");
    }

    @Test
    @Description("This test attempts to log into the website using a blank login and a password that result in error")
    @Severity(MINOR)
    @Owner("Vibha Singh")
    public void missingUsername() {
        LoginPage loginPage = new LoginPage(page);
        loginPage.login("","admin123");
        String actualErrorMessage = loginPage.getMissingUsernameErrorMessage();
        Assert.assertEquals(actualErrorMessage, "Required1");
    }

}

@Description("This test attempts to log into the website using a invalid login and a password that result in error")

6. Create testng.xml for the project

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Playwright test suite">

    <listeners>
        <listener class-name="com.example.utils.TestListener"/>
    </listeners>

    <test name="Integration of Playwright Java with TestNG">
    <classes>
        <class name="com.example.tests.LoginTests">

        </class>
    </classes>
    </test>
</suite>

#allure.properties
allure.results.directory=target/allure-results

8. Run the Tests and Generate Allure Report

To run the tests, use the below command

mvn clean test

In the image below, we can see that one test failed and four passed out of three tests.

This will create the allure-results folder with all the test reports within build folder. These files will be used to generate Allure Report.

9. How to Generate an Allure Report

Use the command below to generate the Allure Report

 allure serve build/allure-results

This will generate the beautiful Allure Test Report as shown below.

Graphs in Allure Report

Graphs allow you to see different statistics collected from the test data: status breakdown or severity and duration diagrams.

Timeline in Allure Report

The timeline tab visualizes retrospective test execution. Allure adaptors collect precise timings of tests. Here on this tab, they are arranged according to their sequential or parallel timing structure.

 allure awesome build/allure-results

Congratulations!! We have integrated an allure report with Cucumber, Selenium, and TestNG. I hope this tutorial is useful to you.

Additional Tutorials on Allure Reports

Integration of Allure Report with Selenium and JUnit4
Integration of Allure Report with Selenium and TestNG
Gradle – Allure Report for Selenium and JUnit4
Gradle – Allure Report for Cucumber, Selenium and TestNG
Integration of Allure Report with Rest Assured and JUnit4

Integration of Playwright with Java, Cucumber and TestNG

HOME

Benefits of Using Cucumber with Playwright

<properties>
    <java.version>17</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <cucumber.version>7.33.0</cucumber.version>
    <testng.version>7.12.0</testng.version>
    <playwright.version>1.57.0</playwright.version>
    <maven.compiler.version>3.14.1</maven.compiler.version>
    <maven.surefire.version>3.5.4</maven.surefire.version>
    <maven.failsafe.version>3.5.4</maven.failsafe.version>
    <lombok.version>1.18.30</lombok.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
</properties>

<dependencies>

    <!-- Cucumber with Java -->
    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- Cucumber with TestNG -->
    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-testng</artifactId>
      <version>${cucumber.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- TestNG -->
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- Playwright -->
    <dependency>
      <groupId>com.microsoft.playwright</groupId>
      <artifactId>playwright</artifactId>
      <version>${playwright.version}</version>
    </dependency>

</dependencies>

 <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.version}</version>
        <configuration>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.version}</version>
        <configuration>
          <testFailureIgnore>true</testFailureIgnore>
          <includes>
            <include>**/*RunnerTests.java</include>
          </includes>
        </configuration>
      </plugin>
      
    </plugins>
  </build>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>Cucumber_Playwright_TestNG</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Cucumber_Playwright_TestNG</name>
  <url>http://maven.apache.org</url>

  <properties>
    <java.version>17</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <cucumber.version>7.33.0</cucumber.version>
    <testng.version>7.12.0</testng.version>
    <playwright.version>1.57.0</playwright.version>
    <maven.compiler.version>3.14.1</maven.compiler.version>
    <maven.surefire.version>3.5.4</maven.surefire.version>
    <maven.failsafe.version>3.5.4</maven.failsafe.version>
    <lombok.version>1.18.30</lombok.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
  </properties>

  <dependencies>

    <!-- Cucumber with Java -->
    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- Cucumber with TestNG -->
    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-testng</artifactId>
      <version>${cucumber.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- TestNG -->
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- Playwright -->
    <dependency>
      <groupId>com.microsoft.playwright</groupId>
      <artifactId>playwright</artifactId>
      <version>${playwright.version}</version>
    </dependency>

  </dependencies>
 
 <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.version}</version>
        <configuration>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.version}</version>
        <configuration>
          <testFailureIgnore>true</testFailureIgnore>
          <includes>
            <include>**/*RunnerTests.java</include>
          </includes>
        </configuration>
      </plugin>
      
    </plugins>
  </build>
</project>

Feature: Login to HRM Application

  Background:
    Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"

  @ValidCredentials
  Scenario: Login with valid credentials

    When User enters username as "Admin" and password as "admin123"
    Then User should be able to login successfully and new page opens with heading "Dashboard"

  @InvalidCredentials
  Scenario Outline: Login with invalid credentials

    When User enters username as "<username>" and password as "<password>"
    Then User should be able to see error message "<errorMessage>"

    Examples:
      | username   | password  | errorMessage           |
      | Admin      | admin12$$ | Invalid credentials    |
      | admin$$    | admin123  | Invalid credentials    |
      | abc123     | xyz$$     | Invalid credentials    |

  @MissingUsername 
  Scenario: Login with blank username

    When User enters username as " " and password as "admin123"
    Then User should be able to see a message "Required1" below Username

package com.example.utils;

import com.microsoft.playwright.*;

public class PlaywrightFactory {

    private static Playwright playwright;
    private static Browser browser;
    private static BrowserContext context;
    private static Page page;

    public static void initBrowser() {

        playwright = Playwright.create();
        browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
        context = browser.newContext();
        page = context.newPage();
    }

    public static Page getPage() {
        return page;
    }

    public static void closeBrowser() {
        if (page != null) page.close();
        if (context != null) context.close();
        if (browser != null) browser.close();
        if (playwright != null) playwright.close();
    }
}

package com.example.hooks;

import com.example.utils.PlaywrightFactory;
import com.microsoft.playwright.*;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;

public class Hooks {

    @Before
    public void beforeScenario(Scenario scenario) {
        System.out.println("Starting scenario: " + scenario.getName());
        PlaywrightFactory.initBrowser();
    }

    @After
    public void afterScenario(Scenario scenario) {
        Page page = PlaywrightFactory.getPage();
        if (page != null && scenario.isFailed()) {
            scenario.attach(page.screenshot(), "image/png", scenario.getName());
        }
        PlaywrightFactory.closeBrowser();  
        System.out.println("Finished scenario: " + scenario.getName());
    }
}


package com.example.pages;

import com.microsoft.playwright.*;

public class LoginPage {

    private Page page;

    // Locators
    private final Locator usernameLocator;
    private final Locator passwordLocator;
    private final Locator submitLocator;
    private final Locator invalidCredentialsLocator;
    private final Locator missingUsernameLocator;

    public LoginPage(Page page) {
        this.page = page;
        this.usernameLocator = page.locator("input[name='username']");
        this.passwordLocator = page.locator("input[name='password']");
        this.submitLocator = page.locator("button[type='submit']");
        this.invalidCredentialsLocator = page.locator("//p[contains(@class, \"oxd-text oxd-text--p oxd-alert-content-text\")]");
        this.missingUsernameLocator = page.locator("//span[contains(@class, 'oxd-text oxd-text--span oxd-input-field-error-message oxd-input-group__message')]");
    }

    public void login(String user, String pass){
        usernameLocator.fill(user);
        passwordLocator.fill(pass);
        submitLocator.click();
    }

    public void getUrl(String url){
        page.navigate(url);
    }

    public String getMissingUsernameErrorMessage() {
        return missingUsernameLocator.textContent();
    }

    public String getErrorMessage () {
        return invalidCredentialsLocator.textContent();
    }
}

package com.example.pages;

import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;

public class DashboardPage {

    private Page page;

    private final Locator headingLocator;

    public DashboardPage(Page page){
        this.page = page;
        this.headingLocator = page.locator("//h6[contains(@class, \"oxd-topbar-header-breadcrumb-module\")]");
    }

    public String getDashboardPageHeading() {
        return headingLocator.textContent();
    }

}

package com.example.steps;

import com.example.utils.PlaywrightFactory;
import com.microsoft.playwright.Page;

public class BaseStep {

    protected Page getPage() {
        Page page = PlaywrightFactory.getPage();
        if (page == null) {
            throw new RuntimeException(
                    "Page is NULL. Ensure @Before hook ran and glue includes hooks package."
            );
        }
        return page;
    }
}

package com.example.definitions;

import com.example.steps.BaseStep;
import com.example.pages.DashboardPage;
import com.example.pages.LoginPage;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.testng.Assert;

public class LoginPageDefinitions extends BaseStep {
    
    private LoginPage loginPage;
    private DashboardPage dashboardPage;

    @Given("User is on HRMLogin page {string}")
    public void userIsOnHRMLoginPage(String baseUrl) {
        loginPage = new LoginPage(getPage());
        loginPage.getUrl(baseUrl);
    }

    @When("User enters username as {string} and password as {string}")
    public void userEntersUsernameAsAndPasswordAs(String username, String password) {
        loginPage.login(username, password);
    }

    @Then("User should be able to see error message {string}")
    public void userShouldBeAbleToSeeErrorMessage(String expectedErrorMessage) {
        Assert.assertEquals(loginPage.getErrorMessage(), expectedErrorMessage);
    }

    @Then("User should be able to see a message {string} below Username")
    public void userShouldBeAbleToSeeAMessageBelowUsername(String expectedErrorMessage) {
        Assert.assertEquals(loginPage.getMissingUsernameErrorMessage(), expectedErrorMessage);
    }

    @Then("User should be able to login successfully and new page opens with heading {string}")
    public void userShouldBeAbleToLoginSuccessfullyAndNewPageOpen(String expectedHeading) {
        dashboardPage = new DashboardPage(getPage());
        Assert.assertEquals(dashboardPage.getDashboardPageHeading(), expectedHeading);

    }

}

package com.example.runner;

import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;

@CucumberOptions(features = "src/test/resources/features/LoginPage.feature",
        glue = {"com.example.hooks","com.example.definitions"},
        plugin = {
                "pretty",
        }
)

public class RunnerTests extends AbstractTestNGCucumberTests {

}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Playwright test suite" thread-count="3">
    <test name="Chromium Tests">
        <classes>
            <class name="com.example.runner.RunnerTests"/>
        </classes>
    </test>
</suite>

mvn clean test

cucumber.publish.enabled=true

  • Hooks: Hooks manage browser setup, teardown, and failure handling

Mastering Page Object Model for Playwright with Java and TestNG

HOME

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>Playwright_TestNG_Demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Playwright_TestNG_Demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <playwright.version>1.57.0</playwright.version>
    <testng.version>7.11.0</testng.version>
    <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
  </properties>

  <dependencies>

    <dependency>
      <groupId>com.microsoft.playwright</groupId>
      <artifactId>playwright</artifactId>
      <version>${playwright.version}</version>
    </dependency>

    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source.version}</source>
          <target>${maven.compiler.target.version}</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>testng.xml</suiteXmlFile>
          </suiteXmlFiles>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

import com.microsoft.playwright.Page;

public class LoginPage {

    private Page page;

    //Locators
    private final String usernameLocator = "input[name='username']";
    private final String passwordLocator = "input[name='password']";
    private final String submitButton = "button[type='submit']";
    private final String errorMessage = "//p[contains(@class, 'oxd-text oxd-text--p oxd-alert-content-text')]";

    //Constructor
    public LoginPage(Page page){
        this.page = page;
    }

    public void login(String username, String password) {
        page.fill(usernameLocator,username);
        page.fill(passwordLocator,password);
        page.click(submitButton);
    }

    public String getErrorMessage(){
        return page.textContent(errorMessage);
    }
}

package org.example.pages;

import com.microsoft.playwright.Page;

public class DashboardPage {

    private Page page;

    //Locators
    private final String dashboardHeading = "//h6[contains(@class, 'oxd-topbar-header-breadcrumb-module')]";

    //Constructor
    public DashboardPage(Page page) {
        this.page = page;
    }

    // Methods
    public String getHeading() {
        return page.textContent(dashboardHeading);
    }
}

package org.example.utils;

import com.microsoft.playwright.*;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;

public class BaseTests {

    // Shared between all tests in this class.
    protected Playwright playwright;
    protected Browser browser;

    // New instance for each test method.
    protected BrowserContext context;
    protected Page page;

    @BeforeClass
    public void launchBrowser() {
        playwright = Playwright.create();
        browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
    }

    @BeforeMethod
    public void createContextAndPage() {
        context = browser.newContext();
        page = context.newPage();
        page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    }

    @AfterMethod
    public void closeContext() {
        context.close();
    }

    @AfterClass
    public void closeBrowser() {
        playwright.close();
    }
}
Playwright playwright;
Browser browser = null;
BrowserContext context;
Page page;
@BeforeClass
public void launchBrowser() {
        playwright = Playwright.create();
        browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
}

@BeforeMethod
void createContextAndPage() {
      context = browser.newContext();
      page = context.newPage();
      page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
}
@AfterMethod
void closeContext() {
       context.close();
}
@AfterClass
void closeBrowser() {
      playwright.close();
}

package org.example.tests;

import org.example.pages.DashboardPage;
import org.example.pages.LoginPage;
import org.example.utils.BaseTests;
import org.testng.Assert;
import org.testng.annotations.Test;

public class LoginTests extends BaseTests {

    @Test
    public void loginToApplication(){
        LoginPage loginPage = new LoginPage(page);
        loginPage.login("Admin","admin123");
        DashboardPage dashboardPage = new DashboardPage(page);
        String actualHeading = dashboardPage.getHeading();
        Assert.assertEquals(actualHeading,"Dashboard", "Unable to login to the application");
    }

    @Test
    public void invalidCredentials() {
        LoginPage loginPage = new LoginPage(page);
        loginPage.login("Playwright","test");
        Assert.assertEquals(loginPage.getErrorMessage(), "Invalid credentials" ,"Incorrect Error Message is displayed");

    }
}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Page Object Model Playwright test suite">
    <test name="Chrome Test">
        <parameter name="browser" value="chromium" />
        <classes>
            <class name="org.example.tests.LoginTests"/>
        </classes>
    </test>
</suite>    

Cross Browser Testing with Playwright and Java

HOME

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>Playwright_TestNG_Demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Playwright_TestNG_Demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <playwright.version>1.57.0</playwright.version>
    <testng.version>7.11.0</testng.version>
    <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
  </properties>

  <dependencies>

    <dependency>
      <groupId>com.microsoft.playwright</groupId>
      <artifactId>playwright</artifactId>
      <version>${playwright.version}</version>
    </dependency>

    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source.version}</source>
          <target>${maven.compiler.target.version}</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>testng.xml</suiteXmlFile>
          </suiteXmlFiles>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

package com.example;

import com.microsoft.playwright.*;
import org.testng.annotations.*;

public class BaseClass {

    // Shared between all tests in this class.
    Playwright playwright;
    Browser browser = null;

    // New instance for each test method.
    BrowserContext context;
    Page page;

    @BeforeClass
    @Parameters("browser")
    void launchBrowser(String browserName) {

        playwright = Playwright.create();
        BrowserType browserType = null;

        if (browserName.equals("chromium")) {
            browserType = playwright.chromium();
        } else if (browserName.equals("firefox")) {
            browserType = playwright.firefox();
        } else if (browserName.equals("webkit")) {
            browserType = playwright.webkit();
        }

        browser = browserType.launch(new BrowserType.LaunchOptions().setHeadless(false));
    }

    @BeforeMethod
    void createContextAndPage() {
        context = browser.newContext();
        page = context.newPage();
        page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    }

    @AfterMethod
    void closeContext() {
        context.close();
    }

    @AfterClass
    void closeBrowser() {
        playwright.close();
    }
}

Playwright playwright;
Browser browser = null;
BrowserContext context;
Page page;
@BeforeClass
    @Parameters("browser")
    void launchBrowser(String browserName) {

        playwright = Playwright.create();
        BrowserType browserType = null;

        if (browserName.equals("chromium")) {
            browserType = playwright.chromium();
        } else if (browserName.equals("firefox")) {
            browserType = playwright.firefox();
        } else if (browserName.equals("webkit")) {
            browserType = playwright.webkit();
        }

        browser = browserType.launch(new BrowserType.LaunchOptions().setHeadless(false));
    }

@BeforeMethod
void createContextAndPage() {
      context = browser.newContext();
      page = context.newPage();
      page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
}
@AfterMethod
   void closeContext() {
       context.close();
}
@AfterClass
void closeBrowser() {
      playwright.close();
}

package com.example;

import org.testng.annotations.*;

import static org.testng.Assert.assertEquals;

public class CrossBrowserTests extends BaseClass{

    @Test
    void verifyPageTitle() {
        System.out.println("Page Title :" + page.title());
        assertEquals("OrangeHRM", page.title());
    }

    @Test
    void verifyInvalidCredentials() {
        page.locator("input[name='username']").fill("Playwright");
        page.locator("input[name='password']").fill("admin123");
        page.locator("button[type='submit']").click();
        String expectedValue = page.locator("//p[contains(@class, \"oxd-text oxd-text--p oxd-alert-content-text\")]").textContent();
        assertEquals(expectedValue,"Invalid credentials");
    }
    
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Playwright test suite">
    <test name="Chrome Test">
        <parameter name="browser" value="chromium" />
        <classes>
           <class name="com.example.CrossBrowserTests"/>
    </classes>
    </test>
    <test name="firefox Test">
        <parameter name="browser" value="firefox" />
        <classes>
            <class name="com.example.CrossBrowserTests"/>
        </classes>
    </test> <!-- Test -->

    <test name="WebKit Test">
        <parameter name="browser" value="webkit" />
        <classes>
            <class name="com.example.CrossBrowserTests"/>
        </classes>
    </test> <!-- Test -->
</suite>

void launchBrowser(@Optional ("chromium")  String browserName) 

This will run the tests in all 3 browsers as mentioned in the .xml file.

Integration of Playwright Java with TestNG

HOME

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>Playwright_TestNG_Demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Playwright_TestNG_Demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <playwright.version>1.57.0</playwright.version>
    <testng.version>7.11.0</testng.version>
    <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
  </properties>

  <dependencies>

    <dependency>
      <groupId>com.microsoft.playwright</groupId>
      <artifactId>playwright</artifactId>
      <version>${playwright.version}</version>
    </dependency>

    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source.version}</source>
          <target>${maven.compiler.target.version}</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>testng.xml</suiteXmlFile>
          </suiteXmlFiles>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Playwright test suite">
    <test name="Integration of Playwright Java with TestNG">
    <classes>
        <class name="com.example.TestNG_Demo_Tests">
        </class>
    </classes>
    </test>
</suite>

package com.example;

import com.microsoft.playwright.*;
import org.testng.annotations.*;

import static org.testng.Assert.assertEquals;


public class TestNG_Demo_Tests {

    // Shared between all tests in this class.
    Playwright playwright;
    Browser browser;

    // New instance for each test method.
    BrowserContext context;
    Page page;

    @BeforeClass
    void launchBrowser() {
        playwright = Playwright.create();
        browser = playwright.chromium().launch();
    }

    @BeforeMethod
    void createContextAndPage() {
        context = browser.newContext();
        page = context.newPage();
        page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    }

    @Test
    void verifyPageTitle() {
        System.out.println("Page Title :" + page.title());
        assertEquals("OrangeHRM", page.title());
    }

    @Test
    void verifyLogin() {
        page.locator("input[name='username']").fill("Admin");
        page.locator("input[name='password']").fill("admin123");
        page.locator("button[type='submit']").click();
        String expectedValue = page.locator("//h6[contains(@class, \"oxd-topbar-header-breadcrumb-module\")]").textContent();
        assertEquals(expectedValue,"Dashboard");
    }

    @Test
    void verifyInvalidCredentials() {
        page.locator("input[name='username']").fill("Playwright");
        page.locator("input[name='password']").fill("admin123");
        page.locator("button[type='submit']").click();
        String expectedValue = page.locator("//p[contains(@class, \"oxd-text oxd-text--p oxd-alert-content-text\")]").textContent();
        assertEquals(expectedValue,"Invalid credentials");
    }

    @AfterMethod
    void closeContext() {
        context.close();
    }

    @AfterClass
    void closeBrowser() {
        playwright.close();
    }
}
Playwright playwright;
Browser browser = null;
BrowserContext context;
Page page;

This method is annotated with @BeforeClass, indicating it runs once before any test methods in the current class.

The browser is launched in Chromium and non-headless mode (setHeadless(false)), meaning an actual browser window is opened.

@BeforeMethod
void createContextAndPage() {
      context = browser.newContext();
      page = context.newPage();
      page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
}
@AfterMethod
   void closeContext() {
       context.close();
}
@AfterClass
void closeBrowser() {
      playwright.close();
}

TestNG Multiple Choice Answers

HOME












<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="SampleSuite">
    <test name="SampleTest">
        <classes>
            <class name="com.example.MyTestClass" />
        </classes>
    </test>
</suite>













25 Useful TestNG Multiple-Choice Questions | Self-Test Your Knowledge

HOME

Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer


Answer

How to Use dependsOnMethods() in TestNG for Selenium Test Case Dependency

HOME

import org.testng.annotations.Test;

public class TestNGMethodDependencyDemo {

    @Test
    public static void FirstTest() {
        System.out.println("This is Test Case 1");
    }

    @Test(dependsOnMethods = "FirstTest")
    public static void SecondTest() {
        System.out.println("This is Test Case 2 and will be executed after Test Case 1 successfully executed");
    }

    @Test
    public static void ThirdTest() {
        System.out.println("This is Test Case 3");
    }

    @Test
    public static void FourthTest() {
        System.out.println("This is Test Case 4");
    }
}

In the below scenario, Test Case 2 is dependent on Test CASE 1. If Test Case 1 fails, then Test Case 2 will skip.

package TestNGDemo;

import org.testng.annotations.Test;
public class TestNGMethodDependencyErrorDemo {

      @Test
      public static void FirstTest() {
            System.out.println("This is Test Case 1");
            throw new RuntimeException();
      }

      @Test(dependsOnMethods = "FirstTest")
      public static void SecondTest() {
          System.out.println("This is Test Case 2 and will be executed after Test Case 1 sucessfully executed");
     }

     @Test
     public static void ThirdTest() {
          System.out.println("This is Test Case 3");
     }

      @Test
      public static void FourthTest() {
            System.out.println("This is Test Case 4");
    }
}