The following test script is so well organized.
It starts with declaring all variables that are being used in the test script’s code.
Then, it has all element locators.
Finally, the test code follows:
@Test
public void searchTest() throws InterruptedException {
//variables
String homePageUrl = "https://www.vpl.ca/";
String resultsPageUrl = "https://vpl.bibliocommons.com";
String keyword = "java";
String currentUrl = "";
String resultsFound = "";
int i = 0;
int j = 0;
int resultsCount = 0;
int broadenResultsCount = 0;
//locators
By searchBoxId = By.id("edit-search");
By searchButtonId = By.id("edit-submit");
By resultsFoundXpath =
By.xpath("(//span[@data-key = 'pagination-text'])[1]");
By broadenSearchXpath = By.xpath("//a[@class = 'broaden-search-link']");
//test
driver.get(homePageUrl);
Assert.assertEquals(driver.getCurrentUrl(), homePageUrl);
WebElement searchBox = driver.findElement(searchBoxId);
searchBox.sendKeys(keyword);
WebElement searchButton = driver.findElement(searchButtonId);
searchButton.click();
currentUrl = driver.getCurrentUrl();
Assert.assertTrue(currentUrl.startsWith(resultsPageUrl));
Assert.assertTrue(currentUrl.contains("query=" + keyword));
Assert.assertTrue(currentUrl.contains("searchType=smart"));
WebElement resultsFoundLabel = driver.findElement(resultsFoundXpath);
resultsFound = resultsFoundLabel.getText();
Assert.assertTrue(resultsFound.contains("1 to 10"));
i = resultsFound.indexOf("of") + 3;
j = resultsFound.indexOf(" results");
resultsCount = Integer.parseInt(resultsFound.substring(i, j));
Assert.assertTrue(resultsCount > 0);
WebElement broadenSearchLink = driver.findElement(broadenSearchXpath);
broadenSearchLink.click();
currentUrl = driver.getCurrentUrl();
Assert.assertTrue(currentUrl.contains("searchType=bkw"));
Thread.sleep(5000);
resultsFoundLabel = driver.findElement(resultsFoundXpath);
resultsFound = resultsFoundLabel.getText();
i = resultsFound.indexOf("of") + 3;
j = resultsFound.indexOf(" results");
broadenResultsCount = Integer.parseInt(resultsFound.substring(i, j));
Assert.assertTrue(broadenResultsCount > 0);
Assert.assertTrue(broadenResultsCount > resultsCount); }
Nice structure, isn’t it?
Everything is neatly organized. Everything is easy to find.
Unfortunately, I suggest that you do not do this at all.
It is a bad practice to list all variables used by a test script at the beginning of the test script.
Let’s start with these variables and see where should they be declared:
//variables
String homePageUrl = "https://www.vpl.ca/";
String resultsPageUrl = "https://vpl.bibliocommons.com";
String keyword = "java";
String currentUrl = "";
String resultsFound = "";
int i = 0;
int j = 0;
int resultsCount = 0;
int broadenResultsCount = 0;
homePageUrl, resultsPageUrl and keyword variables are not going to have different values during the test execution. Their values will not change since the home page url is fixed, the results page url and the search keyword are fixed as well.
Because of this, also due to the fact that probably other test scripts need them as well, we should declare them as constants at the class level:
private static final String HOME_PAGE_URL = "https://www.vpl.ca/";
private static final String RESULTS_PAGE_URL = "https://vpl.bibliocommons.com"; private static final String KEYWORD = "java";
What about the other variables?
Instead of being declared at the beginning of the test script and then used further below, they should be declared as close as possible to where they are needed.
Why is this important?
First,
the code is easier to understand if the variable is declared when it is being used or just before it is used. You can see right away how the variable is declared and used, without any scrolling up and down through the code.
Second,
the scope of the variable is smaller since the variable is declared, instantiated and used in the same block of code. Compare this with declaring the variable at the beginning of the script, instantiating it 10 lines below and using after 20 more lines.
Third,
if the variable is declared on the same line of code where it is being used, a lot of lines of code are no longer needed so the test script becomes shorter.
So, instead of declaring i, j and resultCount at the top of the script, just declare them on the same line where they are used:
int i = resultsFound.indexOf("of") + 3;
int j = resultsFound.indexOf(" results");
int resultsCount = Integer.parseInt(resultsFound.substring(i, j));
We dealt with the variables.
What should we do with the locators?
//locators
By searchBoxId = By.id("edit-search");
By searchButtonId = By.id("edit-submit");
By resultsFoundXpath =
By.xpath("(//span[@data-key = 'pagination-text'])[1]");
By broadenSearchXpath = By.xpath("//a[@class = 'broaden-search-link']");
They are not going to change, either, during the execution of the test script. And probably other test scripts will need these locators as well. So, let’s change them to constants and move them at the class level:
private static final By SEARCH_BOX_ID = By.id("edit-search");
private static final By SEARCH_BUTTON_ID = By.id("edit-submit");
private static final By RESULTS_FOUND_XPATH =
By.xpath("(//span[@data-key = 'pagination-text'])[1]");
private static final By BROADEN_SEARCH_XPATH =
By.xpath("//a[@class = 'broaden-search-link']");
So, with all these changes, the code becomes:
public class WebTest {
private WebDriver driver;
private static final String HOME_PAGE_URL = "https://www.vpl.ca/";
private static final String RESULTS_PAGE_URL =
"https://vpl.bibliocommons.com";
private static final String KEYWORD = "java";
private static final By SEARCH_BOX_ID = By.id("edit-search");
private static final By SEARCH_BUTTON_ID = By.id("edit-submit");
private static final By RESULTS_FOUND_XPATH =
By.xpath("(//span[@data-key = 'pagination-text'])[1]");
private static final By BROADEN_SEARCH_XPATH =
By.xpath("//a[@class = 'broaden-search-link']");
@BeforeMethod
public void setUp() {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().window().maximize();
}
@AfterMethod
public void tearDown() {
driver.quit();
}
@Test
public void searchTestRefactored() throws InterruptedException {
driver.get(HOME_PAGE_URL);
Assert.assertEquals(driver.getCurrentUrl(), HOME_PAGE_URL);
WebElement searchBox = driver.findElement(SEARCH_BOX_ID);
searchBox.sendKeys(KEYWORD);
WebElement searchButton = driver.findElement(SEARCH_BUTTON_ID);
searchButton.click();
String currentUrl = driver.getCurrentUrl();
Assert.assertTrue(currentUrl.startsWith(RESULTS_PAGE_URL));
Assert.assertTrue(currentUrl.contains("query=" + KEYWORD));
Assert.assertTrue(currentUrl.contains("searchType=smart"));
WebElement resultsFoundLabel = driver.findElement(RESULTS_FOUND_XPATH);
String resultsFound = resultsFoundLabel.getText();
Assert.assertTrue(resultsFound.contains("1 to 10"));
int i = resultsFound.indexOf("of") + 3;
int j = resultsFound.indexOf(" results");
int resultsCount = Integer.parseInt(resultsFound.substring(i, j));
Assert.assertTrue(resultsCount > 0);
WebElement broadenSearchLink = driver.findElement(BROADEN_SEARCH_XPATH);
broadenSearchLink.click();
currentUrl = driver.getCurrentUrl();
Assert.assertTrue(currentUrl.contains("searchType=bkw"));
Thread.sleep(5000);
resultsFoundLabel = driver.findElement(RESULTS_FOUND_XPATH);
resultsFound = resultsFoundLabel.getText();
i = resultsFound.indexOf("of") + 3;
j = resultsFound.indexOf(" results");
int broadenResultsCount = Integer.parseInt(resultsFound.substring(i, j));
Assert.assertTrue(broadenResultsCount > 0);
Assert.assertTrue(broadenResultsCount > resultsCount);
}
}
In conclusion, declare constants at the class level, at the top of the class.
All other variables from the test scripts should be declared when they are used.