Interview #25: How to create & use custom exception in Java Test automation?

In Java test automation, custom exceptions can improve the readability and maintainability of your test framework, as well as provide more meaningful information when a test fails. Here’s a detailed guide on creating and using custom exceptions in Java for test automation.

Disclaimer: For QA-Testing Jobs, WhatsApp us @ 91-6232667387

Why Use Custom Exceptions in Test Automation?

Standard Java exceptions (like NullPointerException or IllegalArgumentException) provide limited information. Custom exceptions help:

  1. Identify Specific Failures: Custom names make it clear where the problem originated.
  2. Add Context-Specific Information: Custom exception messages can be tailored to provide more useful information.
  3. Control Exception Handling: Allows you to handle exceptions in a specific way in test code, e.g., logging to a specific file, retrying actions, or even terminating the test.

Steps to Create a Custom Exception

1. Define a Custom Exception Class

To create a custom exception in Java, define a new class that extends the Exception class (for checked exceptions) or RuntimeException class (for unchecked exceptions). In test automation, unchecked exceptions (subclasses of RuntimeException) are often preferred because they don’t require explicit handling.

// Custom Exception for Element Not Found in UI
public class ElementNotFoundException extends RuntimeException {
public ElementNotFoundException(String message) {
super(message);
}

public ElementNotFoundException(String message, Throwable cause) {
super(message, cause);
}
}

2. Add Constructors to Your Custom Exception

Typically, two constructors are useful:

  • One that accepts a String message, allowing you to pass a custom error message when the exception is thrown.
  • Another that accepts both a String message and a Throwable cause, so you can include a cause if the exception was triggered by another exception.

public class ElementNotFoundException extends RuntimeException {
// Constructor with only message
public ElementNotFoundException(String message) {
super(message);
}
// Constructor with message and cause
public ElementNotFoundException(String message, Throwable cause) {
super(message, cause);
}
}

3. Throw the Custom Exception in Your Test Code

Wherever a condition or state does not meet expectations (e.g., a UI element not found), throw your custom exception. This makes test failures more meaningful.

For example, in a Selenium-based UI test framework, you might throw this exception when an element cannot be located:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
public class LoginPage {
private WebDriver driver;
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public WebElement findUsernameField() {
try {
return driver.findElement(By.id("username"));
} catch (NoSuchElementException e) {
throw new ElementNotFoundException("Username field was not found on the Login page.", e);
}
}
}

4. Handle the Custom Exception (Optional)

Handling custom exceptions in a test framework can help with logging, retrying actions, or performing other recovery actions. However, in most test scenarios, simply throwing the exception may be sufficient to fail the test.

public class LoginTest {
public void loginWithInvalidCredentials() {
try {
LoginPage loginPage = new LoginPage(driver);
WebElement usernameField = loginPage.findUsernameField();
usernameField.sendKeys("invalidUser");
// Additional steps...
} catch (ElementNotFoundException e) {
System.err.println("Custom Exception Caught: " + e.getMessage());
// Optionally log to a file or take a screenshot for debugging
}
}
}

5. Example of Another Custom Exception

Another custom exception could be used for a failed assertion in test validation, such as an assertion failure on an element’s text.

public class AssertionException extends RuntimeException {
public AssertionException(String message) {
super(message);
}
}

And then, use it like this in your test assertions:

public void verifyElementText(String expected, WebElement element) {
String actual = element.getText();
if (!actual.equals(expected)) {
throw new AssertionException("Text assertion failed: expected [" + expected + "] but found [" + actual + "]");
}
}

Advantages of Using Custom Exceptions in Test Automation

  • Clearer Debugging Information: You know exactly what went wrong without needing to dig through stack traces.
  • Improved Test Failure Reporting: Makes it easier to pinpoint failure points, allowing faster issue resolution.
  • Better Test Maintenance: Test code is cleaner and more readable, especially when dealing with complex automation frameworks.

Key Considerations for Custom Exceptions

  1. Do Not Overuse Custom Exceptions: Custom exceptions add complexity. Only use them when a specific failure condition requires a clear and unique handling or error message.
  2. Provide Meaningful Messages: Always include meaningful, informative messages to help quickly identify the cause of the error.
  3. Consider Checked vs. Unchecked: In most cases, unchecked exceptions (subclassed from RuntimeException) are more appropriate for test automation, allowing exceptions to propagate without requiring try-catch blocks.

Example Summary

Here’s a complete example of using custom exceptions for a test failure scenario:

public class ElementNotFoundException extends RuntimeException {
public ElementNotFoundException(String message) {
super(message);
}

public ElementNotFoundException(String message, Throwable cause) {
super(message, cause);
}
}
// Usage in a Selenium page object
public class LoginPage {
private WebDriver driver;
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public WebElement findPasswordField() {
try {
return driver.findElement(By.id("password"));
} catch (NoSuchElementException e) {
throw new ElementNotFoundException("Password field was not found on the Login page.", e);
}
}
}
// In a test
public void testLoginFailure() {
LoginPage loginPage = new LoginPage(driver);
try {
WebElement passwordField = loginPage.findPasswordField();
passwordField.sendKeys("wrongPassword");
// Additional test steps...
} catch (ElementNotFoundException e) {
System.out.println("Custom Exception Caught: " + e.getMessage());
}
}

This setup makes the test code more robust, descriptive, and easier to maintain, allowing custom handling and reporting based on test-specific failure conditions.

Previous: Interview #24: Common Java String manipulation programs

Interview #35: Write a Selenium script that checks for broken links on a webpage.

To check for broken links on a webpage using Selenium, you can follow a systematic approach: Retrieve all anchor (<a>) tags with href ...

Most Popular