我们在做 web 网站自动化测试的过程中, 会经常遇到 web 应用程序使用了 AJAX 技术. 当浏览器加载页面的时候, 而页面上的元素还未同时被加载完成, 那么我们此时进行元素的定位往往会出现错误, 影响我们在自动化测试工作进程. 这样在加载某个元素延迟而造成了 ElementNotVisibleException 的报错, 就会降低自动化脚本的稳定性. 如何解决这个问题呢? 我们可以通过设置元素等待改善这种问题造成的负面影响. 我们可以描绘成这种场景, 程序员和女友约好吃西餐, 结果程序员在西餐厅吃的美滋滋回来后看到女友还在梳妆台化妆, 好奇的问怎么还在化妆没有出门呢? 女友心里顿时无名的火涌上心头, 欺负我慢不和你谈对象了, 抛个异常跟你分手.
webdriver 为我们提供了三种等待方法:
1, 强制等待
第一种是办法简单粗暴就是强制等待 sleep(), 强制让程序员等待 xx 时间, 不管女朋友能不能来到约会地点, 还是已经提前到了, 都必须等待 xx 时间
- from time import sleep
- from selenium import webdriver
- url='https://www.baidu.com/'
- driver=webdriver.Chrome()
- driver.get(url)
- sleep(3)
- print(driver.current_url)
- driver.quit()
这种叫强制等待, 不管你浏览器是否加载完了, 程序都得等待 3 秒, 3 秒一到, 继续执行下面的代码, 作为调试很有用, 有时候也可以在代码里这样等待, 不过不建议总用这种等待方式, 太死板, 严重影响程序执行速度.
2, 隐性等待
第二种方法就比强制等待方法较细腻人性化了, implicitly_wait(xx), 我们可以想象成这样的场景: 程序员和女友约定好, 不论程序员什么时候到了约定地点, 都必须要等女友一家子 xx 秒, 如果女友一家子这段时间内来了, 好的和女友手挽手去西餐厅共进晚餐, 但是如果女友在规定的时间内没赶到, 则程序员自己去, 结果自然就是女友发飙给你抛个异常恶心一下.
- from selenium import webdriver
- url='https://www.baidu.com/'
- driver=webdriver.Chrome()
- driver.implicitly_wait(20)# 隐性等待, 最长等待 20s
- driver.get(url)
- print(driver.current_url)
- driver.quit()
隐形等待是设置了一个最长等待时间, 如果在规定时间内网页加载完成, 则执行下一步, 否则一直等到时间截止, 然后执行下一步. 但是这里有一个弊端, 那就是程序会一直等待整个页面加载完成, 也就是我们可以看到浏览器标签栏那个小圈不再转, 才会执行下一步, 通常页面想要的元素早就在加载完成了, 但是因为个别 js 之类的东西特别慢, 得等到页面全部完成才能执行下一步, 那我们需要主题元素出现就可以下一步该如何去做呢, 那就要看 selenium 提供的另一种等待方式 -- 显性等待 wait 了. 这里需要强调的是: 隐性等待对整个 driver 的周期都起作用, 所以只要设置一次即可.
3, 显性等待
第三种方法就是显性等待, WebDriverWait, 配合该类的 until() 和 until_not() 方法, 就能够根据判断条件来进行灵活地等待了. 它主要的意思是: 程序每隔 xx 秒看以下条件是否满足, 如果条件成立了, 则执行下一步, 否则继续等待, 直到超过设置的最长时间, 然后抛出 TimeoutException. 我们可以想象成这样的场景: 程序员和女友约定好, 不论程序员什么时候到了约定地点, 都必须要等女友一家子 xx 秒, 而与第二个场景不同的是程序员隔一段时间观望主体女友是否出现, 若来了程序员就不需要再等待, 直接拉着女友手挽手去西餐厅共进晚餐不用管女友一家子了.
- from selenium import webdriver
- from selenium.webdriver.support.wait import WebDriverWait
- from selenium.webdriver.support import expected_conditions as EC
- from selenium.webdriver.common.by import By
- url='https://www.baidu.com/'
- driver = webdriver.Chrome()
- driver.implicitly_wait(20) # 隐性等待和显性等待可以同时用, 但要注意: 等待的最长时间取两者之中的大者
- driver.get(url)
- locator = (By.ID, 'su')
- try:
- WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator))
- finally:
- driver.close()
上例中, 我们设置了隐性等待和显性等待, 在其他操作中, 隐性等待起决定性作用, 在 WebDriverWait.. 中显性等待起主要作用, 但要注意的是: 最长的等待时间取决于两者之间的大者, 如果隐性等待时间 > 显性等待时间, 则该句代码的最长等待时间等于隐性等待时间.
来源: https://www.cnblogs.com/gentleman-shao/p/9105464.html