Tracking Down Timing Errors with Synchronization Points

In Chapter 5, Waiting for Elements, you learned about the different types of waits that can be used in Selenium. Another way to call the waits is by making use of synchronization points, because they enable our automation scripts to wait until the web application responds. The web application being tested is a simple web page that loads an element. This element always shows up randomly, between 0 and 10 seconds (this has been done intentionally, to simulate an application that is loading information from different backend services). After the element shows up, we click on it, and the second element loads. This goes on until the fourth element, when the last click changes the contents of the element identified by instruction. The test is asserting the presence of the mentioned elements.

Here, we will analyze an existing test that automates a given web application. This test's execution time is much longer than it should be. We will identify sections of the test that can be improved, and then we will adjust the test to shorten the overall execution time. The steps for completion are as follows:

  1. Open https://trainingbypackt.github.io/Beginning-Selenium/lesson_8/activity_8-B-1.html.
  2. After reviewing the web application found at https://trainingbypackt.github.io/Beginning-Selenium/lesson_8/activity_8-B-1.html, copy the Java file found at https://github.com/TrainingByPackt/Beginning-Selenium/blob/master/docs/lesson_8/lesson8/src/test/java/com/beginningselenium/examples/tests/Activity8_B1_FirstState.java to your IDE.
  1. Analyze and identify what can be improved in the following script:
package com.beginningselenium.examples.tests;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class Activity8_B1_FirstState {

private WebDriver driver;

@BeforeMethod
public void setUpWebDriver() {
driver = new ChromeDriver();
}

@AfterMethod(alwaysRun = true)
public void teardownWebDriver() {
if (driver != null) {
driver.close();
}
}
//[…]
  1. Run the test.
    After running the test, you will notice that it always takes 53 seconds, no matter whether the elements are shown before or not. We are aware that the elements will be shown at a random time, usually between 0 and 10 seconds, which is reflected by the use of Thread.sleep() in the test. Remember that Thread.sleep() is not helpful, because it always waits for a fixed time, and that leads to slower and longer tests (which, in many cases, should be waiting for shorter time periods).
  2. The first thing that we can do to improve this test is replace Thread.sleep() with waits. Since we want to do this iteratively, without changing too many things at once, we can replace it with an implicit wait of ten seconds.
  1. After replacing all of the Thread.sleep() calls with an implicit wait, our test should look as follows:
//[…]
public class Activity8_B1_SecondState {

private WebDriver driver;

@BeforeMethod
public void setUpWebDriver() {
driver = new ChromeDriver();
}

@AfterMethod(alwaysRun = true)
public void teardownWebDriver() {
if (driver != null) {
driver.close();
}
}

@Test
public void TimingTest() {
driver.manage().timeouts().implicitlyWait(12, TimeUnit.
SECONDS);
driver.get("https://trainingbypackt.github.io/Beginning-
Selenium/lesson_8/activity_8-B-1.html");
//[…]

It looks much better without those ugly Thread.sleep calls. Now, we should run the test, to see how much faster it is.
To our surprise, the test does not work at all. We are getting the following exceptions:

"org.openqa.selenium.ElementNotVisibleException: element
not visible"

Since our web application is simulating slowness by making elements visible and invisible, implicit waits won't work, because an implicit wait will just check whether the element is present in the DOM. We will have to keep improving the test by switching to explicit waits.

  1. After switching from implicit waits to explicit waits (where we wait for the element to be present), our test should look as follows (run the test a few times, as well):
//[…]
public class Activity8_B1_ThirdState {

private WebDriver driver;

@BeforeMethod
public void setUpWebDriver() {
driver = new ChromeDriver();
}

@AfterMethod(alwaysRun = true)
public void teardownWebDriver() {
if (driver != null) {
driver.close();
}
}

@Test
public void TimingTest() {
driver.get("https://trainingbypackt.github.io/Beginning-
Selenium/lesson_8/activity_8-B-1.html");

WebDriverWait wait = new WebDriverWait(driver, 12);

System.out.println("Waiting for the first button");
wait.until(ExpectedConditions.
visibilityOfElementLocated(By.id("firstButton")));
WebElement firstButton = driver.findElement(By.
id("firstButton"));
System.out.println("Clicking on the first button");
firstButton.click();
//[…]

You can see that the test's execution time is shorter, after having run it a few times. Most of the time, the elements will be visible in a shorter time lapse than the established maximum wait, and by this, we are already bringing down the whole execution time.

One downside of this change is that we now have a test with more lines of code, and some parts of it (like the element locators) are duplicated. This can make the test a bit harder to understand, and we should improve upon it.

  1. Reduce the lines of code by using the value that the waits return. The value of the following code can be cast to a WebElement, and that simplifies the complexity and the amount of code in the test:
wait.until(ExpectedConditions.visibilityOfElementLocated(By.
id("firstButton")))

With this method, we can avoid writing locators more than once, and we can also avoid applying extra assertions (since the ExpectedConditions class is already verifying things for us). After changing the code, our test should look as follows:

@Test
public void TimingTest() {
driver.get("https://trainingbypackt.github.io/Beginning-
Selenium/lesson_8/activity_8-B-1.html");

WebDriverWait wait = new WebDriverWait(driver, 12);

System.out.println("Waiting for the first button");
WebElement firstButton = wait.until(ExpectedConditions.
visibilityOfElementLocated(By.id("firstButton")));
System.out.println("Clicking on the first button");
firstButton.click();

System.out.println("Waiting for the second button");
WebElement secondButton = wait.until(ExpectedConditions.
visibilityOfElementLocated(By.id("secondButton")));
System.out.println("Clicking on the second button");
secondButton.click();

System.out.println("Waiting for the third button");
WebElement thirdButton = wait.until(ExpectedConditions.
visibilityOfElementLocated(By.id("thirdButton")));
System.out.println("Clicking on the third button");
thirdButton.click();

System.out.println("Waiting for the fourth button");
WebElement fourthButton = wait.until(ExpectedConditions.
visibilityOfElementLocated(By.id("fourthButton")));
System.out.println("Clicking on the fourth button");
fourthButton.click();

System.out.println("Waiting for the final status");
wait.until(ExpectedConditions.textToBe(By.
id("instruction"), "Activity completed!"));
}
  1. Run the test a few more times to verify its stability and that it has a shorter execution time, as compared to its first version.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.136.22.50