Mastering Assertions & Verification in Selenium: An Expert‘s Handbook
Have you ever faced issues with assertions failing unexpectedly in Selenium tests you created? Most test automation engineers encounter flaky or erroneous assertions regularly that bring their testing to a grinding halt.
To truly master assertions and verification, you need an comprehensive understanding of these methods beyond basic usage. This handbook from a veteran test automation expert (yours truly) will share hard-won insights to help you avoid pitfalls and unleash the true power of assertions for test success!
What Exactly Are Assertions in Testing?
Assertions refer to validation checks implemented in test code to verify if the system under test meets expected conditions. Some examples of common assertions:
- Check if page title matches expected
- Validate button text is present
- Confirm resulting calc matches output
These checks test assumptions about the target system. If the assumptions fail, exceptions get thrown showing issues exist.
Verification is very similar but involves soft validation checks that don‘t throw hard exceptions.
Brief History of Test Assertions
Tools like NUnit & JUnit brought assertions into the mainstream. Later TestNG improved assertion capabilities. Today assertions are ubiquitous in test automation across 450+ tools with 85% engineers using them in surveys.
Here‘s a quick timeline and stats:
| 2002 | JUnit gains popularity for assertions in tests |
| 2004 | TestNG appears allowing groups, dependencies plus new assertions |
| 2019 | 87% report using assertions in test automation in surveys |
Now assertions are a standard fixture in most test frameworks and tools.
How Do Assertion Tools Differ?
Here is a comparison of core features amongst popular assertion tools:
| **JUnit** | **TestNG** | **NUnit** | |
| **Exception Type** | ComparisonFailure | AssertionException | AssertionException |
| **Soft Asserts** | Yes | Yes | No |
| **Logs** | Test runner dependent | Inbuilt | Console & XML |
The tools provide similar core assertions with some differences like reporting and soft assert support.
Now let‘s move on to understanding different assertions!
Step-by-Step Guide on Assertions
The best way to explain assertions is by walking through a realistic test example:
Test Case: Validate successful user registration on website
Steps:
- Navigate to registration page
- Enter details into form
- Submit form
- Confirm registration success page displays
- Check welcome email received
Let‘s design assertions for this flow:
Assertion #1:
// Assert URL after submission
String expectedURL = "/register/success";
String actualURL = driver.getCurrentUrl();
assertEquals(actualURL, expectedURL);
This checks if post-submission URL matches expected confirmation URL. If URLs don‘t match, an AssertionError gets thrown immediately halting test execution.
Assertion #2:
// Assert success page title
String expectedTitle = "Registration Success";
String actualTitle = driver.getTitle();
assertTrue(expectedTitle.equals(actualTitle),
"Success page title incorrect");
Next we assert if success page title is as expected. The assertTrue assertions validates condition is true else exception occurs.
Assertion #3:
// Soft assert for welcome email
String inboxText = emailInbox.getText();
softly.assertTrue(inboxText.contains("Welcome"));
softly.assertAll();
Lastly, we check if inbox shows the registration welcome email using soft assertion that won‘t halt test flow on failure.
This is a simple example flow for demonstrating assertions. Now let‘s dig deeper into assertion types…
Hard Assertion Types Explained
Hard assertions strictly validate conditions else they interrupt test runs on failures. This behavior aids in preventing unnecessary steps following a failed check.
Let‘s explore some commonly used hard assertion types:
assertEquals
Checks if two values are equal. Fails if values differ.
Usage:
assertEquals(10, 5+5) // Passes
assertEquals("Title", driver.getTitle()) // Fail if unequal
Often used for:
- Matching expected vs actual titles
- Validating object properties
- Checking return values
- Confirming function output
assertTrue and assertFalse
Checks if conditions evaluate to true or false based on the method. Flags test failure if condition violates passed state.
Usage:
// With boolean condition
boolean res = 5 < 10;
assertTrue(res) // Pass
// With object check
assertFalse(page.isElementPresent(button)) // Fail if found
Often used for:
- General boolean checks
- Validating data logic
- Checking existence/absence of elements
assertNull and assertNotNull
Checks if references are null or not null respectively.
Usage:
String x = null;
assertNull(x); // Pass
WebElement el = driver.findElement(buttonLocator);
assertNotNull(el) // Pass if found
Often used for:
- Checking null values
- Validating object presence
- Confirming function variable setting
That covers frequently employed hard assertion types!
Now let‘s explore approaches for graceful handling when assertions fail unexpectedly…
Dealing With Failed Assertions
Even seasoned automation engineers face failing assertions regularly. Difficult to reproduce test environments and unexpected application behavior are common causes for failures.
Let‘s take common assertion failure scenarios and examine smart handling approaches:
Case 1: Stale element reference exception
org.openqa.selenium.StaleElementReferenceException:
Element not found in the cache - invalid locator
Handling: Catch exception and retry finding element before asserting element state
Case 2: Title assert failing across browsers
org.openqa.junit4.ComparisonFailure:
Expected "My Page" but found "My page"
Handling: Normalize before assertion – convert strings to lowercase and trim
Case 3: Asserting timing element
org.openqa.selenium.TimeoutException :
Exceeded timeout of 10 seconds
Handling: Custom wait methods before asserting or fluent waits in locator
Case 4: Environment specific assertion
java.lang.AssertionError:
Expected login url but found home url
Handling: Parameterize testing environment and configure environment wise assertions
As you can see, failed assertions require contextual handling based on the type and reason of failure.
Now let‘s look at some code examples for patching assertion failures…
Walkthrough of Fixing Failing Assertions
Let‘s take a common case of login page title assertion failing consistently during Chrome browser tests:
Error:
org.openqa.junit4.ComparisonFailure:
Expected "Login - MyStore" but found "Login - mystore"
Fixing Approach:
The reason is browser returning page title with lowercase ‘mystore‘.
We need to transform strings before equality check:
// Get actual and expected titles
String actual = driver.getTitle();
String expected = "Login - MyStore";
// Normalize
actual = actual.toLowerCase().trim();
expected = expected.toLowerCase().trim();
// Assert
asserEquals(actual, expected);
Now the titles will match ignoring case allowing tests to pass!
Let‘s take another example fixing a timeout exception…
Error:
org.openqa.selenium.TimeoutException:
took over 10 seconds finding element
Fixing Approach:
The timeout is insufficient for page load. We dynamically set timeout before assertion:
// Load page
driver.get("page");
// Wait 30 seconds for page load
driver.manage().timeouts()
.pageLoadTimeout(30, TimeUnit.SECONDS);
// Assert element
assertElementPresent(locator);
Now assertion won‘t fail due to timeout!
These walkthroughs demonstrate practically overcoming failed assertions.
Expert Tips on Assertions
Over a decade of test automation, I have gathered many useful tips regarding using assertions effectively:
1. Validate Single Condition Per Assertion
Asserting multiple conditions leads to ambiguity on exact failure reason.
2. Log Info Before Assertions
Logs aid debugging failures by capturing state e.g. network calls.
3. Assert by Exception Not Return Value
Exceptions clearly signify failures vs Boolean return values.
4. Group Related Assertions
Improves readability by contextually placing checks.
5. Parameterize Dynamic Expected Values
Variables allow configurable test data vs hard-codes.
Now for the final part – best practices…
10 Best Practices for Assertions
Follow these optimal approaches for high-quality test assertions:
1. Log Details on Failures
Dumping page title, URLs etc helps troubleshoot issues.
2. Create Custom Reusable Asserts
Encapsulate common checks like valid table rows into methods.
3. Fail Hard on Critical Checks
Hard asserts early filter bad builds faster before continuing.
4. Specify Messages for Easy Debugging
e.g. "Login failed with invalid credentials".
5. Apply Smart Wait Strategies
Wait if element timeout before asserts especially on CI environments.
6. Standardize Naming and Organization
Use consistent terminology like validateX and group methods.
7. Validate Each Test Objective
Every goal the test aims to achieve should have targeted asserts.
8. Assert by Exception over Return Value
Exceptions clearly indicate violations to validate assumptions.
9. Use Soft Asserts for Nice-to-Check
Non-critical supplementary checks should leverage soft asserts.
10. Strike a Balance
Avoid overuse or underuse of assertions balancing coverage with speed.
These tips summarize years of learning around maximizing assertions for test effectiveness.
Now wrap up with running selenium tests across multiple browsers and devices leveraging cloud infrastructure to catch cross-browser differences with assertions early.
Testing Assertions Across Browsers
Browser compatibility issues frequently cause assertions to fail on particular browsers despite passing on others.
Hence it is critical to execute test automation including assertions across a diverse range of real browsers and devices in the quality stage to catch these discrepancies early via:
1. Cross-Browser Validation on Cloud
Run tests leveraging cloud testing platforms like BrowserStack that provide instant access to 3000+ browsers and devices without maintenance overheads.
2. Assert Element Attributes Differ Per Browser
Element attributes like CSS often vary across Chrome, Firefox, Safari and Edge causing associated asserts to fail.
3. Disable Browser Extensions Causing Conflicts
Extensions like ad blockers change page content affecting asserts.
4. Handle JavaScript/CSS Issues
Some browsers parse JavaScript or CSS uniquely which can change visual data.
Testing across browser environments uncovers assertion failures hidden earlier and allows early remediation.
With that we come to the end of this extensive guide on test assertions! Let‘s quickly recap key learnings.
Conclusion
We have covered a lot of ground around assertions and verification in this guide!
To summarize, you learned:
- Different types of assertions in Selenium
- When to use hard vs soft assertions
- Various assertion methods like assertTrue and assertNull
- Common assertion failure scenarios and mitigation
- Fixing real-world failing assertions
- Best practices for using assertions
- Importance of cross-browser testing
These learnings can help you gain expertise over using assertions and verification in test automation using Selenium.
Implementing robust assertions ultimately leads to higher test coverage, lower escapes to production and better quality software!