Answer
Designing a BaseTest Class
BaseTest is the foundation of a well-structured Selenium framework. Every test class extends it, getting driver management, config loading, and utilities for free.
Complete BaseTest Implementation
Java
package base;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.testng.annotations.*;
import java.io.FileInputStream;
import java.time.Duration;
import java.util.Properties;
public class BaseTest {
// ThreadLocal for parallel execution safety
private static ThreadLocal<WebDriver> tlDriver = new ThreadLocal<>();
protected Properties config;
public static WebDriver getDriver() {
return tlDriver.get();
}
@BeforeSuite
public void loadConfig() throws Exception {
config = new Properties();
FileInputStream fis = new FileInputStream(
System.getProperty("user.dir") + "/src/test/resources/config.properties"
);
config.load(fis);
}
@Parameters("browser")
@BeforeMethod
public void setUp(@Optional("chrome") String browser) {
WebDriver driver = createDriver(browser);
tlDriver.set(driver);
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(30));
driver.get(config.getProperty("baseUrl", "https://automateqa.online"));
}
private WebDriver createDriver(String browser) {
return switch (browser.toLowerCase()) {
case "firefox" -> {
WebDriverManager.firefoxdriver().setup();
yield new FirefoxDriver();
}
case "edge" -> {
WebDriverManager.edgedriver().setup();
yield new EdgeDriver();
}
default -> {
WebDriverManager.chromedriver().setup();
ChromeOptions opts = new ChromeOptions();
if (Boolean.parseBoolean(System.getProperty("headless", "false"))) {
opts.addArguments("--headless=new", "--no-sandbox",
"--disable-dev-shm-usage", "--window-size=1920,1080");
}
yield new ChromeDriver(opts);
}
};
}
@AfterMethod(alwaysRun = true)
public void tearDown() {
if (getDriver() != null) {
getDriver().quit();
tlDriver.remove();
}
}
}
config.properties
PROPERTIES
baseUrl=https://staging.automateqa.online
browser=chrome
headless=false
implicitWait=10
pageLoadTimeout=30
Test Class — Extends BaseTest
Java
public class LoginTest extends BaseTest {
@Test
public void validLoginTest() {
WebDriver driver = getDriver();
driver.findElement(By.id("username")).sendKeys("admin");
driver.findElement(By.id("password")).sendKeys("secret");
driver.findElement(By.id("loginBtn")).click();
Assert.assertTrue(driver.getTitle().contains("Dashboard"));
}
}
What BaseTest Should Handle
| Responsibility | Where |
|---|---|
| Driver creation | @BeforeMethod |
| Config loading | @BeforeSuite |
| Browser selection | @Parameters("browser") |
| Parallel safety | ThreadLocal<WebDriver> |
| Screenshots on fail | @AfterMethod + ITestResult |
| Driver cleanup | @AfterMethod(alwaysRun=true) |
| Common waits | Utility methods or separate BasePage |
