Order of Execution (Before Annotations)

  1. @BeforeSuite – Runs once before the entire test suite.

  2. @BeforeTest – Runs before <test> tag in testng.xml.

  3. @BeforeClass – Runs before the first method in the current class.

  4. @BeforeMethod – Runs before every @Test method.


Order of Execution (After Annotations)

  1. @AfterMethod – Runs after every @Test method.

  2. @AfterClass – Runs after all test methods in the current class.

  3. @AfterTest – Runs after all tests in the <test> tag.

  4. @AfterSuite – Runs once after the entire test suite

@BeforeSuite
  @BeforeTest
    @BeforeClass
      @BeforeMethod
        @Test
      @AfterMethod
      @BeforeMethod
        @Test
      @AfterMethod
    @AfterClass
  @AfterTest
@AfterSuite

This structure is especially useful when:

  • Suite = initializing global resources (e.g., DB, reports).

  • Test = logical group (e.g., Chrome tests, Firefox tests).

  • Class = one Java test class.

  • Method = each test method.


import org.testng.annotations.*;

public class AnnotationExample {

    @BeforeSuite
    public void beforeSuite() {
        System.out.println("===> BeforeSuite: Set up DB connection or reporting");
    }

    @BeforeTest
    public void beforeTest() {
        System.out.println("===> BeforeTest: Prepare data or open browser for test group");
    }

    @BeforeClass
    public void beforeClass() {
        System.out.println("===> BeforeClass: Initialize page objects or test data for this class");
    }

    @BeforeMethod
    public void beforeMethod() {
        System.out.println("===> BeforeMethod: Launch browser or reset preconditions");
    }

    @Test
    public void test1() {
        System.out.println(">>>>> Test1: Executing test logic here");
    }

    @Test
    public void test2() {
        System.out.println(">>>>> Test2: Executing another test logic");
    }

    @AfterMethod
    public void afterMethod() {
        System.out.println("===> AfterMethod: Close browser or clean up after test");
    }

    @AfterClass
    public void afterClass() {
        System.out.println("===> AfterClass: Clean up test class resources");
    }

    @AfterTest
    public void afterTest() {
        System.out.println("===> AfterTest: Cleanup actions after group of tests");
    }

    @AfterSuite
    public void afterSuite() {
        System.out.println("===> AfterSuite: Close DB connection or finalize report");
    }
}

src/

├── base/

│   └── BaseTest.java

├── pages/

│   └── LoginPage.java

├── tests/

│   └── LoginTest.java

├── utils/

│   ├── ExcelUtil.java

│   ├── DBUtil.java

│   ├── ScreenshotUtil.java

│   └── ExtentManager.java

testng.xml

pom.xml

resources - config.properties, Test_Data.xlsx, Drivers****

test-output - TestNG reports

reports - Extent Reports


Base Test

package com.sample.pagefactory.base;


import com.aventstack.extentreports.ExtentReports;

import com.aventstack.extentreports.ExtentTest;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.openqa.selenium.chrome.ChromeOptions;

import org.openqa.selenium.firefox.*;

import org.testng.ITestResult;

import org.testng.annotations.*;

import com.sample.pagefactory.utils.ConfigReader;

import com.sample.pagefactory.utils.ExtentManager;

import com.sample.pagefactory.utils.ScreenshotUtils;


import java.lang.reflect.Method;


public class BaseTest {

protected WebDriver driver;

protected ExtentReports extent;

protected ExtentTest test;


@Parameters({"browser"})

@BeforeMethod

public void setup(@Optional("chrome") String browser, Method method) {

extent = ExtentManager.getInstance();

test = extent.createTest(method.getName());


// private static ThreadLocal<WebDriver> driver = new ThreadLocal<>();

//

// public static WebDriver getDriver() {

// return driver.get();

// }


boolean isHeadless = Boolean.parseBoolean

                                (ConfigReader.get("headless"));


if (browser.equalsIgnoreCase("chrome")) {

ChromeOptions options = new ChromeOptions();

if (isHeadless) {

options.addArguments("--headless=new",

                                            "--window-size=1920,1080");

}

driver = new ChromeDriver(options);

} else if (browser.equalsIgnoreCase("firefox")) {

FirefoxOptions options = new FirefoxOptions();

if (isHeadless) {

options.addArguments("-headless");

}

driver = new FirefoxDriver(options);

} else {

throw new RuntimeException("Unsupported browser: " + browser);

}


driver.manage().window().maximize();

}


@AfterMethod

public void tearDown(ITestResult result) {

if (result.getStatus() == ITestResult.FAILURE) {

String screenshotPath = ScreenshotUtils.takeScreenshot

                                            (driver, result.getName());

test.fail("Test failed", ScreenshotUtils.addScreenshot

                                                ToReport(screenshotPath));

}

if (driver != null) {

driver.quit();

}

extent.flush();

}

}

Base Test_DesiredCaps

package com.sample.pagefactory.base;


import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.openqa.selenium.chrome.ChromeOptions;

import org.openqa.selenium.MutableCapabilities;

import org.openqa.selenium.firefox.FirefoxDriver;

import org.openqa.selenium.firefox.FirefoxOptions;

import org.testng.annotations.*;

import com.sample.pagefactory.utils.ConfigReader;


import java.lang.reflect.Method;


public class BaseClass_DesiredCaps {

protected WebDriver driver;


@Parameters("browser")

@BeforeMethod

public void setup(@Optional("chrome") String browser, Method method) {

boolean isHeadless = Boolean.parseBoolean(ConfigReader.get("headless"));


switch (browser.toLowerCase()) {

case "chrome":

ChromeOptions chromeOptions = new ChromeOptions();

if (isHeadless) chromeOptions.addArguments("--headless=new");

chromeOptions.setCapability("browserName", "chrome"); // DesiredCapability logic

driver = new ChromeDriver(chromeOptions);

break;


case "firefox":

FirefoxOptions firefoxOptions = new FirefoxOptions();

if (isHeadless) firefoxOptions.addArguments("-headless");

firefoxOptions.setCapability("browserName", "firefox");

driver = new FirefoxDriver(firefoxOptions);

break;


default:

throw new RuntimeException("Unsupported browser: " + browser);

}


driver.manage().window().maximize();

}


@AfterMethod

public void tearDown() {

if (driver != null) {

driver.quit();

}

}

}



LoginPage.java


package com.sample.pagefactory.pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
WebDriver driver;
//Constructor
public LoginPage(WebDriver driver)
{
this.driver = driver;
PageFactory.initElements(driver, this);
}
//Locators
@FindBy(xpath="//input[@id='username']")
WebElement txt_username;
@FindBy(xpath="//input[@id='password']")
WebElement txt_password;
@FindBy(xpath="//button[contains(text(),'Submit')]")
WebElement btn_login;
//Action methods
public void setUserName(String user)
{
txt_username.sendKeys(user);
}
public void setPassword(String pwd)
{
txt_password.sendKeys(pwd);
}
public void clickLogin()
{
btn_login.click();;
}
}

LoginTest_Properties.java

package com.sample.pagefactory.tests;
import com.sample.pagefactory.pages.LoginPage;
import com.sample.pagefactory.utils.ConfigReader;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
import org.testng.Assert;
import org.testng.Reporter;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import java.time.Duration;
public class LoginTest_Properties  {
WebDriver driver;
@BeforeClass
void Setup()
{
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
driver.get(ConfigReader.get("url"));
}
@Test
void testLogin() throws InterruptedException
{
LoginPage lp = new LoginPage(driver);
lp.setUserName(ConfigReader.get("username"));
Reporter.log("Entered user name");
lp.setPassword(ConfigReader.get("password"));
Reporter.log("Entered password");
lp.clickLogin();
Reporter.log("Clicked on Login button");
Thread.sleep(2000);
String title = driver.getTitle();
Assert.assertEquals(title, "Secure Page page for Automation Testing Practice");
Reporter.log("Title displayed successfully");
}
@AfterClass
void Teardown()
{
driver.quit();
}
    }

LoginTest_DP_Excel

package com.sample.pagefactory.tests;

import com.sample.pagefactory.base.BaseTest;
import org.testng.Assert;
import org.testng.Reporter;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.sample.pagefactory.pages.LoginPage;
import com.sample.pagefactory.utils.ExcelUtils;

public class LoginTest_DP_Excel extends BaseTest {

    @Test(dataProvider = "loginData")
    public void testLogin(String username, String password) {
        driver.get("https://practice.expandtesting.com/login");
        LoginPage lp = new LoginPage(driver);
        lp.setUserName(username);
Reporter.log("Entered user name");
lp.setPassword(password);
Reporter.log("Entered password");
lp.clickLogin();
Reporter.log("Click on Login button");        
String title = driver.getTitle();
Assert.assertEquals(title, "The Internet");
Reporter.log("Page title verified successfully");
        test.pass("Login test passed with user: " + username);
    }

    @DataProvider(name = "loginData")
    public Object[][] getData() {
        return ExcelUtils.getData(System.getProperty("user.dir")+"/src/main/resources/Test_Data.xlsx", "Sheet1");
    }
}


ConfigReader.java

package com.sample.pagefactory.utils;

import java.io.FileInputStream;
import java.util.Properties;

public class ConfigReader {
    private static Properties prop = new Properties();

    static {
        try {
            FileInputStream fis = new FileInputStream(System.getProperty("user.dir")+"src/main/resources/config.properties");
            prop.load(fis);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String get(String key) {
        return prop.getProperty(key);
    }
}

DBUtils.java

package com.sample.pagefactory.utils;


import java.sql.*;


public class DBUtils {


public static void readDB(String query) {

try (Connection con = DriverManager.getConnection("jdbc:mysql:

                //localhost:3306/testdb", "user", "password");

Statement stmt = con.createStatement();

ResultSet rs = stmt.executeQuery(query)) {

while (rs.next()) {

System.out.println(rs.getString(1)); // customize as needed

}

} catch (Exception e) {

e.printStackTrace();

}

}

}


ExcelUtils.java

package com.sample.pagefactory.utils;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;

public class ExcelUtils {

    public static Object[][] getData(String filePath, String sheetName) {
        try (FileInputStream fis = new FileInputStream(filePath);
             Workbook workbook = new XSSFWorkbook(fis)) {
            Sheet sheet = workbook.getSheet(sheetName);
            int rows = sheet.getPhysicalNumberOfRows();
            int r = sheet.getLastRowNum();
            int cols = sheet.getRow(0).getLastCellNum();

            Object[][] data = new Object[rows - 1][cols];

            for (int i = 1; i < rows; i++) {
                for (int j = 0; j < cols; j++) {
                    Cell cell = sheet.getRow(i).getCell(j);
                    data[i - 1][j] = cell.toString();
                }
            }
            return data;
        } catch (Exception e) {
            e.printStackTrace();
            return new Object[0][0];
        }
    }
}

ExtentManager.java

package com.sample.pagefactory.utils;

import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.reporter.ExtentSparkReporter;

public class ExtentManager {
    private static ExtentReports extent;

    public static ExtentReports getInstance() {
        if (extent == null) {
            ExtentSparkReporter reporter = new ExtentSparkReporter("reports/report.html");
            extent = new ExtentReports();
            extent.attachReporter(reporter);
        }
        return extent;
    }
}

ScreenshotUtils.java

package com.sample.pagefactory.utils;

import com.aventstack.extentreports.MediaEntityBuilder;
import com.aventstack.extentreports.model.Media;

import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;

import java.io.File;
import java.nio.file.Files;

public class ScreenshotUtils {

    public static String takeScreenshot(WebDriver driver, String testName) {
        try {
            File src = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
            String path = System.getProperty("user.dir") + "screenshots/" + testName + ".png";
            File dest = new File(path);
            Files.copy(src.toPath(), dest.toPath());
            return dest.getAbsolutePath();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

//  public static com.aventstack.extentreports.MediaEntityModelProvider addScreenshotToReport(String path) {
    public static Media addScreenshotToReport(String path) {
        try {
            return MediaEntityBuilder.createScreenCaptureFromPath(path).build();
        } catch (Exception e) {
            return null;
        }
    }
}


TestListener.java

package com.sample.pagefactory.utils;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class TestListener implements ITestListener {

    @Override
    public void onStart(ITestContext context) {
        System.out.println("Test started: " + context.getName());        
    }

    @Override
    public void onTestSuccess(ITestResult result) {
        System.out.println("Test passed: " + result.getTestName());
    }

    @Override
    public void onTestFailure(ITestResult result) {
        System.out.println("Test failed: " + result.getTestName());
        // Add code here to take a screenshot, log details, etc.
    }

    @Override
    public void onTestSkipped(ITestResult result) {
        System.out.println("Test skipped: " + result.getTestName());
    }

    @Override
    public void onFinish(ITestContext context) {
        System.out.println("Test run finished." + context.getName());
    }