In the Previous Tutorial, we learned to interact with the elements in the page. In this tutorial, we’ll learn to handle the timeout issues in the script.
What are timeout or wait issues in the automation script?
Let us say you wrote a script to automate this scenario:
- Go to myshopping.com
- Search for iPhone
- Click on Add to Cart button
You ran the script and it worked as expected. A few days later your company announced huge deals and the website traffic increased exponentially. When your automation script was run again it got failed. You did the debugging, read the error message and found that the script failed to find Add to Cart button. However, while manually navigating the website you do not see any such problem.
What can be the issue?
Well, it may be possible that the search result for iPhone took some time to appear but the script was running like anything. So it failed to find that button.
This is what we call synchronization/timeout/wait issues in Test Automation.
Verify element exists
What if before performing the click action, I check if Add to Cart button exists on the page?
Yes, this is how we can handle this issue.
List<WebElement> elements = driver.findElements(By.id("firstname"));
if(elements.size() > 0){
driver.findElement(By.id("firstname")).sendKeys("TestFirstName");
}
#Get the list of elements with matching locator
elements = driver.find_elements_by_name("login")
if len(elements) > 0:
driver.find_elements_by_name("login").click()
The issue is still not solved. If the element is not loaded immediately the count will be 0 and it will still be not able to perform actions on that object.
Hardcoded wait – Instructing code to wait for a fixed time
What if I instruct the code to wait for a certain amount of time like 1 minute?
Very bad. You are talking about hardcore wait statement. It will wait for that time even if the page/object is already loaded. Or it will only wait till that time but the page/object is still not loaded. This is not a good approach to solve this issue. Yes, technically you can instruct Java thread to wait for the specified amount of milliseconds –
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Here we are saying the Java thread to wait for 5000 milliseconds (i.e. 5 seconds). We need to put the Thread.Sleep() statement inside try/catch block because this statement can throw an error (exception) that we need to handle(catch).
#Hardcoded wait for 60 seconds
import time
time.sleep(60)
Huh, Who will tell me the better way then?
You can go with Implicit Waits. You can instruct WebDriver to wait (poll the DOM) for a specified amount of time if the object (element) is not immediately available in the page (DOM).
Implicit Wait
The wait time for WebDriver is set to 0 seconds, by default. WebDriver waits for 0 seconds while finding for an element. It means if the element is not immediately available, WebDriver will throw an exception.
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
#If the element is not immediately available poll the DOM for 10 seconds
driver.implicitly_wait(10)
If we write the above line of code, the WebDriver will wait for 10 seconds if any element is not immediately available on the page. Once that time is passed and the element is still not available, WebDriver will throw an exception.
Where to declare Implicit Wait?
Technically you can define implicit wait at any part of your Selenium script. It is good to declare it right after instantiating WebDriver.
WebDriver driver = new ChromeDriver;
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
But when I type this line of code in eclipse I am getting a red line below TimeUnit. It seems I need to import some package.
You have become the smarter dude. Move mouse over that line and eclipse will suggest you what to do. You need to import java.util.concurrent package.
driver = webdriver.Chrome('C:\teachmeselenium\chromedriver.exe') driver.implicitly_wait(10)
Once declared the implicit wait is valid for the life of the WebDriver instance so you do not need to write it again.
Let us explore Explicit Waits in the Next Tutorial.