A base test class helps you write tests faster by putting common setup and cleanup steps in one place. It keeps your test code clean and easy to manage.
Base test class pattern in Selenium Java
public class BaseTest { protected WebDriver driver; @BeforeEach public void setUp() { driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://example.com"); } @AfterEach public void tearDown() { if (driver != null) { driver.quit(); } } }
The base class uses @BeforeEach to run setup before every test.
The driver is protected so child test classes can use it.
public class BaseTest { protected WebDriver driver; @BeforeEach public void setUp() { driver = new FirefoxDriver(); driver.manage().window().maximize(); driver.get("https://example.com"); } @AfterEach public void tearDown() { if (driver != null) { driver.quit(); } } }
public class BaseTest { protected WebDriver driver; @BeforeEach public void setUp() { driver = new ChromeDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://example.com"); } @AfterEach public void tearDown() { if (driver != null) { driver.quit(); } } }
This test class HomePageTest extends the base class. It opens the browser, goes to example.com, and checks the page title. The browser closes automatically after the test.
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import static org.junit.jupiter.api.Assertions.assertEquals; public class BaseTest { protected WebDriver driver; @BeforeEach public void setUp() { driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://example.com"); } @AfterEach public void tearDown() { if (driver != null) { driver.quit(); } } } public class HomePageTest extends BaseTest { @Test public void testHomePageTitle() { String title = driver.getTitle(); assertEquals("Example Domain", title); } }
Always quit the driver in @AfterEach to close the browser and free resources.
Use protected access for the WebDriver so child classes can use it but it stays hidden from outside.
Keep your base test class simple and focused on setup and teardown only.
A base test class saves time by sharing setup and cleanup code.
Child test classes extend the base class to reuse the WebDriver and setup steps.
This pattern keeps tests clean, organized, and easy to maintain.
Practice
Base Test Class in Selenium Java testing?Solution
Step 1: Understand the role of a base test class
A base test class contains common setup and cleanup methods that multiple test classes can reuse.Step 2: Identify the benefit of code reuse
Sharing setup code avoids duplication and keeps tests organized and maintainable.Final Answer:
To share common setup and cleanup code across multiple test classes -> Option AQuick Check:
Base test class = shared setup/cleanup [OK]
- Thinking base class holds all tests
- Ignoring code reuse benefits
- Confusing base class with utility classes
Solution
Step 1: Check Java class declaration syntax
public class BaseTest { WebDriver driver; @BeforeEach void setup() { /* init driver */ } } correctly declares a public class with a WebDriver field and a setup method annotated with @BeforeEach.Step 2: Identify errors in other options
class BaseTest { void setup() { WebDriver driver = new WebDriver(); } } misses access modifiers and uses local driver variable incorrectly. public BaseTest { WebDriver driver; void setup() { } } lacks 'class' keyword. public class BaseTest extends WebDriver { void setup() { } } wrongly extends WebDriver, which is an interface.Final Answer:
public class BaseTest { WebDriver driver; @BeforeEach void setup() { /* init driver */ } } -> Option DQuick Check:
Correct class syntax with setup method = public class BaseTest { WebDriver driver; @BeforeEach void setup() { /* init driver */ } } [OK]
- Missing 'public' keyword
- Incorrect class declaration syntax
- Extending WebDriver interface wrongly
ChildTest.testExample()?
public class BaseTest {
WebDriver driver;
@BeforeEach
void setup() {
driver = new ChromeDriver();
System.out.println("Setup done");
}
@AfterEach
void teardown() {
driver.quit();
System.out.println("Teardown done");
}
}
public class ChildTest extends BaseTest {
@Test
void testExample() {
System.out.println("Test running");
}
}Solution
Step 1: Understand JUnit lifecycle with base class
@BeforeEach runs before each test method, @AfterEach runs after. ChildTest inherits these methods.Step 2: Trace the output order
First "Setup done" prints from setup(), then "Test running" from testExample(), finally "Teardown done" from teardown().Final Answer:
Setup done Test running Teardown done -> Option BQuick Check:
@BeforeEach -> test -> @AfterEach = Setup done Test running Teardown done [OK]
- Assuming setup runs after test
- Ignoring inheritance of setup/teardown
- Mixing order of print statements
public class BaseTest {
WebDriver driver;
@BeforeEach
void setup() {
driver = new ChromeDriver();
}
@AfterEach
void teardown() {
driver.close();
}
}Solution
Step 1: Understand difference between driver.close() and driver.quit()
driver.close() closes current window, driver.quit() closes all windows and ends session.Step 2: Identify best practice for cleanup
In teardown, driver.quit() is preferred to fully close browser and free resources.Final Answer:
Using driver.close() instead of driver.quit() in teardown -> Option AQuick Check:
Proper cleanup uses driver.quit() [OK]
- Confusing driver.close() with driver.quit()
- Forgetting to quit WebDriver session
- Assuming driver.close() frees all resources
Solution
Step 1: Understand JUnit 5 lifecycle annotations
@BeforeAll and @AfterAll run once before and after all tests; methods must be static by default.Step 2: Match requirement to annotations
To initialize WebDriver once before all tests and quit after all tests, use @BeforeAll and @AfterAll with static methods.Final Answer:
@BeforeAll for setup and @AfterAll for teardown with static methods -> Option CQuick Check:
One-time setup/teardown = @BeforeAll/@AfterAll static [OK]
- Using @BeforeEach/@AfterEach for one-time setup
- Not making @BeforeAll/@AfterAll methods static
- Mixing instance and static lifecycle methods
Ready to prove it?
Pass the test and this pattern moves unknown
