ANTeam

V1

2022/03/07阅读:53主题:红绯

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 WebDriverWait

WebDriverWait(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()

分类:

后端

标签:

Python

作者介绍

ANTeam
V1