A typical test script has more than 1 assertion, actually quite a few spread out from the beginning of the test script to its end:
@Test
public void broadeningSearchDisplaysMoreResults() {
driver.get(HOME_PAGE_URL);
String homePageUrl = driver.getCurrentUrl();
Assert.assertEquals(homePageUrl, HOME_PAGE_URL);
WebElement searchBox = driver.findElement(SEARCH_BOX_ID);
searchBox.sendKeys(KEYWORD);
WebElement searchButton = driver.findElement(SEARCH_BUTTON_ID);
searchButton.click();
String resultsPageUrl = driver.getCurrentUrl();
boolean isUrlcorrect = resultsPageUrl.startsWith(RESULTS_PAGE_URL);
Assert.assertTrue(isUrlCorrect,
"results page url does not start with " + RESULTS_PAGE_URL);
boolean isKeywordIncluded = resultsPageUrl.contains("query=" + KEYWORD);
Assert.assertTrue(isKeywordIncluded,
"results page url does not contain query=" + KEYWORD);
boolean isSearchTypeInUrl = resultsPageUrl.contains("searchType=smart");
Assert.assertTrue(isSearchTypeInUrl,
"results page url does not contain searchType=smart");
WebElement resultsFoundLabel = driver.findElement(RESULTS_FOUND_XPATH);
String resultsFoundText = resultsFoundLabel.getText();
boolean isPageCountIncluded = resultsFoundText.contains("1 to 10");
Assert.assertTrue(isPageCountIncluded,
"results count does not include 1 to 10");
int i1 = resultsFoundText.indexOf("of") + 3;
int i2 = resultsFoundText.indexOf(" results");
int totalCount = Integer.parseInt(resultsFoundText.substring(i1, i2));
Assert.assertTrue(totalCount > 0, "totalCount is not > 0");
WebElement searchBroaden = driver.findElement(BROADEN_SEARCH_XPATH);
searchBroaden.click();
resultsPageUrl = driver.getCurrentUrl();
Assert.assertTrue(resultsPageUrl.contains("searchType=bkw"),
"results page url doesnt include searchType=bkw");
resultsFoundLabel = driver.findElement(RESULTS_FOUND_XPATH);
resultsFoundText = resultsFoundLabel.getText();
int j1 = resultsFoundText.indexOf("of") + 3;
int j2 = resultsFoundText.indexOf(" results");
int newTotalCount = Integer.parseInt(resultsFoundText.substring(j1, j2));
Assert.assertTrue(newTotalCount > 0, "new total count is not > 0");
Assert.assertTrue(newTotalCount > totalCount,
newTotalCount + " is not > than " + totalCount);
}
The test script does a lot of validations, does it not?
At least, this is what we can get from how many assertions it has:
Assert.assertEquals(homePageUrl, HOME_PAGE_URL);
Assert.assertTrue(isUrlCorrect,
"results page url does not start with " + RESULTS_PAGE_URL);
Assert.assertTrue(isKeywordIncluded,
"results page url does not contain query=" + KEYWORD);
Assert.assertTrue(isSearchTypeInUrl,
"results page url does not contain searchType=smart");
Assert.assertTrue(isPageCountIncluded,
"results count does not include 1 to 10");
Assert.assertTrue(totalCount > 0, "totalCount is not > 0");
Assert.assertTrue(resultsPageUrl.contains("searchType=bkw"),
"results page url doesnt include searchType=bkw");
Assert.assertTrue(newTotalCount > 0, "new total count is not > 0");
Assert.assertTrue(newTotalCount > totalCount,
newTotalCount + " is not > than " + totalCount);
}
9 assertions, in total.
But, if we look at the name of the test script, broadeningSearchDisplaysMoreResults(), we get the feeling that something is not right.
Only the last 2 assertions of the test script are about checking the more results are displayed after broadening the search. The other 7 are not actually related to the purpose of the test script.
So, what can we do?
Having so many assertions makes it difficult to understand which ones are about the purpose of the test script and which ones are not.
The last 2 assertions are validating the test script. The other 7 are just making sure that the navigation of the test script goes without errors.
We cannot remove the first 7 assertions since, without them, the test script maintenance becomes hard. If we do not have an assertion about results page being displayed, if the results found element (from the results page) cannot be found, we will believe that there is something wrong with the results found element. This may not be correct if the results page is just very slow loading.
So, we have to keep the first 7 assertions.
A possible solution is to change them to something that works like an assertion but is not an assertion. Like a verification:
@Test
public void broadeningSearchDisplaysMoreResults() {
driver.get(HOME_PAGE_URL);
String homePageUrl = driver.getCurrentUrl();
Verify.verify(homePageUrl.equalsIgnoreCase(HOME_PAGE_URL));
WebElement searchBox = driver.findElement(SEARCH_BOX_ID);
searchBox.sendKeys(KEYWORD);
WebElement searchButton = driver.findElement(SEARCH_BUTTON_ID);
searchButton.click();
String resultsPageUrl = driver.getCurrentUrl();
Verify.verify(resultsPageUrl.startsWith(RESULTS_PAGE_URL),
"results page url does not start with " + RESULTS_PAGE_URL);
Verify.verify(resultsPageUrl.contains("query=" + KEYWORD),
"results page url does not contain query=" + KEYWORD);
Verify.verify(resultsPageUrl.contains("searchType=smart"),
"results page url does not contain searchType=smart");
WebElement resultsFoundLabel = driver.findElement(RESULTS_FOUND_XPATH);
String resultsFoundText = resultsFoundLabel.getText();
Verify.verify(resultsFoundText.contains("1 to 10"),
"results count does not include 1 to 10");
int i1 = resultsFoundText.indexOf("of") + 3;
int i2 = resultsFoundText.indexOf(" results");
int totalCount = Integer.parseInt(resultsFoundText.substring(i1, i2));
Verify.verify(totalCount > 0, "totalCount is not > 0");
WebElement searchBroaden = driver.findElement(BROADEN_SEARCH_XPATH);
searchBroaden.click();
Thread.sleep(5000);
Verify.verify(driver.getCurrentUrl().contains("searchType=bkw"),
"results page url doesnt include searchType=bkw");
resultsFoundLabel = driver.findElement(RESULTS_FOUND_XPATH);
resultsFoundText = resultsFoundLabel.getText();
int j1 = resultsFoundText.indexOf("of") + 3;
int j2 = resultsFoundText.indexOf(" results");
int newTotalCount = Integer.parseInt(resultsFoundText.substring(j1, j2));
Assert.assertTrue(newTotalCount > 0,
"new total count is not > 0");
Assert.assertTrue(newTotalCount > totalCount,
newTotalCount + " is not > than " + totalCount);
}
We replaced the first 7 assertions with verifications.
A typical verification looks like this:
Verify.verify(condition, errorMessage);
It gets 2 parameters, a condition to validate and an error message to be displayed if the condition is not true.
Isn’t this very similar with Assert.assertTrue(condition, errorMessage)?
The verification is used from the com.google.common.base.Verify class that is included with the Selenium Java bindings.
You can read about it here: Verify class
This class works similarly with the Assert one:
Static convenience methods that serve the same purpose as Java language assertions, except that they are always enabled. These methods should be used instead of Java assertions whenever there is a chance the check may fail "in real life".
But are there really no differences?
Let’s see what is displayed in the console when we change
Assert.assertTrue(isKeywordIncluded,
"results page url does not contain query=" + KEYWORD);
to
Verify.verify(resultsPageUrl.contains("query=" + KEYWORD),
"results page url does not contain query=" + KEYWORD);
The console info in case the assertion fails is
java.lang.AssertionError: results page url does not contain query=java
expected [true] but found [false]
at org.testng.Assert.fail(Assert.java:110)
at org.testng.Assert.failNotEquals(Assert.java:1577)
at org.testng.Assert.assertTrue(Assert.java:56)
at webtests.WebTest.searchTestWithLessAssertions(WebTest.java:129)
The console info when using the verification is
com.google.common.base.VerifyException: results page url does not contain query=java
at com.google.common.base.Verify.verify(Verify.java:126)
at webtests.WebTest.searchTestWithLessAssertions(WebTest.java:129)
This is almost identical.
So, we get the same results when replacing the navigation assertions with verifications.
The real benefit is that now we can clearly see the navigation verifications from the test assertions.
The test assertions are at the end of the test script while the navigation verifications are throughout the test script.
We have now just a few assertions that are all related to the purpose of the test script.