Product companies and some service companies will ask you to write code on a whiteboard, in a shared editor, or on paper. You MUST be able to write a Page Object class, a TestNG test, a DataProvider, and a wait utility from memory. Practice these until you can write them without thinking.
The interviewer says: "Write a complete test for login functionality with valid and invalid credentials." Here is what they want to see:
public class LoginTest extends BaseTest {
@Test(dataProvider = "loginData")
public void testLogin(String username, String password, boolean shouldPass) {
LoginPage loginPage = new LoginPage(getDriver());
loginPage.enterUsername(username);
loginPage.enterPassword(password);
loginPage.clickLogin();
if (shouldPass) {
DashboardPage dashboard = new DashboardPage(getDriver());
Assert.assertTrue(dashboard.isPageLoaded(),
"Dashboard should load after valid login");
} else {
Assert.assertTrue(loginPage.isErrorMessageDisplayed(),
"Error message should appear for invalid login");
}
}
@DataProvider(name = "loginData")
public Object[][] loginData() {
return new Object[][] {
{"admin", "password123", true},
{"admin", "wrongpass", false},
{"", "password123", false},
{"admin", "", false},
{"invalid@user", "password123", false}
};
}
}The interviewer says: "Write a complete Page Object for a login page." They are checking: private locators, public methods, BasePage inheritance, return types, and wait usage.
public class LoginPage extends BasePage {
private By usernameField = By.id("username");
private By passwordField = By.id("password");
private By loginButton = By.id("login-btn");
private By errorMessage = By.cssSelector(".error-message");
private By forgotPasswordLink = By.linkText("Forgot Password?");
public LoginPage(WebDriver driver) {
super(driver);
}
public LoginPage enterUsername(String username) {
type(usernameField, username);
return this;
}
public LoginPage enterPassword(String password) {
type(passwordField, password);
return this;
}
public DashboardPage clickLogin() {
waitForClickable(loginButton);
return new DashboardPage(driver);
}
public DashboardPage login(String username, String password) {
enterUsername(username);
enterPassword(password);
return clickLogin();
}
public boolean isErrorMessageDisplayed() {
return isDisplayed(errorMessage);
}
public String getErrorMessageText() {
return getText(errorMessage);
}
public ForgotPasswordPage clickForgotPassword() {
waitForClickable(forgotPasswordLink);
return new ForgotPasswordPage(driver);
}
@Override
public boolean isPageLoaded() {
return isDisplayed(usernameField);
}
}This challenge tests whether you understand the foundation layer. The interviewer wants to see reusable wait methods, protected access for child classes, and clean abstraction.
public abstract class BasePage {
protected WebDriver driver;
protected WebDriverWait wait;
private static final Logger logger = LogManager.getLogger(BasePage.class);
protected BasePage(WebDriver driver) {
this.driver = driver;
int timeout = Integer.parseInt(
ConfigReader.getInstance().getProperty("timeout"));
this.wait = new WebDriverWait(driver, Duration.ofSeconds(timeout));
}
protected WebElement waitForVisible(By locator) {
logger.info("Waiting for visible: " + locator);
return wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
}
protected void waitForClickable(By locator) {
logger.info("Clicking: " + locator);
wait.until(ExpectedConditions.elementToBeClickable(locator)).click();
}
protected void type(By locator, String text) {
logger.info("Typing '" + text + "' into: " + locator);
WebElement element = waitForVisible(locator);
element.clear();
element.sendKeys(text);
}
protected String getText(By locator) {
return waitForVisible(locator).getText();
}
protected boolean isDisplayed(By locator) {
try {
return driver.findElement(locator).isDisplayed();
} catch (NoSuchElementException e) {
return false;
}
}
protected void scrollToElement(WebElement element) {
((JavascriptExecutor) driver).executeScript(
"arguments[0].scrollIntoView({block:'center'});", element);
}
public abstract boolean isPageLoaded();
}// ExcelReader utility
public class ExcelReader {
public static List<Map<String, String>> getTestData(
String filePath, String sheetName) {
List<Map<String, String>> data = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(filePath);
XSSFWorkbook workbook = new XSSFWorkbook(fis)) {
XSSFSheet sheet = workbook.getSheet(sheetName);
Row headerRow = sheet.getRow(0);
List<String> headers = new ArrayList<>();
for (Cell cell : headerRow) {
headers.add(cell.getStringCellValue());
}
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) continue;
Map<String, String> rowData = new LinkedHashMap<>();
for (int j = 0; j < headers.size(); j++) {
Cell cell = row.getCell(j);
rowData.put(headers.get(j),
cell != null ? cell.toString() : "");
}
data.add(rowData);
}
} catch (IOException e) {
throw new RuntimeException("Failed to read Excel: " + e.getMessage());
}
return data;
}
}
// DataProvider using ExcelReader
@DataProvider(name = "registrationData")
public Object[][] registrationData() {
List<Map<String, String>> data = ExcelReader.getTestData(
"src/test/resources/testdata/registration.xlsx", "Sheet1");
return data.stream()
.map(row -> new Object[]{row})
.toArray(Object[][]::new);
}
// Test using the DataProvider
@Test(dataProvider = "registrationData")
public void testRegistration(Map<String, String> data) {
RegistrationPage regPage = new RegistrationPage(getDriver());
regPage.enterName(data.get("name"));
regPage.enterEmail(data.get("email"));
regPage.enterPassword(data.get("password"));
regPage.clickRegister();
Assert.assertEquals(regPage.getConfirmation(), data.get("expected"));
}public class BrowserFactory {
public static WebDriver createDriver(String browser) {
WebDriver driver;
boolean headless = Boolean.parseBoolean(
ConfigReader.getInstance().getProperty("headless"));
switch (browser.toLowerCase()) {
case "chrome":
ChromeOptions chromeOptions = new ChromeOptions();
if (headless) chromeOptions.addArguments("--headless=new");
chromeOptions.addArguments("--window-size=1920,1080");
chromeOptions.addArguments("--disable-notifications");
driver = new ChromeDriver(chromeOptions);
break;
case "firefox":
FirefoxOptions firefoxOptions = new FirefoxOptions();
if (headless) firefoxOptions.addArguments("--headless");
driver = new FirefoxDriver(firefoxOptions);
break;
case "edge":
EdgeOptions edgeOptions = new EdgeOptions();
if (headless) edgeOptions.addArguments("--headless=new");
driver = new EdgeDriver(edgeOptions);
break;
default:
throw new IllegalArgumentException(
"Unsupported browser: " + browser);
}
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(
Duration.ofSeconds(30));
return driver;
}
}Practice writing these classes on paper or a whiteboard without any IDE help. No autocomplete, no imports suggestion. If you can write a LoginPage and a LoginTest from memory in 10 minutes, you are ready for the coding round.
Key Point: Coding challenges are about writing clean, working code from memory. Practice Page Object, TestNG test, DataProvider, BasePage, and BrowserFactory until they are muscle memory.