显示等待WebDriverWait常用写法解析
在网络上各种selenium自动化测试框架搭建的过程中,对于selenium显示等待有好几种写法,包含但不限于以下几种:
-
写法1:
+++ from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait self.driver = webdriver.Chrome() WebDriverWait(self.driver).until(lambda x:x.find_element(*loc)) +++
-
写法2:
+++ from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait self.driver = webdriver.Chrome() WebDriverWait(self.driver).until(EC.presence_of_element_located(loc)) +++
-
写法3:
+++ from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC self.driver = webdriver.Chrome() EC.presence_of_element_located(loc)(self.driver) +++
新手看着可能有些晕乎乎的,我曾经也是看着也挺晕的。接下来我就要来说说这几种写法是怎么运行的。
写法1
先来简单看看写法,在WebDriverWait初始化时传入了driver参数,然后调用until方法,传入了一个lambda匿名函数
WebDriverWait(self.driver).until(lambda x:x.find_element(loc))
为了看清运行原委我们得去看看源码(如果你创建了虚拟环境的话,路径会如下所示):
venv\Lib\site-packages\selenium\webdriver\support\wait.py
![](https://i.loli.net/2020/09/27/QirbgsmR24nF3zD.png)
可以看到driver参数传进来之后被赋值给了WebDriverWait类变量_driver,那么他在哪里使用了呢,我们接着往下看:
![](https://i.loli.net/2020/09/27/E86tCVwXSs2zakT.png)
在WebDriverWait类的until函数中使用了。
先看一下until的函数注释(翻译):调用驱动程序提供的方法作为参数,直到返回值不是False。
结合上文,我们传入的method是lambda x:x.find_element(*loc)
是一个匿名函数。
![](https://i.loli.net/2020/09/28/SEaTAn2cQMZxrKX.png)
结合官方文档的说明,f(0)可以实现给lambda传入参数。lambda可以引用所在域的变量,x引用的域变量就是WebDriverWait的self._driver类变量 ,lambda x:x.find_element(loc)
表达式就被替换成为了self.driver.find_element就可以正常的使用driver使用一样
写法1的运行大致就是这样了。
写法2
写法2我们必须关联以下expected_conditions模块才能看清楚
venv\Lib\site-packages\selenium\webdriver\support\expected_conditions.py
![](https://i.loli.net/2020/09/28/8K7luZse19wjqQL.png)
可以看到EC中的都是类,函数只有两个,后面介绍
第二种写法里面我们先看until里面的部分,locator的参数就是我们传入的loc,loc是什么呢,就是(By.ID,'#su')
这种。
然后下面实现了一个__call__
方法,里面传入的参数就是driver,这个方法是什么意思呢,请看下面的小提示。
小提示:重载运算符(魔法方法),python中的可调用对象包括
自定义的函数
、python内置函数
,类的实例化对象
,method() =method.__call__()
函数。
这个方法还是通过method(self._driver)方式传入了driver的实例对象。
然后第64行把这两个参数传给了_find_element方法,EC模块中的两个函数这个就是其中之一:
![](https://i.loli.net/2020/09/28/igHp549hwoaluIC.png)
这个函数返回了什么呢,第411行,返回了driver.find_element()方法,通过__call__
方法返回了self.driver.find_element。
由此我们可以推断出写法1和写法2是完全一样的,包括解包的时机。
写法3
读完了写法1和写法2,写法3会显得更简单
presence_of_element_located(传入的参数)(传入的driver),在前面小提示已经说过,第二个括号中的正是通过__call__
方法来实现的重载运算()调用。
然后两个参数传入进去后,presence_of_element_located函数返回driver.find_element。
和写法1和写法2不同的是外层没有包含显示等待的类。所以写法3不支持显示等待,只是返回了一个普通的driver方法或基于driver方法实现的结果。
随风挥手 ——土木狗的IT生涯 | 群: 299524235 |