【Selenium学习】Selenium 总结

1.Selenium 简介

Selenium 经历了三个大版本,Selenium 1.0、Selenium 2.0 和 Selenium 3.0。

Selenium 不是由单独一个工具构成的,而是由一些插件和类库组成的,这些插件和类库有其各自的特

点和应用场景。Selenium 1.0 家族关系如下图所示。

1.1 Selenium 1.0

(1)Selenium IDE。

Selenium IDE 是嵌入在 Firefox 浏览器中的一个插件,它提供了比较完备的自动化功能,如脚本录制/回放、定时任务等;还可以将录制的脚本导成不同编程语言的 Selenium 测试脚本,这在很大程度上可以帮助新手编写测试用例。

但旧版的 Selenium IDE 不支持 Firefox 新版本支持的 API,因此 Selenium 团队重新开

发了新版的 Selenium IDE,可以同时支持 Chrome、Firefox 以及其他浏览器。

项目地址:https://github.com/SeleniumHQ/selenium-ide

(2)Selenium Grid。

Selenium Grid 是一个自动化测试辅助工具。利用 Grid 可以很方便地实现在多台机器上

或异构环境中运行测试用例。

(3)Selenium RC(Remote Control)。

Selenium RC是 Selenium 家族的核心部分,支持多种不同语言编写的自动化测试脚本。把 Selenium RC 的服务器作为代理服务器去访问应用,即可达到测试的目的。

Selenium RC 分为 Client Libraries 和 Selenium Server 两部分。Client Libraries 主要用于

编写测试脚本,负责控制 Selenium Server 的库。Selenium Server 负责控制浏览器行为。

Selenium Server 主要分为三部分:Selenium Core、Launcher 和 Http Proxy。Selenium Core

就是一堆 JavaScript 函数的集合。通过这些 JavaScript 函数,我们可以用程序对浏览器进行

操作。Launcher 用于启动浏览器,把 Selenium Core 加载到浏览器页面当中,同时,把浏览

器的代理设置为 Http Proxy。

1.2 Selenium 2.0

Selenium 2.0 把 WebDriver 加到了 Selenium1.0 这个家族中,简单用公式表示如下:

Selenium 2.0 = Selenium 1.0 + WebDriver

需要注意的是,在 Selenium 2.0 中主推的是 WebDriver,可以将其看作 Selenium RC 的

替代品。为了保持向下的兼容性,Selenium 2.0 并没有彻底抛弃 Selenium RC。

Selenium RC 与 WebDriver 的工作方式有着本质的区别。

(1)Selenium RC的工作原理:

需要Selenium RC启动一个Server,将操作Web元素的API调用转化为一段段Javascript,在Selenium内核启动浏览器之后注入这段Javascript。这种Javascript注入技术的缺点是速度不理想,而且稳定性大大依赖于Selenium内核对API翻译成的Javascript质量高低。

(2)WebDriver的工作原理:

当Selenium2.x 提出了WebDriver的概念之后,它提供了完全另外的一种方式与浏览器交互。那就是利用浏览器原生的API,封装成一套更加面向对象的Selenium WebDriver API,直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件,配置证书之类的)。由于使用的是浏览器原生的API,速度大大提高,并且避免了 JavaScript 安全模型导致的限制。当然带来了一些副作用,就是不同的浏览器厂商,对Web元素的操作和呈现多少会有一些差异,这就直接导致了Selenium WebDriver要分浏览器厂商不同,而提供不同的实现。例如Firefox就有专门的FirefoxDriver,Chrome就有专门的ChromeDriver等等。(甚至包括了AndroidDriver和iOS WebDriver)

1.3 Selenium 3.0

Selenium 3.0 做了以下更新:

(1)去掉了 Selenium RC,简单用公式表示如下:

Selenium 3.0 = Selenium 2.0 −Selenium RC

(2)Selenium 3.0 只支持 Java 8 以上版本。

(3)Selenium 3.0 中的 Firefox 浏览器驱动独立了。Selenium 2.0 测试库默认是集成

Firefox 浏览器驱动的,在 Selenium 3.0 中,Firefox 浏览器和 Chrome 浏览器一样,在使用

前需要下载和设置浏览器驱动。

(4)mac OS 操作系统集成了 Safari 的浏览器驱动,该驱动默认在/usr/bin/safaridriver 目

录下。

(5)只支持 IE 9.0 以上版本。

1.4 各浏览器驱动下载地址

GeckoDriver(Firefox):https://github.com/mozilla/geckodriver/releases

ChromeDriver(Chrome):https://sites.google.com/a/chromium.org/chromedriver/home

IEDriverServer(IE):http://selenium-release.storage.googleapis.com/index.html

OperaDriver(Opera):https://github.com/operasoftware/operachromiumdriver/releases

MicrosoftWebDriver(Edge):https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver

2. Selenium 八大定位法

2.1 ID定位

HTML Tag 的 id 属性值是唯一的,故不存在根据 id 定位多个元素的情况。下面以在百度首页搜索框输入文本“python”为例。搜索框的 id 属性值为“kw”,如图1.1所示:

代码如下,“find_element_by_id”方法已废弃,使用find_element(By.ID, 'kw')

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
# 需要将浏览器驱动添加到环境变量中
# 打开百度
driver.get('https://www.baidu.com/')
# 通过id,在搜索输入框中输入文本“python”
driver.find_element(By.ID, 'kw').send_keys('python')
# 点击搜索
driver.find_element(By.ID, 'su').click()
# 关闭浏览器
driver.close()

2.2 name 定位

以上百度搜索框也可以用 name 来实现,如图 1.1 所示,其 name 属性值为“wd”,方法“find_element(By.NAME, 'wd')”表示通过 name 来定位

代码如下:

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 通过name,在搜索输入框中输入文本“自动化测试”
driver.find_element(By.NAME, 'wd').send_keys('自动化测试')
# 点击搜索
driver.find_element(By.ID, 'su').click()
# 关闭浏览器
driver.close()

注意:用 name 方式定位需要保证 name 值唯一,否则定位失败。

2.3 class 定位

以百度首页搜索框为例,如图 1.1所示,其 class 属性值为“s_ipt”,“By.CLASS_NAME, 's_ipt'”表示通过 class_name 来定位

代码如下:

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 通过class,在搜索输入框中输入文本“web测试”
driver.find_element(By.CLASS_NAME, 's_ipt').send_keys('web测试')
# 点击搜索
driver.find_element(By.ID, 'su').click()
# 关闭浏览器
driver.close()

2.4 link_text 定位

link_text 是以超链接全部名字作为关键字来定位元素的。以百度首页“新闻”超链接为例,如图 1.2 所示,关键字为“新闻”。

代码如下:

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 通过link_text定位,点击‘新闻’超链接
driver.find_element(By.LINK_TEXT, '新闻').click()
# 关闭浏览器
driver.close()

注意:用此方法定位元素超链接,中文字需要写全。

2.5 partial_link_text 定位

即用超链接文字的部分文本来定位元素,类似数据库的模糊查询。以“新闻”超链接为例,只需“新”一个字即可,即取超链接全部文本的一个子集。

代码如下:

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 通过partial_link_text定位,用超链接文字的部分文本来定位元素,类似数据库的模糊查询
driver.find_element(By.PARTIAL_LINK_TEXT, '新').click()
# 关闭浏览器
driver.close()

2.6 tag_name 定位

tag_name 定位即通过标签名称定位,如图 1.6所示,定位标签“form”并打印标签属性值“name”。

代码如下:

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# tag_name 定位即通过标签名称定位
print(driver.find_element(By.TAG_NAME, 'form').get_attribute('name'))

成功后控制台输出“f”

2.7 CSS 定位

CSS 定位的优点是速度快、语法简洁。表 1.1 中的内容出自 W3School 的 CSS 参考手册。CSS 定位的选择器有十几种,在本节中主要介绍几种比较常用的选择器。

仍以百度搜索框为例,代码如下:

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')

#  以class选择器为例,实现CSS定位,在搜索框输入“python3”
driver.find_element(By.CSS_SELECTOR, '.s_ipt').send_keys('python3')

#  以id定位语法结构为:#加 id 名,实现CSS定位,在搜索框输入“python3”
driver.find_element(By.CSS_SELECTOR, '#kw').send_keys('python3')

# CSS 定位主要利用属性 class 和 id 进行元素定位。也可以利用常规的标签名称来定位,如输入框标签“input”,在标签内部又设置了属性值为“name=’wd’”
driver.find_element(By.CSS_SELECTOR, "input[name='wd']").send_keys('python3')

# CSS 定位方式可以使用元素在页面布局中的绝对路径来实现元素定位。百度首页搜索输入框元素的绝对路
# 径为“html>body>div>div>div>div>div>form>span>input[name="wd"]”
driver.find_element(By.CSS_SELECTOR, 'html>body>div>div>div>div>div>form>span>input[name="wd"]').send_keys('python3')

# CSS 定位也可以使用元素在页面布局中的相对路径来实现元素定位。相对路径的写法和直接利用标签名称来定位,两者
# 的代码实现的功能是一致的
driver.find_element(By.CSS_SELECTOR, "input[name='wd']").send_keys('python3')

# 点击搜索
driver.find_element(By.ID, 'su').click()
# 关闭浏览器
driver.close()

2.8 XPath 定位

通过 XPath 来定位元素的方式,对比较难以定位的元素来说很有效,几乎都可以解决,特别是对于有些元素没有 id、name 等属性的情况。

XPath 是 XML Path 语言的缩写,是一种用来确定 XML 文档中某部分位置的语言。它在 XML 文档中通过元素名和属性进行搜索,主要用途是在 XML 文档中寻找节点。XPath定位比 CSS 定位有更大的灵活性。XPath 可以向前搜索也可以向后搜索,而 CSS 定位只能向前搜索,但是 XPath 定位的速度比 CSS 慢一些。

XPath 语言包含根节点、元素、属性、文本、处理指令、命名空间等。以下文本为 XML实例文档,用于演示 XML 的各种节点类型,便于理解 XPath。

<?xml version = "1.0" encoding = "utf-8" ?> 
<!-- 这是一个注释节点 --> 
<animalList type="mammal"> 
 <animal categoruy = "forest"> 
 <name>Tiger</name> 
 <size>big</size> 
 <action>run</action> 
 </animal> 
</animalList>

其中<animalList>为文档节点,也是根节点;<name>为元素节点;type=“mammal”为属性节点。

节点之间的关系:

• 父节点。每个元素都有一个父节点,如上面的 XML 示例中,animal 元素是 name、size,以及 action 元素的父节点。

• 子节点。与父节点相反,这里不再赘述。

• 兄弟节点,有些也叫同胞节点。它表示拥有相同父节点的节点。如上代码所示,name、size 和 action 元素都是同胞节点。

• 先辈节点。它是指某节点的父节点,或者父节点的父节点,以此类推。如上代码所示,name 元素节点的先辈节点有 animal 和 animalList。

• 后代节点。它表示某节点的子节点、子节点的子节点,以此类推。如上代码所示,animalList 元素节点的后代节点有 animal、name 等。

仍以百度搜索框为例,代码如下:

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# XPath 有多种定位策略,最简单直观的就是写出元素的绝对路径。
driver.find_element(By.XPATH, '/html/body/div/div/div/div/div/form/span/input').send_keys('python3')

# XPath还可以使用元素的属性值来定位。//input 表示当前页面某个 input 标签,[@id='kw'] 表示这个元素的 id 值是 kw。
driver.find_element(By.XPATH, "//input[@id='kw']").send_keys('python3')

# 如果一个元素本身没有可以唯一标识这个元素的属性值,我们可以查找其上一级元素。
# form[@class='fm  has-soutu']通过 class 定位到父元素,后面的/span/input 表示父元素下面的子元素。
driver.find_element(By.XPATH, "//form[@class='fm  has-soutu']/span/input").send_keys('python3')

# 如果一个属性不能唯一区分一个元素,那么我们可以使用逻辑运算符连接多个属性来查找元素
driver.find_element(By.XPATH, "//input[@id='kw' and @class='s_ipt']").send_keys('python3')

# 点击搜索
driver.find_element(By.ID, 'su').click()
# 关闭浏览器
driver.close()

3.Selenium 中常用的元素操作方法

3.1.send_keys 方法模拟键盘键入

此方法类似于模拟键盘键入。以在百度首页搜索框输入“Selenium”为例,代码如下:

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 通过id,在搜索输入框中输入文本“Selenium”
driver.find_element(By.ID, 'kw').send_keys('Selenium')

3.2.text 方法获取文本值

Selenium 提供了 text 方法用于获取文本值,即 HTML 标签“<a></a>”之间的文字。以在

百度首页超链接“新闻”为例,代码如下:

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 通过link_text定位,点击‘新闻’超链接
driver.find_element(By.LINK_TEXT, '新闻').click()

3.3.get_attribute()获取属性值

以百度首页的“百度一下”按钮为例,获取属性 value 对应的值(页面元素如图所示),

可以用 get_attribute 方法来实现。

代码如下:

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 执行后,控制台打印“百度一下”
print(driver.find_element(By.ID, 'su').get_attribute('value'))

输出结果为:

3.4.set_window_size()方法控制浏览器窗口大小

from selenium import webdriver

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 参数数字为像素
print("设置浏览器宽 480、高 500 显示")
driver.set_window_size(480, 500)

3.5.maximize_window() 方法控制浏览器窗口最大化

from selenium import webdriver

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 参数数字为像素
print("设置浏览器宽 480、高 500 显示")
driver.set_window_size(480, 500)
# 将窗口最大化
driver.maximize_window()

3.6.控制浏览器后退、前进

在使用 Web 浏览器浏览网页时,浏览器提供了后退和前进按钮,可以方便地在浏览过

的网页之间切换,WebDriver 还提供了对应的 back()和 forward()方法来模拟后退和前进按

钮。下面通过例子演示这两个方法的使用。

from selenium import webdriver

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 访问百度首页
first_url = 'http://www.baidu.com'
print("now access %s" %(first_url))
driver.get(first_url)
# 访问新闻页
second_url='http://news.baidu.com'
print("now access %s" %(second_url))
driver.get(second_url)
# 返回(后退)到百度首页
print("back to %s " %(first_url))
driver.back()
# 前进到新闻页
print("forward to %s" %(second_url))
driver.forward()

为了看清楚脚本的执行过程,这里每操作一步都通过 print()打印当前的 URL 地址。

3.7.refresh()方法模拟浏览器刷新

from selenium import webdriver

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
#刷新当前页面
driver.refresh()

3.8.submit():提交表单。

有些搜索框不提供搜索按钮,而是通过按键盘上的回车键完成搜索内容的提交,这时可以通过 submit()模拟。

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 搜索框输入‘python’
driver.find_element(By.ID, 'kw').send_keys('python')
# 提交表单
driver.find_element(By.ID, 'kw').submit()

3.9.clear() 清除输入框值

以在百度搜索框输入“python”,再清除为例,示例代码如下:

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 搜索框输入‘python’
driver.find_element(By.ID, 'kw').send_keys('python')
# 清除内容
driver.find_element(By.ID, 'kw').clear()

3.10.close()关闭当前窗口

from selenium import webdriver

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 关闭浏览器
driver.close()

quit()也是关闭浏览器,但是是退出驱动程序并关闭所有相关窗口Selenium 中特殊元素操作

4.Selenium 中特殊元素操作

4.1.鼠标定位操作

鼠标悬停,即当光标与其名称表示的元素重叠时触发的事件,在 Selenium 中将键盘鼠标操

作封装在 Action Chains 类中。Action Chains 类的主要应用场景为单击鼠标、双击鼠标、鼠标拖

曳等。部分常用的方法使用分类如下:

• click(on_element=None),模拟鼠标单击操作。

• click_and_hold(on_element=None),模拟鼠标单击并且按住不放。

• double_click(on_element=None),模拟鼠标双击。

• context_click(on_element=None),模拟鼠标右击操作。

• drag_and_drop(source,target),模拟鼠标拖曳。

• drag_and_drop(source,xoffset,yoffset),模拟将目标拖曳到目标位置。

• key_down(value,element=None),模拟按住某个键,实现快捷键操作。

• key_up(value,element=None),模拟松开某个键,一般和 key_down 操作一起使用。

• move_to_element(to_element),模拟将鼠标移到指定的某个页面元素。

• move_to_element_with_offset(to_element,xoffset,yoffset),移动鼠标至指定的坐标。

• perform(),将之前一系列的 ActionChains 执行。

• release(on_element=None),释放按下的鼠标。

接下来,列举鼠标右击操作和鼠标双击操作两个实例。

(1)鼠标右击操作,实现右击/双击百度首页“新闻”超链接。代码如下:
# _*_ coding:utf-8 _*_
"""
name:zhangxingzai
date:2023/2/16
form:《Selenium 3+Python 3自动化测试项目实战》
"""

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 定位超链接‘新闻’
element = driver.find_element(By.LINK_TEXT, '新闻')
# 实现在新闻超链接上右击
ActionChains(driver).context_click(element).perform()
# 实现用鼠标实现双击‘新闻’
ActionChains(driver).double_click(element).perform()
(2)以百度首页设置为例,使用“move_to_element”的方法,鼠标即可悬停于元素设置:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 通过id定位超链接‘设置’
setting = driver.find_element(By.ID, 's-usersetting-top')
# 使用方法 move_to_element 模拟将鼠标悬停在超链接“设置”处
ActionChains(driver).move_to_element(setting).perform()
# 定位超链接‘高级设置’,并实现单击操作
driver.find_element(By.CLASS_NAME, 'set').click()

实现效果如下:

4.2.Select 操作

Web 页面中经常会遇到下拉框选项,Select 模块提供了对标准 Select 下拉框的多种操作方

法。打开百度,单击“设置→高级设置”,会出现一个 Select 下拉框,如下图所示:

Select 元素的 HTML 代码如下图所示。

接下来介绍 3 种选择 Select 元素的值的方法。

Select 类:用于定位<select>标签。

select_by_value():通过 value 值定位下拉选项。

select_by_visible_text():通过 text 值定位下拉选项。

select_by_index():根据下拉选项的索引进行选择。第一个选项为 0,第二个选项为 1。

通过 WebDriver 代码操作下拉框,代码如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from selenium.webdriver.support.select import Select

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 定位超链接‘设置’
setting = driver.find_element(By.ID, 's-usersetting-top')
# 使用方法 move_to_element 模拟将鼠标悬停在超链接“设置”处
ActionChains(driver).move_to_element(setting).perform()
# 通过xpath定位超链接‘高级’,并实现单击操作
driver.find_element(By.XPATH, "//div/a[@target='_blank']/span").click()
# 通过class定位选择‘全部时间’
search_time = driver.find_element(By.CLASS_NAME, 'c-select-selection')
# 通过 value 值定位下拉选项
Select(search_time).select_by_value('stf=1676475129.442,1676561529.442|stftype=1')
# 通过 text 值定位下拉选项
Select(search_time).select_by_visible_text('最近一周')

4.3.键盘操作

前面介绍过,send_keys()方法可以用来模拟键盘输入,我们还可以用它来输入键盘上

的按键,甚至是组合键,如 Ctrl+a、Ctrl+c 等。

经过总结,以下为自动化测试中常用的键盘事件。

• Keys.BACK_SPACE:删除键。

• Keys.SPACE:空格键。

• Keys.TAB:Tab 键。

• Keys.ESCAPE:回退键。

• Keys.ENTER:回车键。

• Keys.CONTROL,”a”:组合键 Ctrl + A。

• Keys.CONTROL,”x”:组合键 Ctrl + X。

• Keys.CONTROL,”v”:组合键 Ctrl + V。

• Keys.CONTROL,”c”:组合键 Ctrl + C。

• Keys.F1:F1 键。

• Keys.F12:F12 键。

用法举例,如下方代码展示:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from time import sleep

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 在输入框输入内容
driver.find_element(By.ID, "kw").send_keys("selenium")
# 删除多输入的一个 m
driver.find_element(By.ID, "kw").send_keys(Keys.BACK_SPACE)
sleep(1)
# 输入空格键+“教程”
driver.find_element(By.ID, "kw").send_keys(Keys.SPACE)
driver.find_element(By.ID, "kw").send_keys("教程")
sleep(1)
# 输入组合键 Ctrl+a,全选输入框内容
driver.find_element(By.ID, "kw").send_keys(Keys.CONTROL, 'a')
sleep(1)
# 输入组合键 Ctrl+x,剪切输入框内容
driver.find_element(By.ID, "kw").send_keys(Keys.CONTROL, 'x')
sleep(1)
# 输入组合键 Ctrl+v,粘贴内容到输入框
driver.find_element(By.ID, "kw").send_keys(Keys.CONTROL, 'v')
sleep(1)
# 用回车键代替单击操作
driver.find_element(By.ID, "su").send_keys(Keys.ENTER)

4.4.利用 JavaScript 操作页面元素

WebDiver 对部分浏览器上控件并不是直接支持的,如浏览器右侧滚动条、副文本等,而是

通常借助 JavaScript 间接操作。WebDriver 提供了 execute_script()和 execute_async_scrip()两种方

法来执行 JavaScript 代码,其区别如下:

(1)execute_script 为同步执行且执行时间较短。WebDriver 会等待同步执行的结果,

然后执行后续代码。

(2)execute_async_script 为异步执行且执行时间较长。WebDriver 不会等待异步执行

代码的结果,而是直接执行后续的代码。

用于调整浏览器滚动条位置的 JavaScript 代码如下。

<!-- window.scrollTo(左边距,上边距); -->
window.scrollTo(0,450);

window.scrollTo()方法用于设置浏览器窗口滚动条的水平位置和垂直位置。第一个参数

表示水平的左边距,第二个参数表示垂直的上边距,代码如下。

from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep

driver = webdriver.Firefox()
# 打开百度
driver.get('https://www.baidu.com/')
# 设置浏览器窗口大小
driver.set_window_size(800, 700)
driver.find_element(By.ID, "kw").send_keys("selenium")
driver.find_element(By.ID, "su").click()
sleep(3)
# 通过 JavaScript 设置浏览器窗口的滚动条位置
js = "window.scrollTo(100,300)"
driver.execute_script(js)

执行结果如下图所示:

4.5.获得验证信息

在进行 Web 自动化测试中,用得最多的几种验证信息是 title、current_url 和 text。

  • title:用于获取当前页面的标题。

  • current_url:用于获取当前页面的 URL。

  • text:用于获取当前页面的文本信息。

下面仍以百度搜索为例,对比搜索前后的信息。

from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep

driver = webdriver.Firefox()
driver.get('https://www.baidu.com/')

print('Before search================')
# 打印当前页面 title
title = driver.title
print("title:" + title)

# 打印当前页面 URL
now_url = driver.current_url
print("URL:" + now_url)

driver.find_element(By.ID, "kw").send_keys("selenium")
driver.find_element(By.ID, "su").click()
sleep(3)

print('After search================')
# 再次打印当前页面 title
title = driver.title
print("title:" + title)
# 再次打印当前页面 URL
now_url = driver.current_url
print("URL:" + now_url)

# 获取搜索结果条数
num = driver.find_element(By.XPATH, "//span[@class='hint_PIwZX c_font_2AD7M']").text
print("result:"+num)

运行结果如下:

通过上面的打印信息可以看出搜索前后的差异,这些差异信息可以拿来作为自动化测试的断言点。

4.6.设置元素等待

WebDriver 提供了两种类型的元素等待:显式等待和隐式等待。

(1)显示等待

显式等待是 WebDriver 等待某个条件成立则继续执行,否则在达到最大时长时抛出超

时异常(TimeoutException)。

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

driver = webdriver.Firefox()
driver.get("https://www.baidu.com")

element = WebDriverWait(driver, 5, 0.5).until(
 EC.visibility_of_element_located((By.ID, "kw"))
 )
element.send_keys('selenium')

WebDriverWait 类是 WebDriver 提供的等待方法。在设置时间内,默认每隔一段时间检

测一次当前页面元素是否存在,如果超过设置时间仍检测不到,则抛出异常。

具体格式如下。

  • driver:浏览器驱动。

  • timeout:最长超时时间,默认以秒为单位。

  • poll_frequency:检测的间隔(步长)时间,默认为 0.5s。

  • ignored_exceptions:超时后的异常信息,默认情况下抛出 NoSuchElementException异常。

WebDriverWait()一般与 until()或 until_not()方法配合使用,下面是 until()和 until_not()

方法的说明:

until(method, message=″)

调用该方法提供的驱动程序作为一个参数,直到返回值为 True。

until_not(method, message=″)

调用该方法提供的驱动程序作为一个参数,直到返回值为 False。

在本例中,通过 as 关键字将 expected_conditions 重命名为 EC,并调用 presence_of_element_located()方法判断元素是否存在。

expected_conditions 类提供的预期条件判断方法如下图所示。

除 expected_conditions 类提供的丰富的预期条件判断方法外,还可以利用is_displayed()方法自己实现元素显示等待。

from time import sleep, ctime
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
driver.get("https://www.baidu.com")
print(ctime())

for i in range(10):
    try:
        el = driver.find_element(By.ID, "kw22")
        if el.is_displayed():
            break
    except:
        pass
    sleep(1)
else:
    print("time out")
print(ctime())

相对来说,这种方式更容易理解。首先 for 循环 10 次,然后通过 is_displayed()方法循环判断元素是否可见。如果为 True,则说明元素可见,执行 break 跳出循环;

否则执行 sleep()休眠 1s 后继续循环判断。10 次循环结束后,如果没有执行 break,则执行 for 循环对应的else 语句,打印“time out”信息。

这里故意将 id 定位设置为“kw22”,定位失败,执行结果如下:

(2)隐式等待

WebDriver 提供的 implicitly_wait()方法可用来实现隐式等待,用法相对来说要简单得

多。

from time import ctime
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException

driver = webdriver.Firefox()
# 设置隐式等待为 10s
driver.implicitly_wait(10)
driver.get("https://www.baidu.com")
try:
    print(ctime())
    driver.find_element(By.ID, "kw22").send_keys('selenium')
except NoSuchElementException as e:
    print(e)
finally:
    print(ctime())

implicitly_wait()的参数是时间,单位为秒,本例中设置的等待时间为 10s。

首先,这10s 并非一个固定的等待时间,它并不影响脚本的执行速度。其次,它会等待页面上的所有

元素。当脚本执行到某个元素定位时,如果元素存在,则继续执行;如果定位不到元素,

则它将以轮询的方式不断地判断元素是否存在。假设在第 6s 定位到了元素,则继续执行,

若直到超出设置时间(10s)还没有定位到元素,则抛出异常。

这里同样故意将 id 定位设置为“kw22”,定位失败,执行结果如下:

4.7.警告框处理

在 WebDriver 中处理 JavaScript 生成的 alert、confirm 和 prompt 十分简单,具体做法是,

首先使用 switch_to.alert()方法定位,然后使用 text、accept、dismiss、send_keys 等进行操

作。

  • text:返回 alert、confirm、prompt 中的文字信息。

  • accept():接受现有警告框。

  • dismiss():解散现有警告框。

  • send_keys():在警告框中输入文本(如果可以输入的话)。

这里以百度搜索设置为例,打开百度搜索设置,设置完成后单击“保存设置”按钮,可以使用 switch_to.alert()方法为百度搜索设置弹窗,如下图所示:

代码如下:

from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains

driver = webdriver.Firefox()
driver.get('https://www.baidu.com/')
# 定位超链接‘设置’
setting = driver.find_element(By.ID, 's-usersetting-top')
# 使用方法 move_to_element 模拟将鼠标悬停在超链接“设置”处
ActionChains(driver).move_to_element(setting).perform()
# 通过class定位超链接‘搜索设置’,并实现单击操作
driver.find_element(By.CLASS_NAME, "set").click()
# 通过xpath获取保存设置
driver.find_element(By.XPATH, "//a[@class='prefpanelgo setting-btn c-btn c-btn-primary']").click()
sleep(3)

# 获取警告框
alert = driver.switch_to.alert
# 获取警告框提示信息
alert_text = alert.text
print(alert_text)
# 接取警告框
alert.accept()

4.8.获取Cookie

有时我们需要验证浏览器中的 Cookie 是否正确,因为基于真实的 Cookie 是无法通过

白盒测试和集成测试的。WebDriver 提供了操作 Cookie 的相关方法,可以读取、添加和删

除 Cookie。

WebDriver 操作 Cookie 的方法如下:

  • get_cookies():获得所有 Cookie。

  • get_cookie(name):返回字典中 key 为“name”的 Cookie。

  • add_cookie(cookie_dict):添加 Cookie。

  • delete_cookie(name,optionsString):删除名为 OpenString 的 Cookie。

  • delete_all_cookies():删除所有 Cookie。

下面通过 get_cookies()获取当前浏览器的所有 Cookie。代码如下:

from selenium import webdriver

driver = webdriver.Firefox()
driver.get('https://www.baidu.com/')
# 获得所有 Cookie 信息并打印
cookie = driver.get_cookies()
print(cookie)

执行结果如下:

从执行结果可以看出,Cookie 中的数据是以字典形式存放的。知道了 Cookie 中数据的

存放形式后,即可按照这种形式向浏览器中添加 Cookie。

from selenium import webdriver

driver = webdriver.Firefox()
driver.get('https://www.baidu.com/')

# 添加 Cookie 信息
driver.add_cookie({'name': 'foo', 'value': 'bar'})
# 遍历指定的 Cookies
for cookie in driver.get_cookies():
    print("%s -> %s" % (cookie['name'], cookie['value']))

执行结果如下:

从执行结果可以看出,最后一条 Cookie 是在脚本执行过程中通过 add_cookie()方法添

加的。通过遍历得到所有的 Cookie,从而找到字典中 key 为“name”和“value”的 Cookie

值。

delete_cookie() 和 delete_all_cookies() 方法的使用也很简单,前者通过 name 删除一个

指定的 Cookie,后者直接删除浏览器中的所有 Cookies。

4.9.窗口截图

自动化测试用例是由程序执行的,因此有时候打印的错误信息不够直观。如果在脚本

执行出错时能够对当前窗口进行截图并保存,那么通过截图就可以非常直观地看到脚本出

错的原因。WebDriver 提供了截图函数 save_screenshot (),可用来截取当前窗口。

from time import sleep
from selenium import webdriver

driver = webdriver.Firefox()
driver.get('https://www.baidu.com/')
sleep(3)

# 截取当前窗口,指定截图图片的保存位置
driver.save_screenshot("D:/baidu_img.png")

WebDriver 建议使用 png 作为图片的后缀名。脚本运行完成后,会在D盘根目录下生成 baidu_img.png 图片

4.10.滑块操作

滑块作为安全验证机制的一种,经常在登录或者注册时涉及。但是在自动化测试时,需要想办法用代码的方式来处理滑块。下面以携程网的注册页面为例来演示如何操作滑块。网站 URL 是“https://passport.ctrip.com/user/reg/home”,代码实现要遵循的流程如下:

  1. 打开携程网注册页面 https://passport.ctrip.com/user/reg/home

  1. 在“携程用户注册协议和隐私政策”处弹出窗,单击“同意并继续”按钮

  1. 在验证手机步骤显示“滑块验证”功能。需要用代码的方式来拖曳滑块到最右侧。

Selenium 中对滑块的操作基本是采用元素拖曳的方式,而这种方式需要用到 Selenium 的Actionchains 功能模块。先分别求出滑块按钮和滑块区域的长度和宽度。

滑块按钮的元素如下:

滑块区域的元素如下:

实现代码如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from time import sleep

driver = webdriver.Firefox()
driver.get('https://passport.ctrip.com/user/reg/home')
sleep(3)
# 通过xpath定位‘同意并继续’并点击
driver.find_element(By.XPATH, "//div/div/a[@class='reg_btn reg_agree']").click()
# 以下代码的功能是获取滑块元素
sour = driver.find_element(By.CLASS_NAME, 'cpt-drop-btn')
print( sour.size['width'])
print(sour.size['height'])
# 以下代码的功能是获取滑块区域元素
ele = driver.find_element(By.CLASS_NAME, 'cpt-bg-bar')
print( ele.size['width'])
print(ele.size['height'])

在以上代码运行后,控制台分别打印这两个元素的长度与宽度。

说明滑块按钮和滑块区域的高度都是 40px,而它们的宽度分别是 40px 和 268px。

下面来实现执行滑块的操作,如注册业务分析中提到的那样,执行滑块的拖曳操作需要使

用到功能模块 ActionChains 的 drag_and_drop_by_offset 方法。方法用法如下:

完整的演示代码如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from time import sleep

driver = webdriver.Firefox()
driver.get('https://passport.ctrip.com/user/reg/home')
sleep(2)
# 通过xpath定位‘同意并继续’并点击
driver.find_element(By.XPATH, "//div/div/a[@class='reg_btn reg_agree']").click()
# 以下代码的功能是获取滑块元素
sour = driver.find_element(By.CLASS_NAME, 'cpt-drop-btn')
# 以下代码的功能是获取滑块区域元素
ele = driver.find_element(By.CLASS_NAME, 'cpt-bg-bar')
# 拖动滑块
x_width = sour.size['width'] + ele.size['width']
y_height = ele.size['height']
sleep(2)
ActionChains(driver).drag_and_drop_by_offset(sour, x_width, y_height).perform()

这样我们就学习完大部分Selenium 的元素操作方法了,读者可以掌握 Selenium 的常用方法,包括熟悉每种方法使用的场景或者前提条件。这里面的方法想要熟练掌握还是要多多练习,可以找个项目或需求文档。读者觉得本篇文章写得不错可以点赞收藏,一键三连哟~你们的支持就是我写博客的最大动力!!!

猜你喜欢

转载自blog.csdn.net/weixin_73348410/article/details/129152098