Why framework design enables scalability in Selenium Java - Automation Benefits in Action
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.time.Duration; // Page Object for Login Page class LoginPage { private WebDriver driver; private WebDriverWait wait; private By usernameField = By.id("username"); private By passwordField = By.id("password"); private By loginButton = By.id("loginBtn"); public LoginPage(WebDriver driver) { this.driver = driver; this.wait = new WebDriverWait(driver, Duration.ofSeconds(10)); } public void enterUsername(String username) { wait.until(ExpectedConditions.visibilityOfElementLocated(usernameField)).sendKeys(username); } public void enterPassword(String password) { wait.until(ExpectedConditions.visibilityOfElementLocated(passwordField)).sendKeys(password); } public void clickLogin() { wait.until(ExpectedConditions.elementToBeClickable(loginButton)).click(); } } // Page Object for Dashboard Page class DashboardPage { private WebDriver driver; private WebDriverWait wait; private By welcomeMessage = By.id("welcomeMsg"); public DashboardPage(WebDriver driver) { this.driver = driver; this.wait = new WebDriverWait(driver, Duration.ofSeconds(10)); } public boolean isWelcomeMessageDisplayed() { return wait.until(ExpectedConditions.visibilityOfElementLocated(welcomeMessage)).isDisplayed(); } } public class LoginTest { private WebDriver driver; private LoginPage loginPage; private DashboardPage dashboardPage; @BeforeClass public void setUp() { driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://example.com/login"); loginPage = new LoginPage(driver); dashboardPage = new DashboardPage(driver); } @Test public void testValidLogin() { loginPage.enterUsername("validUser"); loginPage.enterPassword("validPass123"); loginPage.clickLogin(); // Verify URL String expectedUrl = "https://example.com/dashboard"; WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions.urlToBe(expectedUrl)); Assert.assertEquals(driver.getCurrentUrl(), expectedUrl, "URL after login should be dashboard URL"); // Verify welcome message Assert.assertTrue(dashboardPage.isWelcomeMessageDisplayed(), "Welcome message should be visible on dashboard"); } @AfterClass public void tearDown() { if (driver != null) { driver.quit(); } } }
This test uses the Page Object Model (POM) design pattern to separate page details from test logic, making the framework scalable and easy to maintain.
The LoginPage class contains locators and methods for interacting with the login page. The DashboardPage class contains methods to verify elements on the dashboard.
The test class LoginTest initializes the browser, opens the login page, performs login steps, and asserts the expected URL and presence of a welcome message.
Explicit waits ensure the test waits for elements or URL changes, avoiding flaky tests.
Assertions from TestNG verify the expected outcomes clearly.
This design allows easy addition of new tests or pages without changing existing code, enabling scalability.
Now add data-driven testing with 3 different sets of valid username and password combinations
Practice
Solution
Step 1: Understand framework purpose
A test framework structures code and resources to manage tests efficiently.Step 2: Connect framework to scalability
Organized code allows easy addition and modification of tests as the suite grows.Final Answer:
It organizes code to make adding new tests easier and faster. -> Option CQuick Check:
Framework = organized, scalable tests [OK]
- Thinking frameworks slow down tests
- Believing frameworks remove all maintenance
- Assuming frameworks auto-generate tests
Solution
Step 1: Identify reusable method
public void login(String user, String pass) { driver.findElement(By.id("user")).sendKeys(user); driver.findElement(By.id("pass")).sendKeys(pass); driver.findElement(By.id("loginBtn")).click(); } defines a method with parameters to reuse login steps with different data.Step 2: Compare other options
The other options are either hardcoded steps or unrelated code, not reusable methods.Final Answer:
Reusable login method with parameters -> Option AQuick Check:
Reusable method = method with parameters [OK]
- Choosing hardcoded steps as reusable
- Confusing unrelated code as framework code
- Ignoring method parameters
public void openPage() { driver.get("https://example.com"); }
public void login(String user, String pass) {
driver.findElement(By.id("user")).sendKeys(user);
driver.findElement(By.id("pass")).sendKeys(pass);
driver.findElement(By.id("loginBtn")).click();
}
openPage();
login("admin", "1234");What is the main benefit of this design when adding more tests?
Solution
Step 1: Analyze method usage
openPage and login methods encapsulate common actions for reuse.Step 2: Understand scalability impact
Reusing methods avoids rewriting code, making it easier to add new tests.Final Answer:
Reuse methods to avoid rewriting code -> Option AQuick Check:
Reusable methods = easier test addition [OK]
- Thinking method calls slow tests significantly
- Believing code must be rewritten each time
- Confusing syntax errors with design benefits
public void login(String user, String pass) {
driver.findElement(By.id("username")).sendKeys(user);
driver.findElement(By.id("password")).sendKeys(pass);
driver.findElement(By.id("loginBtn")).click();
}
login("admin", "1234");But the test fails because elements are not found. What is the likely fix to improve framework scalability?
Solution
Step 1: Identify problem cause
Element locators scattered cause maintenance issues and test failures.Step 2: Apply framework design principle
Centralizing locators in one place improves maintainability and scalability.Final Answer:
Use centralized locator repository -> Option BQuick Check:
Centralized locators = easier updates [OK]
- Hardcoding locators everywhere
- Removing reusable methods
- Relying only on waits without fixing locators
Solution
Step 1: Understand scalability needs
Scalable frameworks use reusable methods to avoid duplication and ease maintenance.Step 2: Apply reusable methods to new feature
Creating reusable login and navigation methods allows easy updates and test growth.Final Answer:
Create reusable methods and call them in tests -> Option DQuick Check:
Reusable methods enable scalable test design [OK]
- Copy-pasting code causing maintenance issues
- Writing all steps inline making tests long
- Separating related steps into different tests unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
