Use soft assertions only for verifying multiple, related fields that are included in the same page
This simple Selenium test automates a user registration scenario:
@Test
public void userCanRegisterTest() {
driver.get(URL);
Assert.assertTrue(driver.getCurrentUrl().contains(URL));
driver.findElement(registerLinkXpath).click();
Assert.assertTrue(driver.getCurrentUrl()
.contains(REGISTER_PAGE_URL));
driver.findElement(firstNameId).sendKeys(FIRST_NAME);
driver.findElement(lastNameId).sendKeys(LAST_NAME);
driver.findElement(addressId).sendKeys(ADDRESS);
driver.findElement(cityId).sendKeys(CITY);
driver.findElement(stateId).sendKeys(STATE);
driver.findElement(zipCodeId).sendKeys(ZIP_CODE);
driver.findElement(phoneId).sendKeys(PHONE);
driver.findElement(ssnId).sendKeys(SSN);
driver.findElement(usernameId).sendKeys(USERNAME);
driver.findElement(passwordId).sendKeys(PASSWORD);
driver.findElement(repeatedPasswordId).sendKeys(PASSWORD);
driver.findElement(registerButtonXpath).click();
WebElement registrationMessageLabel = driver.findElement(
successfulRegistrationXpath);
Assert.assertTrue(registrationMessageLabel.isDisplayed());
}
The test loads the home page and checks that the home page is displayed. In the home page, it clicks the register link to navigate to the user registration page. Here, it fills all fields and clicks the register button. Finally, it checks that the successful registration message is displayed.
A similar test would try to register without filling any data:
@Test
public void userCannotRegisterWithFieldsNotFilledTest() {
driver.get(URL);
Assert.assertTrue(driver.getCurrentUrl().contains(URL));
driver.findElement(registerLinkXpath).click();
Assert.assertTrue(driver.getCurrentUrl()
.contains(REGISTER_PAGE_URL));
driver.findElement(registerButtonXpath).click();
WebElement firstNameError = driver.findElement(firstNameErrorId);
Assert.assertEquals(firstNameError.getText(),
"First name is required.");
WebElement lastNameError = driver.findElement(lastNameErrorId);
Assert.assertEquals(lastNameError.getText(),
"Last name is required.");
WebElement addressError = driver.findElement(addressErrorId);
Assert.assertEquals(addressError.getText(),
"Address is required.");
WebElement cityError = driver.findElement(cityErrorId);
Assert.assertEquals(cityError.getText(), "City is required.");
WebElement stateError = driver.findElement(stateErrorId);
Assert.assertEquals(stateError.getText(), "State is required.");
WebElement zipError = driver.findElement(zipCodeErrorId);
Assert.assertEquals(zipError.getText(), "Zip Code is required.");
WebElement ssnError = driver.findElement(ssnErrorId);
Assert.assertEquals(ssnError.getText(),
"Social Security Number is required.");
WebElement usernameError = driver.findElement(usernameErrorId);
Assert.assertEquals(usernameError.getText(),
"Username is required.");
WebElement passwordError = driver.findElement(passwordErrorId);
Assert.assertEquals(passwordError.getText(),
"Password is required.");
WebElement repeatedPasswordError =
driver.findElement(repeatedPasswordErrorId);
Assert.assertEquals(repeatedPasswordError.getText(),
"Password confirmation is required.");
}
This test verifies that an error message is displayed for each field when trying to register without first filling all user information.
Now, error messages change.
Let’s assume that the error messages of the page change from
"First name is required."
"Last name is required."
"Address is required."
"City is required."
"State is required."
"Zip Code is required."
"Social Security Number is required."
"Username is required."
"Password is required."
"Password confirmation is required."
to
"First name - required."
"Last name - required."
"Address - required."
"City - required."
"State - required."
"Zip Code - required."
"Social Security Number - required."
"Username - required."
"Password - required."
"Password confirmation - required."
With the site’s error messages being different, the test will fail on the 1st assertion, the one about the first name field.
Until this assertion passes, we will not know anything about the other assertions for the remaining fields from the user registration page.
But, since
all these assertions are independent
they are about fields of the same page
they are about related fields
we can use soft assertions so, if the test fails, we get not only the status of the first assertion, but the status of all assertions:
@Test
public void userCannotRegisterWithFieldsNotFilledTest() {
driver.get(URL);
Assert.assertTrue(driver.getCurrentUrl().contains(URL));
driver.findElement(registerLinkXpath).click();
Assert.assertTrue(driver.getCurrentUrl()
.contains(REGISTER_PAGE_URL));
SoftAssert softAssert = new SoftAssert();
driver.findElement(registerButtonXpath).click();
WebElement firstNameError = driver.findElement(firstNameErrorId);
softAssert.assertEquals(firstNameError.getText(),
"First name is required");
WebElement lastNameError = driver.findElement(lastNameErrorId);
softAssert.assertEquals(lastNameError.getText(),
"Last name is required");
WebElement addressError = driver.findElement(addressErrorId);
softAssert.assertEquals(addressError.getText(),
"Address is required");
WebElement cityError = driver.findElement(cityErrorId);
softAssert.assertEquals(cityError.getText(), "City is required");
WebElement stateError = driver.findElement(stateErrorId);
softAssert.assertEquals(stateError.getText(), "State is required");
WebElement zipError = driver.findElement(zipCodeErrorId);
softAssert.assertEquals(zipError.getText(), "Zip Code is required");
WebElement ssnError = driver.findElement(ssnErrorId);
softAssert.assertEquals(ssnError.getText(),
"Social Security Number is required");
WebElement usernameError = driver.findElement(usernameErrorId);
softAssert.assertEquals(usernameError.getText(),
"Username is required");
WebElement passwordError = driver.findElement(passwordErrorId);
softAssert.assertEquals(passwordError.getText(),
"Password is required");
WebElement repeatedPasswordError =
driver.findElement(repeatedPasswordErrorId);
softAssert.assertEquals(repeatedPasswordError.getText(),
"Password confirmation is required");
softAssert.assertAll();
}
Please notice how the soft assertion does not include the first 2 assertions of the test as it focuses only on assertions related to user info fields.
For this test, the soft assertion is evaluated at the end and, since at least one of the embedded assertions fails, the soft assertion fails as well.
However, you can see in the console the status of evaluating all embedded assertions:
FAILED: tests.UserRegistrationTests.userCannotRegisterWithFieldsNotFilled2Test
java.lang.AssertionError: The following asserts failed:
expected [First name is required] but found [First name - required.],
expected [Last name is required] but found [Last name - required.],
expected [Address is required] but found [Address - required.],
expected [City is required] but found [City - required.],
expected [State is required] but found [State - required.],
expected [Zip Code is required] but found [Zip Code - required.],
expected [Social Security Number is required] but found [Social
Security Number - required.],
expected [Username is required] but found [Username - required.],
expected [Password is required] but found [Password - required.],
expected [Password confirmation is required] but found [Password confirmation - required.]
Soft assertions are very useful but they should not be used in all situations.
They work well only in cases when multiple, related fields that are part of the same page need to be verified in the same test.