Day 04 β Base Class Refactoring & TestNG Suite Integration
By Day 03, we had a working Base Class that could:
- Launch a browser
- Read configuration values
- Open the application
- Close the browser
On Day 04, we make this code production-ready.
Today is about:
- Refactoring (cleaning and modularising code)
- Optimising TestNG lifecycle usage
- Introducing TestNG XML for suite-level execution
This is the point where our framework starts to feel professional.
π― Why Refactoring Is Necessary
As frameworks grow:
- One long method becomes hard to debug
- Changes in one place can break others
- Reusability drops
Refactoring helps us:
- Split responsibilities
- Improve readability
- Prepare for parallel execution later
π Rule of thumb:
Small methods, single responsibility.
Step 1: Refactoring the Base Class (Modern Approach)
π§ Key Improvements from Day 03
β Load configuration once per suite
β Separate browser launch and configuration
β Avoid unnecessary static waits
β Prepare for cross-browser and parallel execution
π Updated File Location
src/main/java
βββ com.orangehrm.base
βββ BaseClass.java
β
Refactored BaseClass.java (Industry Standard)
package com.orangehrm.base;
import java.io.FileInputStream;
import java.time.Duration;
import java.util.Properties;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
public class BaseClass {
protected static Properties prop;
protected WebDriver driver;
// Load configuration only once before suite execution
@BeforeSuite
public void loadConfig() {
try {
prop = new Properties();
FileInputStream fis = new FileInputStream(
System.getProperty("user.dir") + "/src/main/resources/config.properties"
);
prop.load(fis);
} catch (Exception e) {
throw new RuntimeException("Failed to load config.properties", e);
}
}
// Runs before every test method
@BeforeMethod
public void setup() {
launchBrowser();
configureBrowser();
}
// Browser initialization
private void launchBrowser() {
String browser = prop.getProperty("browser").toLowerCase();
switch (browser) {
case "chrome":
driver = new ChromeDriver(); // Selenium Manager handles driver
break;
case "firefox":
driver = new FirefoxDriver();
break;
case "edge":
driver = new EdgeDriver();
break;
default:
throw new RuntimeException("Unsupported browser: " + browser);
}
}
// Browser configuration
private void configureBrowser() {
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(
Duration.ofSeconds(Integer.parseInt(prop.getProperty("implicit_wait")))
);
driver.get(prop.getProperty("url"));
}
// Runs after every test method
@AfterMethod
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}
π Important Corrections & Best Practices
β Why We Removed LockSupport / Static Waits
- Hard waits are not recommended in modern frameworks
- They block execution unnecessarily
- We will rely on explicit waits inside the Action Driver (Day 05)
π Static waits should only be used for debugging, not framework design.
β
Why @BeforeSuite Is Used for Config
- Configuration data is global
- Loading it once improves performance
- Prevents repeated file I/O operations
β Why WebDriver Is NOT Static
- Static WebDriver breaks parallel execution
- Causes session conflicts
- Modern frameworks use instance-level drivers
Parallel execution will be introduced later using ThreadLocal.
Step 2: Introducing TestNG XML (Suite Control Center)
So far, we ran tests by right-clicking test classes.
In real projects, this is never done.
Instead, we use TestNG XML to:
- Group tests
- Control execution order
- Enable parallel runs
- Integrate with CI/CD
π Create testng.xml
Location (recommended):
src/test/resources/testng.xml
π§Ύ testng.xml (Clean & Correct)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="OrangeHRM Automation Suite">
<test name="Smoke Tests">
<classes>
<class name="com.orangehrm.tests.DummyTest"/>
</classes>
</test>
</suite>
Step 3: Running Tests Using TestNG XML
βΆ How to Run
- Right-click
testng.xml - Select Run As β TestNG Suite
β Expected Flow
- Config loads once
- Browser launches before each test
- Application opens
- Test executes
- Browser closes cleanly
This is exactly how CI tools like Jenkins run tests.
π Day 04 Summary
Today, you:
- Refactored the Base Class for scalability
- Applied TestNG lifecycle correctly
- Introduced suite-based execution
- Prepared the framework for future growth
Your framework is no longer βbasic automationβ β
it is now architected.
π§ Day 04 Task
- Refactor your
BaseClassas shown - Create
testng.xml - Add
DummyTestto the suite - Run tests using TestNG Suite, not individual classes
π Whatβs Coming Next (Day 05)
Next, we will build the Action Driver:
- click()
- sendKeys()
- explicit waits
- element visibility handling
This will make test scripts:
β Smaller
β Cleaner
β Easier to read
Youβve officially crossed into framework engineering territory π
Top comments (0)