宝塔服务器面板,一键全能部署及管理,送你10850元礼包,点我领取

在网络上各种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))

为了看清运行原委我们得去看看源码(如果你创建了虚拟环境的话,路径会如下所示):

venvLibsite-packagesseleniumwebdriversupportwait.py

显示等待WebDriverWait常用写法解析-冯金伟博客园

可以看到driver参数传进来之后被赋值给了WebDriverWait类变量_driver,那么他在哪里使用了呢,我们接着往下看:

显示等待WebDriverWait常用写法解析-冯金伟博客园

在WebDriverWait类的until函数中使用了。
先看一下until的函数注释(翻译):调用驱动程序提供的方法作为参数,直到返回值不是False。

结合上文,我们传入的method是lambda x:x.find_element(*loc)是一个匿名函数。

显示等待WebDriverWait常用写法解析-冯金伟博客园

结合官方文档的说明,f(0)可以实现给lambda传入参数。lambda可以引用所在域的变量,x引用的域变量就是WebDriverWait的self._driver类变量 ,lambda x:x.find_element(loc)表达式就被替换成为了self.driver.find_element就可以正常的使用driver使用一样

​ 写法1的运行大致就是这样了。

写法2

写法2我们必须关联以下expected_conditions模块才能看清楚

venvLibsite-packagesseleniumwebdriversupportexpected_conditions.py

显示等待WebDriverWait常用写法解析-冯金伟博客园

可以看到EC中的都是类,函数只有两个,后面介绍

第二种写法里面我们先看until里面的部分,locator的参数就是我们传入的loc,loc是什么呢,就是(By.ID,'#su')这种。

然后下面实现了一个__call__方法,里面传入的参数就是driver,这个方法是什么意思呢,请看下面的小提示。

小提示:重载运算符(魔法方法),python中的可调用对象包括自定义的函数python内置函数类的实例化对象,method() = method.__call__()函数。
这个方法还是通过method(self._driver)方式传入了driver的实例对象。

然后第64行把这两个参数传给了_find_element方法,EC模块中的两个函数这个就是其中之一:

显示等待WebDriverWait常用写法解析-冯金伟博客园

这个函数返回了什么呢,第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方法实现的结果。