Web UI自动化测试之Selenium工具篇

本文大纲截图:

 

一、自动化测试介绍

1、基本介绍

1.1 自动化

概念: 由机器设备代替人工自动完成指定目标的过程

优点:

  • 1)减少人工劳动力

  • 2)提高工作效率

  • 3)产品规格统一标准

  • 4)规模化(批量生产)

1.2 自动化测试

软件测试:校验系统是否满足规定的需求、弄清预期结果与实际结果之间的差别

软件自动化测试:让程序代替人工去验证系统功能的过程

应用场景:

  • 回归测试:项目在发新版本之后对项目之前的功能进行验证

  • 压力测试:可以理解多用户同时去操作软件,统计软件服务器处理多用户请求的能力

  • 兼容性测试:不同浏览器(IE、Firefox、Chrome)等等

优点:

  • 1)较少的时间内运行更多的测试用例;

  • 2)自动化脚本可重复运行;

  • 3)减少人为的错误;

  • 4)克服手工测试的局限性;

  • 5)提高测试效率,保证产品质量

误区:

  • 1)自动化测试可以完全替代手工测试;

  • 2)自动化测试一定比手工测试厉害;

  • 3)自动化测试可以发掘更多的BUG;

  • 4)自动化测试适用于所有功能

分类:UI自动化、接口自动化、性能测试、单元测试

UI自动化:Web端、移动端

Web端:

  • 什么Web项目适合做自动化测试?

    • 1.需求变动不频繁

    • 2.项目周期长

    • 3.项目需要回归测试

  • Web自动化测试在什么阶段开始?

    • 功能测试完毕(手工测试)

  • Web自动化测试所属分类——黑盒测试(功能测试)

    • 1)黑盒测试(功能测试)

    • 2)白盒测试(单元测试)

    • 3)灰盒测试(接口测试)

移动端:APP应用、小程序、H5页面

2、环境搭建

UI自动化基本环境包括:

  • Java JDK 环境

  • Python和PyCharm安装

  • Selenium WebDriver、浏览器驱动、UnitTest、Pytest、parameterized、json、Selenium Grid

  • MySQL

3、测试工具

  • QTP 是一个商业化的功能测试工具,收费,支持web,桌面自动化测试

  • Selenium 是一个开源的web自动化测试工具,免费,主要做功能测试

  • Robot Framework是一个基于Python可扩展地关键字驱动的测试自动化框架

4、测试流程

  • 1)整理需要进行自动化测试的用例

  • 2)搭建好自动化测试框架环境

  • 3)编写自动化测试用例脚本

  • 4)执行自动化测试用例脚本

  • 5)生成自动化测试报告

5、测试框架

  • Python + Selenium + UnitTest + 数据驱动 + 日志收集

  • PO 模式:封装思想

6、基本代码(假定的概念)

Web 自动化基本代码

""" Web 自动化基本代码 """
# 1、导入模块
from selenium import webdriver
from time import sleep# 2、实例化浏览器对象:类名()
# 实例化谷歌浏览器对象
# driver = webdriver.Chrome()
# 实例化火狐浏览器对象
driver = webdriver.Firefox()# 3、打开网页:必须包含协议头
driver.get('http://www.baidu.com')# 4、观察效果
sleep(6)# 5、关闭页面
driver.close()

二、Selenium工具

1、基本介绍

Selenium 是一个用于Web应用程序的自动化测试工具。

特点:

  • 开源:源代码开放可以根据需要来增加工具的某些功能

  • 跨平台:linux、windows、mac

  • 支持多语言:Python、Java、C#、JavaScript、Ruby、PHP等

  • 支持常见的浏览器:Firefox、Chrome、IE、Edge、Opera、Safari等

  • 成熟稳定

  • 功能强大

发展史:

Selenium 1.0:

组件:Selenium IDESelenium GridSelenium RC[核心组件]

  • Selenium IDE

    • 1)Firefox浏览器插件,可以录制用户的基本操作,生成测试用例

    • 2)测试用例可以在Firefox浏览器里回放

    • 3)测试用例可以转化成其它语言的自动化测试脚本

  • Selenium Grid

    • 允许 Selenium RC 针对规模庞大的测试案例集成;

    • 需要在不同环境中进行的测试案例集进行扩展

  • Selenium RC[核心组件]

    • 1)RC是 Remote Control 的缩写,它的功能就是用来模拟一个浏览器

    • 2)支持多平台、多浏览器及多种开发语言来编写测试用例

  • 缺点:

    • 1)不支持本机键盘和鼠标事件

    • 2)不支持同源策略XSS/HTTP(S)

    • 3)不支持弹出框,对话框(自签名证书和文件的上传、下载)

Selenium 2.0:

  • 组件:Selenium 1.0 + WebDriver[核心组件]

    • 注意:2.0 是过渡版本,主要是使用 WebDriver 替换 RC

  • 特点:

    • 1)基于调用 WebDriver API 来模拟用户操作

    • 2)WebDriver 的速度更快,因为它可以直接交互使用

    • 3)支持多种编程语言

Selenium 3.0:

组件:Selenium IDESelenium GridWebDriver[核心组件]

Selenium IDE:

  • 作用:负责录制、回放脚本,模拟用户对页面的真实操作

  • 安装:作为浏览器插件安装

  • Chrome插件扩展下载网址:https://www.extfans.com/

Selenium Grid:

  • 作用:用于分布式自动化测试,通过控制多台机器、多个浏览器并行执行测试用例,在测试用例比较多的情况下比较实用。

  • 安装:

    • 1)安装java的jre环境并配置环境变量(配置JDK运行环境)

    • 2)在不同的测试集群机上,分别安装不同类型的浏览器和相应的驱动。并配置好环境变量(将浏览器驱动driver配置进PATH变量中)

    • 3)jar包下载:selenium-server-standalone-XX.XX.jar 下载。在https://selenium-release.storage.googleapis.com/index.html找到适配的版本(与Python中安装selenium版本一致)并将其放到电脑的某一个目录下。

WebDriver[核心组件]:

  • 作用:提供 API 来操作浏览器,如:Chrome、FireFox、IE 等

  • 安装:

    • 1)安装 Python 环境(以及PyCharm编辑器<一种Python IDEIntegrated Development Environment,集成开发环境>)

    • 2)安装命令:pip install selenium

  • 使用:在Python中调用来写测试脚本,去操作Web端网页应用

  • 注意:3.0 版本下所有浏览器除了需要安装 Selenium 框架 以外,还需要安装对应的驱动程序

特点:

  • 1)去掉了对 Selenium RC 的支持

  • 2)全面支持 Java8

  • 3)支持macOS(Sierra or later),支持官方的 SafariDriver

  • 4)通过软件的 WebDriver Server,支持Edge浏览器

  • 5)支持IE9.0以上版本

  • 6)通过火狐官方的GeckoDriver来支持Firefox

2、环境安装

2.1 Python3 已安装

pip是一个通用的 Python 包管理工具,提供了对 Python 包的查找、下载、安装、卸载的功能。

2.2 安装 selenium

  • 安装命令:pip install selenium

  • 卸载命令:pip uninstall selenium

  • 查看命令:pip show selenium

2.3 安装浏览器驱动

下载浏览器驱动:

  • 各个驱动下载地址:http://www.seleniumhq.org/download/

  • 注意:浏览器的版本和驱动版本要一致!

火狐浏览器:

  • 1)Firefox 48 以上版本:selenium 3.x + Firefox驱动(geckodriver)

    • 火狐驱动下载地址:https://github.com/mozilla/geckodriver/releases

  • 2)Firefox 48 以下版本:selenium 2.x + 内置驱动

谷歌浏览器:

  • selenium 2.x/3.x + Chrome驱动(chromedriver)

  • 谷歌驱动下载地址:https://sites.google.com/a/chromium.org/chromedriver/downloads

Edge浏览器(了解):

  • selenium 3.x + Edge驱动(MicrosoftWebDriver)

  • Edge驱动下载地址:https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/

环境变量配置: 把驱动文件所在目录添加到Path环境变量中或者直接放到Python安装目录,因为Python已添加到Path中。

3、工作原理

  • 1)运行用python写好的selenium脚本,向web service中发送一个http请求;

  • 2)浏览器驱动中的web service会根据这个请求生成对应的js脚本。注意:相同的操作生成的js脚本在不同浏览器中会有所不同,因此不同的浏览器要有不同的驱动;

  • 3)js脚本驱动浏览器,完成selenium脚本中的各种操作,并返回给web service

  • 4)web service将结果通过http响应的形式返回给客户端。

4、基本代码

# 导包
from selenium import webdriver
import time# 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()
# Firefox浏览器:
driver = webdriver.Firefox()
# Edge浏览器:
driver = webdriver.Edge()# 打开Web页面
driver.get("http://www.baidu.com")# 暂停
time.sleep(3)# 关闭驱动对象
driver.quite()

5、Selenium API

5.1 元素定位

元素定位方法

  • 方法一:

# 导包
from selenium import webdriver#定位一个元素
# driver.find_element_by_xxx()driver.find_element_by_id()
driver.find_element_by_name()
driver.find_element_by_class_name()
driver.find_element_by_tag_name()
driver.find_element_by_link_text()
driver.find_element_by_partial_link_text()
driver.find_element_by_xpath()
driver.find_element_by_css_selector()# 定位一组元素
# driver.find_elements_by_xxx()driver.find_elements_by_id()
driver.find_elements_by_name()
driver.find_elements_by_class_name()
driver.find_elements_by_tag_name()
driver.find_elements_by_link_text()
driver.find_elements_by_partial_link_text()
driver.find_elements_by_xpath()
driver.find_elements_by_css_selector()

截图:

注意:

  • 1)元素定位方法如果带有 s,则执行结果返回的是列表类型数据,里面的数据就是多个元素对象

  • 2)通过列表下标(索引)的方式,取出目标元素,再进行操作。如:

    • elements = driver.find_elements_by_tag_name('input')

    • elements[1].send_keys('123456')

  • 3)如果调用完元素定位方法后,再点语法,提示的均为列表方法,则方法带了 s 。

  • 4)如果调用完元素定位方法后,再点语法,提示的均为元素方法,则方法不带 s 。

  • 方法二:

# 导包
from selenium.webdriver.common.by import By# find_element方法
# driver.find_element(By.xx, 'xxx')driver.find_element(By.ID, 'id值')
driver.find_element(By.NAME, 'name值')
driver.find_element(By.CLASS_NAME, 'class_name值')
driver.find_element(By.TAG_NAME, 'tag_name值')
driver.find_element(By.LINK_TEXT, 'link_text值')
driver.find_element(By.PARTIAL_LINK_TEXT, 'partial_link_text值')
driver.find_element(By.XPATH, 'xpath值')
driver.find_element(By.CSS_SELECTOR, 'css_selector值')
  • 应用场景:使用 PO 设计模式封装代码结构时需要使用 By方法

  • 注释:by方法 是 By方法的封装;或者 By方法 是 by方法的底层实现(原理);By方法和by方法可以同时使用

  • 封装:提取、给名字、扔代码、确认需不需要参数和返回值

元素定位方式

Selenium 提供了八种定位元素方式:

1)id

  • 特点:id定位 是通过元素的id属性来定位元素的;在整个HTML文档中 id 属性必须是唯一的。

  • 前提:元素有id属性

  • id定位方法:element = driver.find_element_by_id(id)

  • 案例:用户输入框的id为userA,用id定位该用户输入框,并输入admin

    • username = driver.find_element_by_id('userA')

    • username.send_keys('admin')

  • 过程:由浏览器去定位元素,由元素去输入信息

  • 说明:当目标元素存在 id属性值时,优先使用 id 方法定位元素

2)name

  • 特点:name定位是根据元素name属性来定位的;在HTML文档中 name 的属性值是可以重复的

  • 前提:定位元素时,尽量保证 使用的特征值 能够代表目标元素在当前页面内的唯一性

  • name 定位方法:element = driver.find_element_by_name(name)

  • 案例:element = driver.find_element_by_name('userA')

  • 说明:在页面内有多个元素的特征值是相同时,当定位元素的方法执行时,默认只会获取第一个符合要求的特征对应元素。

3)class_name

  • 特点:class_name定位是根据元素class属性值来定位元素;HTML通过使用class来定义元素的样式,class属性值可以有多个

  • 前提:元素有class属性

  • class_name定位方法:element = driver.find_element_by_class_name(class_name)

  • 案例:tel = driver.find_element_by_class_name('telA')

  • 注意:在使用 class_name 方法时,如果class有多个属性值,只能使用其中的一个;方法名是:class_name,但要找元素的 class 属性值。

4)tag_name

  • 特点:tag_name定位 是通过标签名来定位的;HTML本质就是由不同的tag组成,每一种标签一般在页面中存在多个,所以不方便进行精确定位,一般很少使用

  • tag_name定位方法:element = driver.find_element_by_tag_name(tag_name)

  • 案例:element = driver.find_element_by_tag_name('input')

  • 说明:如果存在多个相同的标签,则返回符合条件的第一个标签。

5)link_text

  • 特点:link_text定位 是专门用来定位 超链接元素(< a>标签</a >),通过超链接的文本内容来定位元素的

  • link_text定位方法:element = driver.find_element_by_link_text(link_text)

  • 案例:element = driver.find_element_by_link_text('访问 新浪 网站')

6)partial_link_text

  • 特点:partial_link_text定位 是对 link_text定位的补充。link_text使用全部文本内容匹配元素,而 partial_link_text可以使用局部来匹配元素,也可以使用全部文本匹配元素。

  • partial_link_text定位方法:element = driver.find_element_by_partial_link_text(partial_link_text)

  • 案例:element = driver.find_element_by_partial_link_text('访问 新浪')

  • 说明:partial_link_text:可以传入a标签局部文本且能表达唯一性

7)XPath

基本介绍:XPath即为 XML Path 的简称,它是一门在 XML 文档中查找元素信息的语言。HTML可以看做是XML的一种实现,所以 Selenium用户可以使用这种强大的语言在Web应用中定位元素。XML:一种标记语言,用于数据的存储和传递。后缀.xml结尾。

说明:无论哪一种 XPath 策略(方法),定位方法都是同一个,不同策略只决定方法的参数的写法:find_element_by_xpath('XPath策略')

XPath定位方法:element = driver.find_element_by_xpath(xpath)

XPath定位策略

1)路径-定位

  • 绝对路径:从最外层元素到指定元素之间所有经过元素层级的路径

  • 格式:

    • 1> 绝对路径以 /html 根节点开始,使用 / 来分隔元素层级;如:/html/body/div/fieldset/p[1]/input。注意:这里的p[1]是从1开始计数的,不是从0开始的。

    • 2> 绝对路径对页面结构要求比较严格,不建议使用

    • 3> 反着路径写,从目标元素往根节点 /html 推。如:element = driver.find_element_by_xpath('/html/body/div/fieldset/p[1]/input')

  • 相对路径:匹配任意层级的元素,不限制元素的位置

  • 格式:相对路径以 // 开始

    • 如://input 或者 //*

    • 举例:element = driver.find_element_by_xpath('//*[@id="passwordA"]')

    • 说明:使用相对路径时,需要注意方法参数的内外引号嵌套问题

2)利用元素属性-定位

  • 特点:通过使用元素的属性信息来定位元素

  • 格式:

    • 语法1://标签名[@属性名='属性值']

    • 语法2://* [@属性名='属性值'];说明:// 表示任意层级;* 表示任意标签名;如://input[@id='userA'] 或者 //*[@id='userA']

  • 说明:

    • 1> 利用元素属性策略:该方法可以使用目标元素的任意一个属性和属性值,但需要保证唯一性(目标元素的有些属性和属性值,可能存在多个相同的特征的元素);

    • 2> 使用 XPath策略,需要在浏览器工具中根据策略语法,组装策略值,并验证后再写到代码中;

    • 3> 与class_name定位方法不同的是:如果使用具有多个值的 class 属性,则需要传入全部的属性值。

3)属性与逻辑结合-定位

  • 特点:解决元素之间各相同属性重名问题。解决目标元素单个属性和属性值无法定位为一个元素的问题时使用

  • 格式://*[@属性1='属性值1' and @属性2='属性值2']

  • 例如://*[@name='tel' and @class='tel']

  • 说明:多个属性由 and 连接,每一个属性都要由@开头,可以根据需求使用更多属性

4)层级与属性结合-定位

  • 特点:如果通过元素自身的信息不方便直接定位到该元素,则可以先定位到其父级元素,然后再找到该元素。解决目标元素无法直接定位,可以考虑先定位其父层级或祖辈层级,再获取目标元素。

  • 场景:通过父层级确定元素的页面位置,再通过拼接找到目标元素

  • 格式:父层级定位策略/目标元素定位策略

  • 例如://*[@id='p1']/input

  • 扩展:祖辈与后代元素关系定位的实现

  • 格式:祖辈层级定位策略//目标元素定位策略

  • 例如://form//*[@id='userA']

  • 说明:XPath 祖辈和后代关系 只需要使用 // 连接祖辈和后代元素即可。开发用的比较多。

XPath-延伸(动态属性):

动态属性: 要定位的元素的属性是动态的,即每次打开页面,这个元素的id或者class等元素属性是动态生成的

怎么辨别动态属性: 一般看到元素属性里有拼接一串数字的,就很有可能是动态的。想要分辨,刷新一下浏览器再看该元素,属性值中的数字串改变了,即是动态属性了。

  • 1)//*[text()='xxx']

    • 含义:文本内容是xxx的元素 – //*[test()='文本信息'];通过文本信息定位目标元素(要求全部文本内容)

  • 2)//*[contains(@attribute, 'xxx')]

    • 含义:属性中含有xxx的元素

    • //*[contains(@属性名,'属性值的部分内容')];通过给定属性值的任意部分内容进行元素定位

  • 3)//*[starts-with(@attribute, 'xxx')]

    • 含义:属性以xxx开头的元素

    • //*[starts-with(@属性名,'属性值的开头部分内容')];通过给定属性值的开头部分内容进行元素定位

XPath中提供了三个方法来定位部分属性值:

  • driver.find_element_by_xpath ("//div[contains(@id, 'auto-id')]")

  • driver.find_element_by_xpath ("//div[starts-with(@id, 'auto-id')]")

  • driver.find_element_by_xpath ("//div[ends-with(@id, 'auto-id)]")

  • 说明:

    • contains(a, b) 如果a中含有字符串b,则返回true,否则返回false

    • starts-with(a, b) 如果a是以字符串b开头,返回true,否则返回false

    • ends-with(a, b) 如果a是以字符串b结尾,返回true,否则返回false

8)CSS

基本介绍:

  • 1> CSS(Cascading Style Sheets)是一种语言,它用来描述HTML元素的显示样式;

  • 2> 在CSS中,选择器是一种模式,用于选择需要添加样式的元素;

  • 3> 在Selenium中也可以使用这种选择器来定位元素。

  • 提示:在Selenium中推荐使用CSS定位,因为它比XPath定位速度要快;CSS选择器语法非常强大,在这里我们只学习在测试中常用的几个

CSS定位方法:element = driver.find_element_by_css_selector(css_selector)

CSS定位常用策略

1)id选择器

  • 说明:根据元素id属性来选择,符号#

  • 格式:#id属性值

  • 例如:#userA;选择id属性值为userA的元素

2)class选择器

  • 说明:根据元素class属性来选择,符号.

  • 格式:.class属性值

  • 例如:.telA;选择class属性值为telA的所有元素

3)元素选择器

  • 说明:根据元素的标签名选择

  • 格式:element

  • 例如:input;选择所有input元素

4)属性选择器

  • 说明:根据元素的属性名和值来选择

  • 格式:[attribute=value]element[attribute=value]

  • 例如:[type="password"];选择type属性值为password的元素

  • 注意:与class_name定位方法不同的是,如果使用具有多个值的class属性,则需要传入全部的属性值。这与XPath的用法是一致的。

5)层级选择器

  • 说明:根据元素的父子关系来选择

  • 格式1:element1>element2;通过element1来定位element2,并且element2必须为element1的直接子元素

    • 例如1:p[id='p1']>input;定位指定p元素下的直接子元素input

  • 格式2:element1 element2  通过element1来定位element2,并且element2为element1的后代元素

    • 例如2:p[id='p1'] input;定位指定p元素下的后代元素input

  • 注意:父子层级关系中也可以使用空格连接上下层级策略(>后面一定是子元素,如果不是直接子元素则不能用>)

CSS延伸:

  • 格式1:标签名[属性名^='属性值开头部分内容']

    • 含义:根据给出的属性值开头内容定位元素

    • 例如:input[type^='p'];type属性以p字母开头的元素

  • 格式2:标签名[属性名$='属性值结尾部分内容']

    • 含义:根据给出的属性值结尾内容定位元素

    • 例如:input [type$='d'];type属性以d字母结束的元素

  • 格式3:标签名[属性名*='属性值任意部分内容']

    • 含义:根据给出的属性值任意部分内容定位元素

    • 例如:input[type*='w'];type属性包含w字母的元素

  • 注意:标签名可以省略!

    • [属性名^='属性值开头部分内容']

    • [属性名$='属性值结尾部分内容']

    • [属性名*='属性值任意部分内容']

5.2 元素操作

元素操作原因:

  • 让脚本模拟用户给指定元素输入值

  • 让脚本模拟人为删除元素的内容

  • 让脚本模拟点击操作

元素常用操作方法:

1、click()

  • 含义:单击元素

  • 例如:element.click()

2、send_keys(value)

  • 含义:模拟输入

  • 例如:

    • username = driver.find_element_by_id('userA')

    • username.send_keys('admin')

3、clear()

  • 含义:清除文本

  • 例如:

    • username = driver.find_element_by_id('userA')

    • username.clear()

  • 说明:在实际操作中,一般对于输入框元素,都要先执行清空,再执行输入,避免操作错误。所以 send_keys()clear()一般成对操作,即:

    • 元素对象.clear()

    • 元素对象.send_keys()

  • 扩展:错误案例

    • username = driver.find_element_by_id('userA').send_keys('admin')

    • username.clear()

  • 正确写法:

    • username = driver.find_element_by_id('userA')

    • username.send_keys('admin')

    • username.clear()

元素信息常用获取方法:

1、size

  • 含义:返回元素大小

  • 场景:用于判断页面元素布局尺寸是否合理时使用

  • 格式:元素对象.size

  • 举例:

    • username = driver.find_element_by_id('userA')

    • username.size

2、text

  • 含义:获取元素的文本

  • 场景:用于切换页面后,对页面内容特定元素的文本信息的获取(用作断言使用)

  • 格式:元素对象.text

提示: sizetext:为属性,调用时无括号,如:xxx.size

3、get_attribute('xxx')

  • 含义:获取属性值,传递的参数为元素的属性名

  • 场景:有些情况下,需要获取目标元素的特定属性值作为判断依据或数据

  • 格式:元素对象.get_attribute('属性名')

4、is_displayed()

  • 含义:判断元素是否可见

  • 说明:该方法多用于对元素在页面内显示效果的判断时使用(元素不显示不意味着一定无法定位)

5、is_enabled()

  • 含义:判断元素是否可用

  • 说明:该方法多用于判断目标元素是否可以进行交互时使用,如,置灰状态,按钮是否可以点击,链接是否可以点击等

6、is_selected()

  • 含义:判断元素是否选中,用来检查复选框或单选框是否被选中

  • 场景:如购物车页面,不全选商品,不让结算

  • 扩展:判断条件

  • 选中的判断:

  • if check.is_selected():pass

  • 未选中的判断:

  • if not check.is_selected():pass

5.3 特殊元素操作

选择框操作选择框类型:

  • 单选框和多选框

    • 选中属性:checked

    • 置灰属性:disabled

    • 采用八大元素定位方法 来定位

  • 下拉框和复选框

    • 相同:采用 Select类 来操作

    • 不同:下拉框为单选;复选框可多选(按住Ctrl进行多选)

下拉框操作:

  • 概念:下拉框就是HTML中< select>元素

  • 操作:可以通过直接定位下拉框中的内容对应的元素,完成对下拉框元素的处理

  • 说明:

    • 1)如果页面内需要操作的下拉框元素有多个,需要根据目标下拉框,依次实例化下拉框选择对象

    • 2)根据具体需求,三种下拉框内容元素选择方法,任选其一即可。

Select类:

  • 说明:Select类是Selenium为操作select标签特殊封装的

# 导包
from selenium.webdriver.support.select import Select
# 实例化对象
select = Select(element)
  • 说明:element:< select>标签对应的元素,通过元素定位方式获取

  • 例如:driver.find_element_by_id('selectA')

操作方法:

  • 1)select_by_index(index):根据option索引来选择,从0开始

  • 2)select_by_value(value):根据option属性 value值来选择

  • 3)select_by_visible_text(text):根据option显示文本来选择

  • 4)deselect_by_index(index):根据选项的索引,去除 选中元素

  • 5)deselect_by_value(value):选项的value属性值, 去除 选中元素

  • 6)deselect_by_visible_text(text):根据选项的可见文本,去除 选中元素

  • 7)deselect_all():去除 选中所有元素

Select类实现步骤:

  • 1)导包 Select类:from selenium.webdriver.support.select import Select

  • 2)实例化 Select类:select=Select(driver.find_element_by_id('selectA'))

    • 说明:有几个下拉框就要实例化几次

  • 3)调用方法:

    • select.select_by_index(index)

    • select.select_by_value(value)

    • select.select_by_visible_text(text)

弹出框操作

  • 应用场景:页面操作过程中,一旦出现弹窗,如果不进行处理,则后续操作无法执行!Selenium中对处理弹出框的操作,有专用的处理方法,并且处理的方法都一样。

弹窗分类

  • 系统弹窗:JS 实现。网页中常用的弹出框有三种:警告框alert、 确认框confirm、提示框prompt

    • 以JS属性(如onclick)在行内加入JS代码;JS在HTML中实现方式:嵌入head标签内,如:< head>< style>...</style ></head >;外链方式;行内嵌入

  • 自定义弹窗:前端代码封装

    • 说明:由于自定义弹窗可以通过鼠标右键的检查选项获取元素信息,因此出现自定义弹窗时,直接定义目标元素并操作,移除弹窗即可

  • 注意:

    • 1)凡是通过 JS 实现的系统弹窗,都无法通过鼠标右键检查选项获取元素信息。

    • 2)切换系统弹窗处理方法步骤:

alert = driver.switch_to.alert
# 获取弹窗信息(可选):该步骤必须在处理弹窗操作之前
print('弹窗信息是:', alert.text) 
# 接受对话框选项
alert.accept()
# 取消对话框选项
alert.dismiss()  
  • 3)调用的方法上如果存在悬线,意为该方法已经过期,不推荐使用

弹出框处理步骤:

# 获取弹出框对象(切换到弹出框)
alert = driver.switch_to.alert
# 调用方法进行处理(返回alert/confirm/prompt中的文字信息)
alert.text
# 接受对话框选项
alert.accept()
# 取消对话框选项
alert.dismiss()

滚动条操作:

概念:一种可控制页面显示范围的组件

学习滚动条操作的原因:

  • 1)在HTML页面中,由于前端技术框架的原因,页面元素为动态显示,元素根据滚动条的下拉而被加载

  • 2)页面注册同意条款,需要滚动条到最底层,才能点击同意

js脚本操作

在Selenium中并没有直接提供操作滚动条的方法,但是它提供了可执行JavaScript脚本的方法,所以我们可以通过JavaScript脚本来达到操作滚动条的目的。

代码:

  • js = "window.scrollTo(0, 1000)"

  • driver.execute_script(js)

实现步骤:

# 设置JavaScript脚本控制滚动条(0:左边距;1000:上边距;单位:像素;说明:反向只需要将坐标归零即可)
js = "window.scrollTo(0, 1000)"
# selenium调用执行JavaScript脚本的方法
driver.execute_script(js)

frame切换操作:

概念:HTML页面中的一种框架,主要作用是在当前页面中指定区域显示另一页面元素。在Selenium中封装了如何切换frame框架的方法。

frame形式:

# 形式一:
<frameset cols="25%, 75%"><frame src="frame_a.htm"><frame src="frame_b.htm">
</frameset>
# 形式二:
<iframe name="iframe_a" src="demo_iframe.htm" width="200" height="200"></iframe>

frame切换方法:

# 切换到指定frame的方法
driver.switch_to.frame(frame_reference)
# 恢复默认页面方法
driver.switch_to.default_content()'''
frame_reference:可以为frame框架的name、id或者定位到的frame元素
# 括号中为frame的属性
1、driver.switch_to.frame('frame_name')
# 如果页面中只有一个frame,括号中则可以填写 1
2、driver.switch_to.frame(1)
# 如果页面中有多个frame,可以用这种标签索引形式
3、driver.switch_to.frame(driver.find_elements_by_tag_name("iframe")[0])
'''
  • 注意:

    • 1)如果元素信息可以获取,但是代码执行无法定位,则需要手动从目标元素对应的代码开始向上查找,看是否存在iframe标签。

    • 2)如果目标元素存在于frame中,就需要先执行切换frame操作,再定位元素

    • 3)切换frame传入的是能够代表frame元素唯一性的特征值

    • 4)frame不能直接切换frame,需要先切换会默认的页面,再进行frame切换(即如果连续切换多个frame,必须先回到默认页面,才能切换下一个frame)

多窗口切换操作:

在浏览器的一个生命周期内(开启到关闭),任意一个窗口都有唯一的一个句柄值,可以通过句柄值完成窗口切换操作。句柄:handle,窗口的唯一标识码。在Selenium中封装了获取当前窗口句柄、获取所有窗口句柄和切换到指定句柄窗口的方法。

注意: 如果还想重新操作原始页面,务必要完成窗口切换,回到原始页面才可以继续操作(即使是切换到新的窗口已经关闭,也要切换回原始页面)

方法:

  • 1)driver.current_window_handle:获取当前窗口句柄

  • 2)driver.window_handles:获取所有窗口句柄

  • 3)driver.switch_to.window(handle):切换指定句柄窗口

步骤:

# 获取所有窗口句柄(包括新窗口)
handles = driver.window_handles
# print(handles)
# print(type(handles))# 切换窗口(列表的 -1索引<即最后一个> 对应的值始终是 最新窗口的句柄值)
driver.switch_to.window(handles[-1])

代码:

# 获取所有窗口句柄(包括新窗口)
handles = driver.window_handles
# print(handles)
# print(type(handles))# 切换窗口(列表的 -1索引<即最后一个> 对应的值始终是 最新窗口的句柄值)
driver.switch_to.window(handles[-1])# 在新窗口中填写信息
driver.find_element_by_id('userA1').send_keys('admin1')
sleep(2)# 关闭新窗口(close()方法作用是:关闭当前页面)
driver.close()# 切换回原始窗口进行操作
driver.switch_to.window(handles[0])# 在原始窗口页面填写信息
driver.find_element_by_id('userA').send_keys('admin')
sleep(2)# 退出浏览器
driver.quit()

截图操作:

自动化脚本是由程序去执行的,因此有时打印的错误信息并不是十分明确,如果在执行出错的时候对当前窗口截图保存,那么通过图片就可以非常直观看到出错的原因。

应用场景:在自动化测试中,出现错误时,可以通过截图把当前操作的页面截图保存到指定位置,辅助判定分析错误原因。在Selenium中,提供了截图方法,我们只需要调用即可。

窗口截图的方法:

  • 方法:driver.get_screenshot_as_file(imgpath)

    • imgpath:图片保存路径

  • 扩展

    • 1).jpg格式虽然可以使用,但是会有使用警告,一般使用.png格式

    • 2)指定图片文件存放路径:保存到当前文件夹下:'./info.png';保存到特定文件夹下:'./image/info.png'(image文件夹需要手动创建,如果不存在则会报错)

    • 3)利用时间戳存放图片名称(可防止图片重名覆盖的问题)

方式一:
# 导包
import time
# 设置时间戳
now_time = time.strftime('%Y%m%d_%H%M%S')
# 将时间戳拼接到图片名上
driver.get_screenshot_as_file('./info_{}.png'.format(now_time))方式二:
# 导包
import time
driver.get_screenshot_as_file('./info_{}.png'.format(time.strftime('%Y%m%d_%H%M%S')))方式三:
# 导包
from time import sleep, strftime
driver.get_screenshot_as_file('./info_{}.png'.format(strftime('%Y%m%d_%H%M%S')))
  • 4)给元素截图

btn = driver.find_element_by_tag_name('button')
btn.screenshot('./btn.png')

验证码操作:

验证码:一种随机生成的信息(数字、字母、汉字、图片、算术题)等为了防止恶意的请求行为,增加应用的安全性)

原因:在Web应用中,大部分系统在用户登录注册的时候都要求输入验证码,而在设计自动化测试脚本时,就需要临时处理验证码的问题,否则无法继续执行后续测试。在Selenium中并没有对验证码处理的方法,在这里我们介绍一下针对验证码的几种常用处理方式。

验证码的处理方式

  • 1)去掉验证码(测试环境下-采用)

  • 2)设置万能验证码(生产环境和测试环境下-采用)

  • 3)验证码识别技术(通过Python-tesseract来识别图片类型验证码,但识别率很难达到100%)

  • 4)记录cookie(通过记录cookie进行跳过登录)

  • 提示:

    • 1)去掉验证码、设置万能验证码:都是开发来完成

    • 2)验证码识别技术:成功率不高,验证码种类繁多,不太适合

    • 3)记录cookie:比较实用

面试题:常见的验证码处理策略

  • 1)去掉验证码:测试环境下-采用

  • 2)设置万能验证码:生产环境和测试环境下-采用,必须注意保密不要外泄万能验证码

  • 3)验证码识别技术:通过Python-tesseract来识别图片类型验证码,但识别率很难达到100%)

  • 4)记录cookie:通过记录cookie进行跳过登录,不能对登录本身功能进行测试时使用

总结:

测试登录功能时,验证码处理策略:去掉验证码(测试环境下)、设置万能验证码(生产环境和测试环境)

不需要测试登录功能时,验证码处理策略:记录cookie进行跳过登录

Cookie操作:

Cookie概念:

  • 1)Cookie是由Web服务器生成的,并且保存在用户浏览器上的小文本文件,它可以包含用户相关的信息

  • 2)Cookie数据格式:键值对组成(Python中的字典)

  • 3)Cookie产生:客户端请求服务器,如果服务器需要记录该用户状态,就向客户端浏览器颁发一个Cookie数据

  • 4)Cookie使用:当浏览器再次请求该网站时,浏览器把请求的数据和Cookie数据一同提交给服务器,服务器检查该Cookie,以此来辨认用户状态

Cookie操作过程:

  • 1)Web Client 去发送 HTTP Request

  • 2)Web Server 回发 HTTP Response + Set-Cookie

  • 3)Web Client 再发请求 HTTP Request + Cookie

  • 4)Web Server 验证 Cookie 并再次响应 HTTP Response

Cookie绕过原理:

  • 1)客户端登录账号后,将登录状态相关的cookie信息发送给服务器保存;

  • 2)在发送请求,携带的cookie信息如果和服务器保留的一致,则服务器认为客户端为登录状态。

  • 应用场景:

    • 1)实现会话跟踪,记录用户登录状态

    • 2)实现记住密码和自动登录的功能

    • 3)用户未登录的状态下,记录购物车中的商品

  • 注意:

    • 1)本地浏览器中登录的账号,不能退出,否则 cookie信息过期,需要重新获取

    • 2)不同项目的能够进行登录功能绕过的cookie字段信息都不相同,具体名称需要询问开发(也可以自己利用排除法获取-登录前的所有cookies和登录后的所有cookies对比)

    • 3)利用 cookie 绕过登录,则不能对登录功能本身进行测试

    • 4)个别项目如果想要绕过登录,有可能需要添加多个 cookie 字段

Selenium操作Cookie方法:

  • 1)get_cookie(name):获取指定cookie;name:为cookie的名称

  • 2)get_cookies():获取本网站所有本地cookies

  • 3)add_cookie(cookie_dict):添加cookie;cookie_dict:一个字典对象,必选的键包括:'name' and 'value'

    • 如:{'name':'BDUSS', 'value':'xxx......xxx'}

Selenium操作Cookie步骤:

  • 1)打开网站,如百度,个人账号登录(不要使用地方账号登录),然后F12在Application中的Cookie中找到Name为BDUSS的相关信息:Name和Value,并将其整理为字典类型,即:{'name':'BDUSS', 'value':'xxx......xxx'}

  • 2)整理关键 cookie 信息为字典数据:cookie_value = {'name':'BDUSS', 'value':'xxx......xxx'};字典数据的 key和value名称 必须是 name 和 value!!!

  • 3)调用方法添加 cookie 信息:driver.add_cookie(cookie_value)

  • 4)刷新页面,发送 cookie信息给服务器进行验证:driver.refresh()

5.4 元素等待

元素等待:在定位元素时如果未找到,会在指定时间内一直等待的过程。

设置元素等待的原因:

  • 1)网络速度慢

  • 2)电脑配置低

  • 3)服务器处理请求慢

分类: 隐式等待、显式等待、强制等待

隐式等待: 定位元素时,如果能定位到元素则直接返回该元素,不触发等待;如果不能定位到该元素,则间隔一段时间后再去定位元素;如果在达到最大时长时还没有找到指定元素,则抛出元素不存在的异常 NoSuchElementException

  • 格式:driver.implicitly_wait(timeout)

  • 说明:

    • 1)timeout:为等待最大时长,单位:秒

    • 2)隐式等待为全局设置(只需要设置一次,就会作用于所有元素)

  • 注意:当隐式等待被激活时,虽然目标元素已经出现了,但是还是会由于当前页面内的其他元素的未加载完成而继续等待,进而增加代码的执行时长

  • 例如:driver.implicitly_wait(10)

显式等待: 定位指定元素时,如果能定位到元素则直接返回该元素,不触发等待;如果不能定位到该元素,则间隔一段时间后再去定位元素;如果在达到最大时长时还没有找到指定元素,则抛出超时异常 TimeoutException

  • 格式:WebDriverWait(driver, timeout, poll_frequency=0.5).until(lambda x: x.find_element_by_id("id值")

  • 说明:在Selenium中把显式等待的相关方法封装在WebDriverWait类中的

# 导包
from selenium.webdriver.support.wait import WebDriverWaitWebDriverWait(driver, timeout, poll_frequency=0.5)
  • 说明:

    • driver:浏览器驱动对象

    • timeout:超时的时长,单位:秒

    • poll_frequency:检测间隔时间,默认为0.5秒

  • 调用方法:until(method) # 直到…时

    • 1)method:函数名称,该函数用来实现对元素的定位

    • 2)一般使用匿名函数来实现:lambda x: x.find_element_by_id("userA")

    • 3)元素操作方法没有代码提示,需要手写

  • 例如:

    • element = WebDriverWait(driver, 10, 1).until(lambda x: x.find_element_by_id("userA"))

    • element.send_keys('admin')

强制等待:

  • 格式:time.sleep(timeout)

  • 说明:timeout为等待最大时长,单位:秒

  • 例子:

  • 方式一:

    • import time

    • time.sleep(3)

  • 方式二:

    • from time import sleep

    • sleep(3)

隐式等待和显式等待对比:

5.5 鼠标操作

原因:现在Web产品中存在丰富的鼠标交互方式,作为一个Web自动化测试框架,需要应对这些鼠标操作的应用场景。

常见的鼠标操作:点击、右击、双击、悬停、拖拽等;在Selenium中将操作鼠标的方法封装在ActionChains类中。

ActionChains类:

# 导包
from selenium import webdriver
from selenium.webdriver import ActionChains
# 实例化浏览器对象
driver = webdriver.Chrome()
# 实例化鼠标对象,并关联浏览器对象
action = ActionChains(driver)

鼠标常用操作方法:

1)context_click(element)

  • 右击->模拟鼠标右键点击效果

  • 说明:对于点击鼠标右键,如果弹出的是浏览器默认的菜单,Selenium没有提供操作菜单选项的方法。如果是自定义的右键菜单,则可以通过元素定位来操作菜单中的选项。

  • 格式:鼠标对象.context_click(element)

  • 如:action.context_click(element)

2)double_click(element)

  • 双击->模拟鼠标双击效果

  • 场景:左键双击去全选点击内容

  • 说明:使用键盘快捷键 Ctrl + A,也能实现全选

  • 格式:鼠标对象.double_click(element)

3)drag_and_drop(element)

  • 拖动->模拟鼠标拖动效果

  • 说明:需要传入 起始元素 和 目标元素

  • 场景:滑动验证

  • 格式:鼠标对象.drag_and_drop(el1,el2)

4)move_to_element(element)

  • 悬停->模拟鼠标悬停效果

  • 说明:该方法在实际应用中,处理悬停鼠标才会出现的菜单时使用

  • 注意:该方法执行时,不要动鼠标!

  • 格式:鼠标对象.move_to_element(element)

5)perform()

  • 执行->此方法用来执行以上所有鼠标操作

  • 格式:鼠标对象.perform()

  • 说明:在ActionChains类中所有提供的鼠标事件方法,在调用的时候所有的行为都存储在ActionChains对象中,perform()方法 是真正去执行所有的鼠标事件。

扩展:另一种鼠标操作的写法:(在其他编程语言中称为链式编程)

  • ActionChains(driver).move_to_element(btn).perform()

5.6 键盘操作

思考:如何模拟键盘上一些按键或者组合键的输入,如:Ctrl+CCtrl+V。Selenium中把键盘的按键都封装在Keys类中:

Keys类

# 导包
from selenium.webdriver.common.keys import Keys
# 实例化浏览器对象
driver = webdriver.Chrome()
# 定位元素 ID为userA
user = driver.find_element_by_id('userA')

键盘常用操作方法:

1)send_keys(Keys.BACK_SPACE)

  • 删除键(Backspace)

  • 说明:BACK_SPACE 等价于 BACKSPACE

  • 格式:元素对象.send_keys(Keys.BACK_SPACE)

  • 如:user.send_keys(Keys.BACK_SPACE)

2)send_keys(Keys.SPACE)

  • 空格键(Space

3)send_keys(Keys.TAB)

  • 制表键(Tab

4)send_keys(Keys.ESCAPE)

  • 回退键(Esc

5)send_keys(Keys.ENTER)

  • 回车键(Enter

6)send_keys(Keys.CONTROL, 'a')

  • 全选(Ctrl+A

  • 说明:Mac环境下为:send_keys(Keys.COMMAND, 'a')

7)send_keys(Keys.CONTROL, 'c')

  • 复制(Ctrl+C

8)send_keys(Keys.CONTROL, 'v')

  • 粘贴(Ctrl+V

  • 说明:之所以能够复制完内容后,在任意位置处可以进行粘贴,是通过系统的剪切板实现的。

5.7 浏览器操作

思考:脚本启动浏览器窗口大小默认不是全屏?如何刷新页面?

浏览器常用操作方法

1)maximize_window()

  • 最大化浏览器窗口->模拟浏览器最大化按钮

  • 说明:如果能在打开页面时,全屏显示页面,就能尽最大可能加载更多的页面元素,提高可定位性。

2)set_window_size(width, height)

  • 设置浏览器窗口大小->设置浏览器宽、高(像素点)

  • 场景:查看页面是否可以自适应(Web和APP端切换)时使用

3)set_window_position(x, y)

  • 设置浏览器窗口位置->设置浏览器位置

  • 说明:Web和APP项目页面布局都是以屏幕的左上角作为坐标原点(0 ,0);页面内的内容是以自己的左上角与原点间的偏移量来布置位置的

4)back()

  • 后退->模拟浏览器后退按钮

5)forward()

  • 前进->模拟浏览器前进按钮

6)refresh()

  • 刷新->模拟浏览器F5刷新

  • 说明:刷新动作是重新向服务器发起当前页面的请求!

7)close()

  • 关闭当前窗口->模拟点击浏览器关闭按钮

  • 说明:在没有实现浏览器页面切换操作前,close()方法关闭的是原始页面!

  • 场景:关闭一个页面

8)quit()

  • 关闭浏览器驱动对象->关闭所有脚本程序启动的窗口

  • 场景:关闭所有页面

9)title

  • 获取页面title

  • 场景:可以用来做断言使用

10)current_url

  • 获取当前页面URL

  • 场景:可以用来做断言使用

总结:结合浏览器操作和隐式等待来完善Web UI自动化测试基础代码,如下:

# 导入模块
from time import sleep
from selenium import webdriver# 实例化浏览器对象
driver = webdriver.Chrome()
# 最大化浏览器
driver.maximize_window()
# 隐式等待
driver.implicitly_wait(30)
# 打开页面
driver.get('')
# 展示效果
sleep(3)
# 退出浏览器
driver.quit()

 最后:【可能给予你助力自动化测试的教程】

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走

面试资料

我们学习软件测试必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

上面是我整理的配套资源,这些资源对于软件测试的的朋友来说应该是最全面最完整的备战仓库,为了更好地整理每个模块,我也参考了很多网上的优质博文和项目,力求不漏掉每一个知识点,很多朋友靠着这些内容进行复习,拿到了BATJ等大厂的offer,这个仓库也已经帮助了很多的软件测试的学习者,希望也能帮助到你。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平