Building robust and reliable tests is one of the key factors for the success of UI automation testing. But the actual situation is that when one test is executed after another, we often encounter various situations. For example, when the script locates the element or verifies the running state of the program, it sometimes finds that the element cannot be found, which may be caused by the slow response speed caused by sudden resource constraints or network delays. At this time, the result of test failure will be returned. so we need to introduce a delay mechanism into the test script to match the running speed of the script with the response speed of the program. Even if the response of script and program can be synchronized. WebDriver provides us with two mechanisms: implicit waiting and explicit waiting. Here are the following descriptions:
Implicit waiting provides a general method for the synchronization of a complete test case or a set of tests in WebDriver. It is very effective to solve the inconsistency of program response time caused by network delay or dynamic loading using Ajax.
After the DOM is successfully searched, the duration of waiting for one or more DOM elements to be loaded will be set immediately. In general, the default timeout for implicit waiting is set to 0. However, once set, it will affect the whole life cycle of this WebDriver instance or the execution period of a complete test, and the WebDriver will make it effective when looking up the elements of the whole page contained in all test steps.
WebDriver provides the implicit_ Use the wait () method to configure the timeout. For test scripts written based on unittest, the implicit waiting time is often added to the setUp() method and set to 30 seconds. When the test is executed, WebDriver will wait 30 seconds when it cannot find an element. When the timeout of 30 seconds is reached, an exception of NoSuchElementException will be thrown. The following is a simple Baidu search test script using implicit waiting mechanism. The code is as follows:
import unittest from selenium import webdriver class BaiduSearchTest(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome() self.driver.implicitly_wait(30) #set implicit wait time 30s self.driver.maximize_window() #open the baidu page self.driver.get('https://www.baidu.com') def test_search_python(self): #get the search textbox search_textbox = self.driver.find_element_by_id('kw') search_textbox.clear() #enter search keyword search_textbox.send_keys("python") #get the and seacrh button and click search_button = self.driver.find_element_by_id('su') search_button.click() #add assert tag = self.driver.find_element_by_link_text("PyPI").text self.assertEqual('PyPI',tag) def tearDown(self): #close the browser window self.driver.quit() if __name__ == '__main__': unittest.main(verbosity=2)
Explicit waiting is another waiting mechanism for synchronous testing in WebDriver. Explicit waiting has better maneuverability than implicit waiting. Different from the implicit wait, the display wait needs to set some preset or customized conditions for the script, and the next test can be carried out after the conditions are met.
Explicit waiting can only work on test cases that only need synchronization. WebDriver provides WebDriverWait class and expected_conditions class to implement explicit waiting. expected_ The condition class provides some preset conditions as the judgment basis for the next test of the test script. The following is a simple test script with explicit wait. The code is as follows:
import unittest 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 class BaitduExplicitWaitTest(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome() self.driver.get('https://www.baidu.com') def test_login_link(self): WebDriverWait(self.driver, 10).until(lambda s: s.find_element_by_name("tj_login").get_attribute("class") == "lb") login_link = WebDriverWait(self.driver, 10).until(expected_conditions.element_to_be_clickable((By.LINK_TEXT, "Sign in"))) login_link.click() def tearDown(self): self.driver.quit() if __name__ == '__main__': unittest.main(verbosity=2)
The above script first uses python's lambda expression, and realizes customized expected condition judgment based on WebDriverWait. Set the explicit wait timeout to 10s until the login element is obtained and its class attribute is determined to be 1b. Use element at the same time_ to_ be_ Clickable method to determine whether the expected conditions are met. The condition is that the elements waiting to be found through the locator are visible and available. Here is the login option, which can be clicked until the maximum waiting time is 10s. Once the element is found according to the specified locator, the expected condition determination method will return the element to the test script for the next click operation. If no visible clickable element is found through the locator within the set timeout, a timeoutexpectation exception will be thrown.
The following table is expected_ The conditions class supports some common waiting conditions for automatic operation of web browsers.
expected_ The conditions class has provided a variety of built-in expected waiting conditions, which can be directly called in our actual work. But if it exceeds expected_ Don't be afraid of the scope of conditions. WebDriverWait class also provides powerful custom expected waiting judgment function.
Note: try to avoid mixing implicit wait with explicit wait in testing to deal with synchronization problems.
For more information on waiting mechanism, please refer to: https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.wait.html#module-selenium.webdriver.support.wait