Selenium Python – Synchronizing Test
In our earlier chapters, we have learned how do we automate scenarios, identify objects uniquely on a web page and perform actions on them. During the automation of scenarios, it is important that we synchronize our tests. So the time it takes for the web application to process, the automation command should match with the speed at which the command is sent by the script to the application.
Structure
- Synchronizing test
- Why synchronization
- Implicit wait
- Explicit wait
Objective
In this chapter, we will leam how we can establish synchronization in our tests so that we ensure our tests are not flaky. Reliable execution is crucial during testing cycles as they help save time, and ensure reliability in test automation exercises. We will learn how we implement that concept in our test scripts.
Synchronization
If we have not implemented synchronization in our tests, then our tests may hover between passing and failing, resulting in flaky tests. To avoid this we should synchronize our tests so that we have basic reliability in our test behavior. To achieve it we have to apply synchronization in our tests.
There are two kinds of synchronization techniques that we use in test scenarios of Selenium:
- Implicit wait
- Explicit wait
Implicit wait
The implicit wait is a global wait, which applies to every statement in the written test script. An implicit wait, when implemented in the script, tries to find the element on the web page. It will keep polling the web page until the element is found, or till the time is over. If the element is not found within the provided implicit wait, we get an exception NoSuchElementException.
In the following program, we will implement implicit wait:
from selenium import webdriver import unittest class Login(unittest.Testcase): def setup(self): self.driver = webdriver.chrome(executable_path="D:\Eclipse\BPB\seleniumpython\seleniumpyhon\drivers\chromedriver.exe") self.base_url = "http://practice.bpbonline.com/catalog/index.php" def test_login(self): driver=self.driver driver.get(self.base_url) driver.find_element_by_link_test("My Account").click( ) driver.find_element_by_name("email_address").clear( ) driver.find_element_by_name("email_address").send_keys("[email protected]) driver.find_element_by_name("password").clear( ) driver.find_element_by_name("password").send_keys("bpb@123") driver.find_element_by_id("tab1").click( ) driver.find_element_by_lik_text("log off").click( ) driver.find_element_by_lik_text("continue").click( ) def tearDown(self): self.driver.quit( ) If_name_==_main_": unittest.main( )
The commanding self .driven.implicity_wait(30) will apply the wait on every find element command used in the program. So for every statement, it will wait for 30 seconds for the object to appear with the given By locator. It will keep polling the website until it finds the object. If the object is found, the action will be performed on the object. Else after the 30 seconds are over, we will get an exception.
Explicit wait
The explicit wait is basically a local wait which can be implemented either as:
• Static wait: It is a forced wait, which is introduced by using time.sleep(n seconds) in the code line, whenever we wish to wait in the code for n number of seconds. It is not advisable to use static wait in the code because we generally do not know if the time allocated to wait is less or more. We cannot provide a lot of time to wait in the code, because that will delay our test automation script, and if we provide very little time, it may result in a flaky test, so such waits are generally unreliable and not advisable.
• Dynamic wait: The dynamic wait is implemented in the code with the help of a class called as WebDriverWait. This class has a method called as until ( ). In this method, we pass an event which may occur and the time units for which we wish to wait for that event to occur. So in this method of WebDriverWait, we either wait for an event to occur or it times out. The exception we get in here, in case the event doesn’t occur, is TimedOutException. But in case the event has occurred, we do not wait for the entire amount of time to finish, we get out of the until loop as soon as it’s finished.
So, we will have a look at two sets of code here. In the first example, we will run a positive scenario of login logout using WebDriverWait. In the second example, we will execute a negative scenario in which we will fail forcefully by passing wrong object information in the code. So the method will wait for the timeout object to appear:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import webDriverwait from selenium.webdriver.support import expected_conditions as EC import unitest class Login(unitest.TestCase): def setup(self): self.driver = webdriver.chrome(executable_path="D:\Eclipse\BPB\seleniumpython\seleniumpython\drivers\chromedriver.exe") self.base_url="http://practice.bpbonline.com/catalog/index.php" dex test_login(self): driver=self.driver driver.get(self.base_url) driver.find_element_by_link_text("My Account").click( ) driver.find_element_by_name("email_address").clear( ) driver.find_element_by_name("email_address").send_keys("[email protected]") driver.find_element_by_name("password").clear( ) driver.find_element_by_name("password").send_keys("bpb@123") driver.find_element_by_id("tab1").click( ) webdriverwait(driver, 1e).until( Ec.presence_of_element_located((By.LINK_TEXT, "log off"))) driver.find_element_by_link_text("log off").click( ) driver.find_element_by_link_text("continue").click( ) def tearDown(self): self.driver.quit( ) if _name_ ==" _main_ ": unitest.main( )
The code lines using which we have implemented explicit wait are: WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.LINK_TEXT, “Log Off”)))
In the preceding until( ) method, we take an input argument called EC. presence_of_element_located(By.LINK_TEXT, ” Log Off”), here the EC is basically the class called as expected_ conditions exported from selenium.web driver.support import expected_conditions asEC. It has a lot of methods available with it which can help trace an event. In the preceding code, we have used a method presence_of_element_located, so this will basically look for the link with the text Log Off, for 10 seconds. If it finds the link within 10 seconds it will exit the until loop and execute the next command, which is clicking on the link, otherwise, it will timeout and throw a TimedOutException.
Let us try another code example, where we will give a bad locator for the Log Off link, causing the WebDriver wait method to timeout:
WebOriverHait(driver, 10}.until(
EC:presence_of_elenent_located((By.LIHK_TEXT, “Log ££”})) driver.find_eleinent_by_link_text(“Log Off”).click()
The exception which is thrown is an follows:
raise TiraeoutException(message, screen., stacktrace)
selenium.common,exceptions.TimeoutrExceptions Message;
Conclusion
In this chapter, we have seen how we can use the concept of waits, implicit and explicit wait, in our test automation code and ensure that the scripts are reliable during execution time. By implementing the concept of synchronization we have tried to achieve less flaky tests and introduce predictability in them during execution time. In the next chapter, we will discuss advanced types of web elements like table, dropdown, alerts, and frame. We will see how to automate these elements and what all methods are associated with them.
Related Articles:
- Chapter 1 Introduction to Selenium
- Chapter 2 Selenium IDE
- Chapter 3 Locators in Selenium
- Chapter 4 Installation and setup
- Chapter 5 Understanding WebDriver, WebElement and By
- Chapter 6 Unittest in Python
- Chapter 8 Concept of Parameterization
- Chapter 9 Working with Different Web Elements
- Chapter 10 Frames, Alerts, and Action Class
- Chapter 11 Page Object Model
- Chapter 12 Selenium-Grid