Do not use utility classes
Some test scripts rely on utility classes for common purpose methods.
For example,
@Test
public void canNavigateToOtherPagesTest() {
HomePage homePage = new HomePage(driver);
homePage.open();
Verify.verify(Utilities.getUrl(driver).contains("www.vpl.ca"),
"home page url is not correct!");
ResultsPage resultsPage = homePage.searchBy(KEYWORD);
Verify.verify(Utilities.getUrl(driver).contains("bibliocommons.com"),
"results page url is not correct!");
Verify.verify(resultsPage.getResultsFound().contains("1 to 10"),
"results found label does not include 1 to 10!");
Utilities.reloadPage(driver);
Utilities.scrollToBottom(driver);
Utilities.sleep(2);
resultsPage.goToPage(2);
Assert.assertTrue(Utilities.getUrl(driver).contains("page=2"));
Utilities.reloadPage(driver);
Utilities.scrollToBottom(driver);
Utilities.sleep(2);
resultsPage.goToPage(3);
Assert.assertTrue(Utilities.getUrl(driver).contains("page=3"));
}
The test scripts uses 2 page classes, HomePage and ResultsPage which implement multiple user actions:
open()
search()
goToPage()
getResultsFound()
For any common actions (get url, reload page, scroll to bottom , sleep), the test script uses this utility class:
public class Utilities {
public static void scrollToBottom(WebDriver driver) {
((JavascriptExecutor)driver).executeScript(
"window.scrollTo(0, document.body.scrollHeight)");
}
public static void reloadPage(WebDriver driver) {
driver.navigate().refresh();
}
public static void sleep(int seconds) {
try {
Thread.sleep(2000);
}
catch (Exception e) {
//nothing
}
}
public static String getUrl(WebDriver driver) {
return driver.getCurrentUrl();
}
}
Is this a good approach?
No, it is not.
There are multiple reasons why utility classes are a bad practice:
the test scripts will work at 2 levels, using both page methods and utility methods
utility classes discourage writing object-oriented code since most of their methods are static
utility classes usually work as huge containers of methods that have nothing in common
utility classes tend to grow a lot in time
initially, a utility class may be focused and have methods that are somehow connected; in time, you will add more and more methods that have nothing in common; your utility class will become “a house storage”
utility classes are usually a good idea only when used in a library such as Selenium, TestNg and jUnit
all utility methods that interact with the site need a driver parameter
utility classes usually say that you do not understand how to use classes and objects
So, what should we do?
Let’s see how we can get rid of the Utilities methods:
getUrl() can be moved to the HomePage and ResultsPage classes
sleep() is useless if we add synchronization to all page methods (synchronization means waiting for an element before using it)
reloadPage() is useless as there is no good reason for reloading a page while running the test script
scrollToBottom() should be moved to the ResultsPage class
After making all these changes, the test script becomes:
@Test
public void canNavigateToOtherPagesTest() {
HomePage homePage = new HomePage(driver);
homePage.open();
Verify.verify(homePage.getUrl().contains("www.vpl.ca"),
"home page url is not correct!");
ResultsPage resultsPage = homePage.searchBy(KEYWORD);
Verify.verify(resultsPage.getUrl().contains("bibliocommons.com"),
"results page url is not correct!");
Verify.verify(resultsPage.getResultsFound().contains("1 to 10"),
"results found label does not include 1 to 10!");
resultsPage.scrollToBottom();
resultsPage.goToPage(2);
Assert.assertTrue(resultsPage.getUrl().contains("page=2"));
resultsPage.scrollToBottom();
resultsPage.goToPage(3);
Assert.assertTrue(resultsPage.getUrl().contains("page=3"));
}
In conclusion, do not use utility classes.
Add all your code in page classes and use only page methods in the test scripts.
The page classes can be optimized later by building your own framework.