第一章、Web自动化入门
1、自动化
1.1 概念
由机器设备代替人工自动完成指定目标的过程
1.2 优点
- 减少人工劳动力
- 提高工作效率
- 产品规格统一标准
- 规模化(批量生产)
- 安全
2、自动化测试
2.1 概念
用程序代替人工去执行测试的过程
软件测试:对程序进行操作,以发现错误并验证其是否满足需求的过程
2.2 应用场景
解决-冒烟测试
冒烟测试:每个版本提测前,验证其是否达到可测标准
解决-回归测试
回归测试:项目在发新版本之后对项目之前的功能进行验证
解决-压力测试
压力测试:可以理解多用户同时操作软件,统计软件服务器处理多用户请求的能力
解决-兼容性测试
兼容性测试:不同浏览器(IE、Firefox、Chrome) 等等
提高测试效率,保证产品质量
2.3 正确认识
优点
- 较少时间内运行更多测试用例
- 自动化脚本可重复运行
- 减少人为的错误
- 克服手工测试的局限性
误区
- 自动化测试可以完全代替手工测试
- 自动化测试一定比手工测试厉害
- 自动化测试可以发掘更多BUG
- 自动化测试适用于所有功能
分类
- Web自动化测试
- 移动自动化测试
- 接口自动化测试
- 单元测试-自动化测试
3、Web自动化测试
概念:用程序代替人工去执行Web测试的过程
- 什么样的项目适用于Web自动化测试呢?
- 需求变动不频繁
- 项目周期长
- 项目需要回归测试/冒烟测试/兼容性测试/压力测试等
Web自动化测试所属分类:功能测试(黑盒)
4、Selenium
4.1 Web自动化工具简介
主流工具
- QTP:一个商业化功能测试工具,收费,支持Web/桌面自动化测试
- Selenium:开源Web自动化测试工具,主要做功能测试
- Robot Framework:一个基于python的可拓展关键字驱动的自动化测试框架
Selenium特点
- 开源软件:源代码开放可以根据需求增加工具的某些功能
- 跨平台:linux、windows、mac
- 支持多种浏览器:firefox、Chrome、IE、edge、Safari等
- 支持多种语言:Python、Java、C#、Javascript、PHP等
- 成熟稳定:已被Google、百度、腾讯等公司广泛使用
- 功能强大:能够实现商业工具的大部分功能,因为开源,可实现定制化功能
4.2 环境搭建
4.2.1 搭建步骤
基于python搭建环境:
1、Python开发环境(3.x以上)
2、安装Selenium包
3、安装浏览器
4、安装浏览器驱动
4.2.2 安装selenium包
- 安装:pip install selenium
- 验证:pip show selenium
- 卸载:pip uninstall selenium
4.2.3 安装浏览器驱动
驱动下载
Chrome下载地址:chromedriver.storage.googleapis.com/index.html
Firefox下载地址:
Edge下载地址:Microsoft Edge WebDriver | Microsoft Edge Developer
安装步骤
- 1、下载浏览器驱动,浏览器版本要与驱动版本一致
- 2、把驱动文件所在目录添加到Path环境变量中,或者直接放到python安装目录,因为python已添加到Path中
4.3 入门示例
4.3.1 需求
通过程序启动浏览器,并打开百度首页,暂停3秒,关闭浏览器
4.3.2 实现步骤
- 导包
- 创建浏览器驱动对象
- 打开百度首页
- 暂停3s
- 关闭驱动对象
# 1、导包
import time
from selenium import webdriver
# 2、创建浏览器驱动对象
driver = webdriver.Edge()
# 3、打开百度首页
driver.get("http://baidu.com")
# 4、暂停3s
time.sleep(3)
# 5、关闭驱动对象
driver.quit()
第二章、Selenium框架-基础入门
1 元素定位基础
1.1 为什么进行元素定位
让程序操作指定元素,就必须先定位到该元素
1.2 如何进行元素定位
元素定位是通过元素的信息或元素层级结构来定位元素的
# html页面由标签构成,标签基本格式如下:
<标签名 属性名1="属性值1" 属性名2="属性值2">文本</标签名>
示例:
<input id="username" type="text" name="username" placeholder="用户名" />
<div id="my_cart">
<span>我的购物车</span>
</div>
1.3 浏览器开发者工具
概念:浏览器开发者工具是给专业web应用和网站开发人员使用的工具。包含对HTML查看和编辑、Javascript控制台、网络状况监视等功能,是开发Javascript、CSS、HTML和Ajax的助手
作用:定位元素,查看元素信息
使用:浏览器按F12或右键检查,选中要查看的元素
1.4 元素定位方式
1.4.1 总体介绍
Selenium提供了八种元素定位方法:id、name、class_name、tag_name、link_text、partial_link_text、XPath、CSS
1.4.2 id定位
说明:id定位就是通过元素的id属性来定位属性,HTML规定id属性在整个HTML文档必须唯一
前提:元素有id属性
方法
element = driver.find_element_by_id(id)
1.4.3 name定位
说明:name定位就是根据元素name属性定位。HTML文档中name的属性值是可以重复的。
前提:元素有name属性
**方法 **
element = driver.find_element_by_name(name)
1.4.4 class_name定位
说明:class_name定位是根据元素class属性值来定位元素。HTML通过使用class来定义元素的样式
前提:元素有class属性
注意:如果class有多个属性值,只能使用其中一个
方法
element = driver.find_element_by_class_name(class_name)
1.4.5 tag_name定位
说明:tag_name定位是通过标签名来定位;
HTML本质是由不同tag组成,每一种标签一般在页面中存在多个,所以不方便精确定位,一般很少用
方法
element = driver.find_element_by_tag_name(tag_name)
# 如果存在多个相同标签,则返回符合条件的第一个
1.4.6 link_text定位
说明:link_text专门定位超链接元素(标签),通过超链接的文本内容来定位元素
**方法 **
element = driver.find_element_by_link_text(link_text)
# link_text:为超链接的全部文本内容
1.4.7 partial_link_text定位
说明:partial_link_text是对link_text定位的补充, link_text使用全部文本内容匹配元素,而partial_link_text可以使用局部来匹配元素,也可以使用全部文本内容来匹配元素
**方法 **
element = driver.find_element_by_partial_link_text(partial_link_text)
# partial_link_text:可以传入a标签局部文本-能表达唯一性
1.5 定位一组元素
使用上述方法发现一些类似方法
方法
elements = driver.find_element_by_xxx("xxxxx")
作用:
1、查找定位所有符合条件的元素
2、返回值是一个列表
说明:列表数据格式的读取需要指定下标(下标从0开始)
2 元素定位-XPath/CSS
2.1 总体介绍
为什么要学习XPath/CSS定位
1、如果定位元素没有id、name、class属性,该如何定位?
2、如果通过name、class、tag_name无法定位到唯一的元素,该如何定位?
示例:<input type="submit" value="提交" /input>
2.2 XPath定位
2.2.1 XPath是什么?
1.XPath即为XML Path的简称,它是一门在 XML 文档中查找元素信息的语言
2.HTML可以看做是XML的一种实现,所以Selenium用户可以使用这种强大的语言在web应用中定位元素
XML:一种标记语言,用于数据的存储和传递。后缀.xm结尾
<?xm1 version="1.0"encoding="UTF-8" ?>
<node>
<db id="db" desc="三条边的长度都一样">
<b1>3</b1>
<b2>3</b2>
<b3>3</b3>
<expect>等边三角形</expect>
</db>
<dy>
<b1>4</b1>
<b2>4</b2>
<b3>5</b3>
<expect>等腰三角形</expect>
</dy>
</node>
2.2.2 XPath定位方式
2.2.2.1 总体介绍
四种定位方式
1、路径-定位
2、利用元素属性-定位
3、属性与逻辑结合-定位
4、层级与属性结合-定位
方法
element = driver.find_element_by_xpath(xpath)
2.2.2.2 路径
绝对路径:从最外层元素到指定元素之间所有经过元素层级的路径
1、绝对路径以/html根节点开始,使用/来分隔元素层级
如:/html/body/div/fieldset/p[1]/input
2、绝对路径对页面结构要求比较严格,不建议使用
相对路径:匹配任意层级的元素,不限制元素位置
1、相对路径以//开始
2、格式://input或者//*
2.2.2.3 利用元素属性
说明:通过使用元素属性信息来定位元素
格式://input[@id='userA']或者//*[@id='userA']
2.2.2.4 属性与逻辑结合
说明:解决元素之间相同属性重名问题
格式://*[@name='tel' and @class='tel']
2.2.2.5 层级与属性结合
说明:如果通过元素自身信息不发包
格式://*[@id='p1']/input
2.2.2.6 XPath拓展
//*[text()="xxx"]文本内容是xxx的元素
//*[contains(@attribute,'xxx')]属性中含有xxx的元素
//*[starts-with(@attribute,'xxx')]属性以xxx开头的元素
2.3 CSS定位
1、CSS是一种语言,用来描述HTML元素的显示样式
2、在CSS中,选择器是一种模式。用于选择需要添加样式的元素
3、Selenium中也可以使用这种选择器来定位元素
提示:
1、Selenium中推荐使用CSS定位,因为它比XPath定位速度快
2、CSS选择器语法强大,本文只说明几个在测试中常用的
2.3.1 CSS定位方式
2.3.1.1 总体介绍
常用定位方式
- id选择器
- class选择器
- 元素选择器
- 属性选择器
- 层级选择器
方法
element = driver.find_element_by_css_selector(css_selector)
2.3.1.2 id选择器
说明:根据元素id属性来选择
格式:#id
例如:#userA <选择id属性值未userA的元素>
2.3.1.3 class选择器
说明:根据元素class属性来选择
格式:.class
例如:.telA <选择class属性值为“telA”的所有元素>
2.3.1.3 class选择器
说明:根据元素class属性来选择
格式:.class
例如:.telA <选择class属性值为“telA”的所有元素>
2.3.1.4 元素选择器
说明:根据元素的标签名来选择
格式:element
例如:input <选择所有input元素>
2.3.1.5 属性选择器
说明:根据元素的属性名和值来选择
格式:[attribute=value] element[attribute=value]
例如:[type="password"] <选择type属性值为password的元素>
2.3.1.5 层级选择器
说明:根据元素的父子关系来选择
格式1:element1>element2 通过element1来定位element2,并且element2必须为element1的直接子元素
例如1:p[id='p1']>input <定位指定p元素下的直接子元素input>
格式2:element1 element2 通过e1ement1来定位element2,并且element2为element1的后代元索
例如2:p[id='p1']input <定位指定p元素下的后代元素input>
2.3.1.7 CSS拓展
input[type^='p'] type属性以p字母开头的元素
input[types='d'] type属性以d字母结束的元素
input[type*='w'] type属性包含w字母的元素
2.4 XPath和CSS对比
定位方式XPathCSS元素名//inputinputid//[@id='userA']#userAclass//[@class='telA'].telA属性
//[starts-with(@attribute,'x’)]
//[text()="x"]
//*[contains(@attribute,'x’)]
input[type^='x']
input[type$='x']
input[type*='x']
3、元素定位总结
3.1 元素定位分类汇总
1.id、name、class_name:为元素属性定位
2.tag_name:为元素标签名称
3.link_text、partial_link_text:为超链接定位(a标签)
4.XPath:为元素路径定位
5.CSS:为CSS选择器定位
3.2 另一种写法
**方法 **
方法:find_element(by=By.ID,value=None)
备注:需要两个参数,第一个参数为定位的类型由By提供,第二个参数为定位的具体方式
导包:from selenium.webdriver.common.by import By
示例
1. driver.find_element(By.CSS_SELECTOR, '#emailA').send_keys("[email protected]")
2.driver.find_element(By.XPATH, '//*[@id="emailA"]').send_keys('[email protected]')
3.driver.find_element(By.ID,"userA").send_keys("admin")
4.driver.find_element(By.NAME,"passwordA").send_keys("123456")
5.driver.find_element(By.CLASS_NAME, "telA").send_keys("13111111111")
6.driver.find_element(By.TAG_NAME,'input').send_keys("123")
7.driver.find_element(By.LINK_TEXT,'访问 新浪 网站').click()
8.driver.find_element(By.PARTIAL_LINK_TEXT,'访问').click()
4、元素操作
4.1 应用场景
1、需要让脚本模拟用户给指定元素输入值
2 、需要让脚本模拟人为删除元素的内容
3、需要让脚本模拟点击操作
4.2 方法
1、click() 单击元素
2、send_keys(value) 模拟输入
3、clear() 清除文本
5 浏览器操作
5.1 应用场景
脚本启动浏览器窗口大小默认不是全屏?
如何刷新页面?
怎样解决这些问题?
5.2 方法
1.maximize_window() 最大化浏览器窗口-->模拟浏览器最大化按钮
2.set_window_size(width,height) 设置浏览器窗口大小 -->设置浏览器宽、高(像素点)
3.set_window_position(x,y) 设置浏览器窗口位置-->设置浏览器位置
4.back() 后退-->模拟浏览器后退按钮
5.forward() 前进--> 模拟浏览器前进按钮
6.refresh() 刷新--> 模拟浏览器F5刷新
7.close() 关闭当前窗口 -->模拟点击浏览器关闭按钮
8.quit() 关闭浏览器驱动对象 -->关闭所有程序启动的窗口
9.title 获取页面title
10. current_url 获取当前页面URL
5.3 示例
# 最大化浏览器
driver.maximize_window()
# 刷新
driver.refresh()
# 后退
driver.back()
#前进
driver.forward()
# 设置浏览器大小
driver.set_window_size(300,300)
# 设置浏览器位置
driver.set_window_position(300,200)
#关闭浏览器单个窗口
driver.close()
# 关闭浏览器所有窗口
driver.quit()
# 获取title
title = driver.title
# 获取当前页面ur1
url= driver.current_url
6、获取元素信息
6.1 应用场景
1、如何获取元素的文本
2、如何获取元素属性值
3、如何让程序判断是否为可见状态
6.2 常用方法
1.size 返回元素大小
2.text 获取元素的文本
3. get_attribute("xxx") 获取属性值,传递的参数为元素的属性名
- is_displayed() 判断元素是否可见
5.is_enabled() 判断元素是否可用
6.is_selected() 判断元素是否选中,用来检查复选框或单选按钮是否被选中
提示:
size、text:为属性,调用时无括号:如:xxx.size
7、鼠标操作
7.1 鼠标操作是什么?
点击、右击、双击、悬停、拖拽等
7.2 应用场景
Web产品丰富的鼠标交互方式,作为Web自动化测试框架,需要应对这些鼠标操作场景
7.3 常用方法
说明:在Se1enium中将操作鼠标的方法封装在Actionchains类中
实例化对象:
action =ActionChains(driver)方法:
1.context_click(element) 右击 --> 模拟鼠标右键点击效果2.double_click(element) 双击 --> 模拟鼠标双击效果
3.drag_and_drop(source,target) 拖动-->模拟标拖动效果4.move_to_element(element) 悬停 -->模拟鼠标悬停效果
5.perform() 执行--> 此方法用来执行以上所有鼠标操作
为了更好的学习其他方法,我们先学习perform()执行方法,因为所有的方法都需要执行才能生效
7.4 鼠标执行-perform()
说明:在Actionchains类中所有提供的鼠标事件方法,在调用的时候所有的行为都存储在Actionchains对象中,而perform()方法就是真正去执行所有的鼠标事件
强调:必须调用perform()方法才能执行鼠标事件
7.5 鼠标右键-context_click()
说明:
对于点击鼠标右键,如果弹出的是浏览器默认的菜单,Se1enium没有提供操作菜单选项的方法;如果是自定义的右键菜单,则可以通过元素定位来操作菜单中的选项
7.6 鼠标双击-drag_and_drop()
说明:模拟鼠标拖动动作,选定拖动源元素释放到目标元素
**关键点分析 **
1.源元素 source = driver.find_element_by_id(xxx)
2.目标元素 target =driver.find_element_by_id(xxx)
3.调用方法 action.drag_and_drop(source,target).perform()
7.6 鼠标悬停-move_to_element()
说明:模拟鼠标悬停在指定的元素上
8、键盘操作
8.1 应用场景
如何实现复制/粘贴的操作?
说明:
1.模拟键盘上一些按键或组合键的输入,如:Ctrl+C,Ctrl+V
2.Selenium中把键盘按键封装在Keys类中
8.2 常用操作
导包:from selenium.webdriver.common.keys import Keys
1.send_keys(Keys.BACK_SPACE) 删除键(Backspace)
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)
7.send_keys(Keys.CONTROL,'c') 复制(Ctrl+C)提示:以上方法就不一个一个讲解了,因为调用方法都一样
9、元素等待
9.1 概念
定位元素时如果未找到,在指定时间内一直等待的过程
元素等待一共分为两种类型:1.隐式等待 2.显示等待
9.2 应用场景
由于一些原因,我们想找到的元素没有立刻出来,此时如果直接定位会报错,场景如下:
1、网络速度较慢
2、服务器处理请求速度慢
3、硬件配置原因
是否定位每个元素都需要元素等待
9.3 隐式等待
方法
隐式等待为全局设置(只需要设置一次,就会作用于所有元素)
#参数:
timeout:超时的时长,单位:秒
driver.implicitly_wait(timeout)
注意点
每个元素定位超时会报NoSuchElementException异常
9.3 显式等待
在Selenium中把显式等待的相关方法封装在WebDriverWait中
方法
#显式等待,为定位不同元素的超时时间设置不同的值
1、导包 from selenium.webdriver.support.wait import WebDriverwait
2、WebDriverWait(driver,timeout,poll_frequency=0.5)
(1)driver:浏览器驱动对象 (2)timeout:超时的时长,单位:秒 (3)poll_frequency:检测间隔时间,默认为0.5秒
3、调用方法:until(method):直到。。。时
(1)method:函数名称,该函数用来实现对元素的定位 (2)一般使用匿名函数来实现:lamda x:x.find_element_by_id("userA")
如:ele=WebDriverWait(driver,10,1).until(lamda x:x.find_element_by_id("userA"))
注意点
每个元素定位超时会报TimeoutException异常
9.5 隐式和显式区别
1、作用域:隐式为全局元素,显式等待为单个元素有效
2、使用方法:隐式等待直接通过驱动对象调用,而显式等待方法封装在WebDriverWait类中
3、达到最大超时时长后抛出的异常不同:隐式为NoSuchElementException,显式等待为TimeoutException
10、下拉框/弹出框/滚动条操作
10.1 下拉框
10.1.1 方法一
需求:使用'注册A.htm1’页面,完成对城市的下拉框的操作
1.选择'广州’
2.暂停2秒,选择'上海
3.暂停2秒,选择'北京
核心代码
driver.find_element_by_xpath("//[@id='selectA']/option[3]").click()
time.sleep(2)
driver.find_element_by_xpath("//[@id='selectA']/option[2]").click()
time.sleep(2)
driver.find_element_by_xpath("//*[@id='selectA']/option[1]").click()
10.1.2 方法二
说明:select类是selenium为操作select标签特殊封装的
实例化对象:
select=select(element)
e1ement:<se1ect>标签对应的元素,通过元素定位方式获取例如: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显示文本来定位
核心代码
select = Select (driver.find_element_by_id("selecta"))
select.select_by_index(2)
time.sleep(2)
select.select_by_value("sh")
time.sleep(2)
select.select_by_visible_text("北京")
10.2 弹出框
10.2.1 分类
网页中常见的弹出框有三种
1、alert 警告框
2、confirm 确认框
3、prompt 提示框
10.2.2 方法
说明:selenium对弹出框的处理,有专用的方法,且方法都一样*(alert,confirm,prompt)
1、获取弹出框对象
alert = driver.switich_to.alert
2、调用
alert.text 返回alert、confirm、prompt的文字信息
alert.accept() 接受对话框选项(确认)
alert.dismiss() 取消对话框选项(取消)
代码
#需求:打开A界面,完成以下弹出框操作
#1、点击alert按钮
#2、暂停2s,输入用户名admin
#1、
driver.find_element_by_id("alerta").click()
time.sleep(2)
alert = driver.switich_to.alert
print(alert.text)
time.sleep(2)
alert.accept()
#2、
time.sleep(2)
driver.find_element_by_id(""userA).send_keys("admin")
time.sleep(3)
driver.quit()
10.3 滚动条
应用场景:在html中,由于前端技术更新,很多网站内容都是动态加载的,如页面注册同意条款,需要滚动条到最底层才能点击“同意”
实现方式:selenium没有提供操作滚动条的方法,但是提供了操作JavaScript的方法,可以通过JS脚本来操作滚动条。
1、设置JS脚本操作滚动条
js = "window.scrollTo(0,1000)"
(0:左边距,1000:上边距 单位:像素px)
2、selenium调用执行JS脚本的方法
driver.execute_script(js)
** 代码:**
#需求:打开页面
driver.get("A.html")
#js1滚动到最底部
js1 = "winddow.scrollTo(0,10000)" #电脑显示器很难超过10000像素的长度
#js2滚动到最顶部
js2 = "window.scrollTo(0,0)"
#调用js1代码
time.sleep(2)
driver.execute(js1)
#调用js2代码
time.sleep(2)
driver.execute(js2)
time.sleep(3)
driver.quit()
11、frame切换
11.1 frame框架概念
HTML页面中的一种框架,在当前页面指定区域显示另一个区域的元素
形式一:
<frameset cols="25%,75%">
<frame src="A.html">
<frame src="B.html">
</frameset>
形式二:
<iframe name="iframe_a" scr="demo.html" wdith="200" height="200">
11.2 selenium切换frame方法
步骤:
1.driver.swtich_to.frame(frame_reference) 切换到指定frame
frame_reference:可以传frame框架的id,name,定位的frame元素
2.driver.switch_to.default_content() 恢复默认页面
必须回到默认页面才能进一步操作
例如frame框架中有A、B两个页面,切到A后,要先恢复默认才能再切到B
案例实战:注册实例页面有一个主注册页面,一个frame1-注册页面A,一个frame2-注册页面B,需要在主页面填入admin,A页面填入adminA,B页面填入adminB
import time
from selenium import webdriver
driver = webdriver.Edge()
driver.get("注册实例.html")
#1、填写主界面的用户名admin
time.sleep(2)
drver.find_element_by_id("userA").send_keys("admin")
#2、填写注册界面A的用户名adminA
time.sleep(2)
driver.switch_to.frame("idframe1") #切换到A页面,通过id
#driver.switch_to.frame("myframe1") #切换到A页面,通过name
#driver.switch_to.frame(driver.find_element_by_id("userA")) #切换到A页面,通过frame对象
driver.find_element_by_id("userA").send_keys(adminA)
#3、回到主界面
time.sleep(1)
driver.switch_to.default_content()
#4、填写注册界面B的用户名adminB
time.sleep(2)
driver.switch_to.frame("idframe2") #切换到A页面
driver.find_element_by_id("userA").send_keys(adminB)
time.sleep(3)
driver.quit()
12、多窗口切换
12.1 概念
窗口:类似浏览器的标签页,每个窗口对应一个标签页
为什么要切换窗口? 在html页面中,如果点击按钮或超链接跳转到了新的页面,有的会在新窗口打开页面
如果点击按钮或超链接在当前页面打开新页面,就不需要切换窗口
需求
打开A页面
1、在新的窗口打开新浪页面
2、在新浪页面搜索框输入“新浪搜索”
3、在A页面输入用户名"admin"
12.2 多窗口切换-方法
说明:在selenium中封装了获取当前窗口句柄,获取所有窗口句柄和切换到指定句柄的方法
句柄:英文handle,窗口的唯一识别码
方法:
1.driver.current_window_handle 获取当前窗口句柄 2.driver.window_handles 获取所有窗口句柄 3.driver.swtich_to.window(handle) 切换到指定句柄的窗口
对案例需求的解决方案:
1、打开A页面,获取A页面的窗口句柄
2、在A页面点击访问新浪网站后,获取所有窗口句柄
3、根据句柄切换到新浪窗口,对输入框输入“新浪搜索”
4、切换回A页面,输入用户名admin
** 代码:**
import time
from selenium import webdriver
driver = webdriver.Edge()
#因为网络问题可能加载不出来页面,定位不到元素,所以设置一个隐式等待10s
driver.imlicitly_wait(10)
#1、打开A页面,获取当前页面窗口句柄
driver.get("A页面.html")
print("当前页面窗口句柄:",driver.current_window_handle)
#2、在A页面点击新浪超链接,跳转到新浪网站,获取所有窗口句柄
driver.find_element_by_id("fw").click()
handles = driver.window_handles
print("获取所有窗口句柄:",handles)
#3、根据句柄,切换到新浪窗口,在搜索框中输入新浪搜索
driver.switch_to.window(handles[1])
time.sleep(2)
driver.find_element_by_class("inp-txt").clear()
time.sleep(2)
driver.find_element_by_class("inp-txt").send_keys("新浪搜索")
time.sleep(2)
#4、切回原来A页面,输入用户名admin
driver.switch_to.window(handles[0])
driver.find_element_by_id("userA").send_keys("admin")
time.sleep(3)
driver.quit()
13、窗口截图
13.1 概念
把当前操作的页面截图,截图保存至指定位置
为什么要窗口截图:
- 自动化脚本是由程序去执行的,因此有时打印的错误信息不明确
- 如果在执行出错的时候,对窗口进行截图保存了,那么就可以直观看出错误原因,定位错误
13.2 方法
说明:selenium中提供了截图方法,只需要调用即可
方法:driver.get_screenshot_as_file(imgpath)
imagpath:图片路径+名称
代码:
import time
from selenium import webdriver
driver = webdriver.Edge()
#1、打开A页面
driver.get("A页面.html")
driver.find_element_by_id("userA").send_keys("admin")
driver.sleep(2)
#driver.get_screenshot_as_file("./img/123.png") #目录需要提前创建好
#每次都是相同的文件名,会覆盖上一次的截图,因此可以进行优化
#使用时间格式化文件名,可以使截图保存文件名不同,不会覆盖之前保存的文件,更有效
imgpath = "./img/test_{}.png".format(time.strftime("%Y%m%d%H%M%S"))
driver.get_screenshot_as_file(imgpath)
time.sleep(3)
driver.quit()
14、验证码处理
14.1 概念
验证码:一种随机生成的信息(数字、字母、图片、算术题等),为了防止恶意请求行为,增加应用安全性
为什么要学习验证码处理: 在web应用中,大部分系统在用户登录注册时候都需要输入验证码,而自动化脚本也要面临处理验证码的问题。
14.2 常用方法:
1、去掉验证码(测试环境下采用)
2、设置万能验证码 (生产和测试环境下采用)
3、验证码识别技术(通过python-tesseract来识别图片验证码:识别率很难达到100%)
**4、(推荐方法)记录cookie **(服务器发送的身份信息,通过记录cookie进行跳过登录)
cookie:由web服务器产生,并且保存在浏览器上的小文本文件,它可以包含用户相关的信息
数据格式:键值对组成(Python中的字典)
产生:客户端请求服务器,如果服务器需要记录用户状态,就向客户端颁发一个cookie数据
cookie的使用:当浏览器再次请求该网站时,浏览器把请求的数据和cookie数据一起提交给服务器,服务器检查该cookie,以此辨认用户状态
应用场景:
- 实现会话跟踪,记录用户登录状态
- 实现记住密码和自动登录的功能
- 用户未登录状态下,记录购物车中的商品
**14.3 Selenium操作cookie **
方法
- 获取本地所有cookies
- 获取指定cookie
- 添加cookie
说明:selenium中提供了对cookie操作的相关方法
方法:
1、driver.get_cookies() 获取网站本地所有cookies
2、driver.get_cookie(name) 获取指定cookie
name为cookie键值对中的键名
3、driver.add_cookie(cookie_dict) 添加cookie
cookie_dict:一个字典对象,必选的内容包括:"name"和"value"
案例需求:使用cookie实现跳过百度的登录
1、手动登录百度,获取cookie
2、请求百度,并且带上cookie
步骤分析
BDUSS是登录百度之后的唯一身份凭证,拿到BDUSS就等于拿到了账号的控制权,通行贴吧,知道,文库。。。等主要产品
1、登录百度,抓取BDUSS
2、添加BDUSS的键值对
3、调用刷新的方法
** 代码**
import time
from selenium import webdriver
driver = webdriver.Edge()
#案例需求:使用cookie实现跳过百度的登录
#1、手动登录百度,获取cookie
#2、请求百度,并且带上cookie
#没有cookie的时候
driver.get("www.baidu.com")
#添加cookie操作
driver.add_cookie("name":"BDUSS","value":"VJWa05pMFI1NnZpaXdlcUhBZmJ-TXdQVmFaVHp5eGtpa1VnYVFEZVhYcHJBdVJtSUFBQUFBJCQAAAAAAQAAAAEAAAAfbSRqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGt1vGZrdbxmZ")
time.sleep(3)
#刷新,再次请求百度首页,验证是否带上身份信息
driver.refresh()
time.sleep(3)
driver.quit()
三、pytest框架
1、总体介绍
- 什么是框架:英文framework,为解决一类事情的功能整合
- 什么是pytest框架:第三方单元测试框架,一般用于做单元测试(unittest是自带单元测试框架)
- 为什么使用pytest:
- 能够组织多个用例的执行
- 提供丰富的断言方法
- 能够生成测试报告
2、安装、卸载与校验
安装:
pip install pytest -i https://pypi.tuna.tsinghua.edu.cn/simple
卸载:
pip uninstall pytest
校验:
pip list
运行:
命令行运行(推荐)
主函数运行
.表示成功
F表示失败
3、断言
什么是断言?
让程序代替人工判断测试脚本执行结果是否符合预期的结果
为什么要学习断言
- 自动化脚本一般是无人值守状态
- 我们不知道执行结果是否符合预期
- 我们需要让程序代替人工检测执行结果是否符合预期
- 这就需要用到断言
3.1 断言方法
assert xx 判断xx不为真
assert not xx 判断xx不为真
assert a in b 判断b包含a
assert a==b 判断a=b
assert a!=b 判断a不等于b
def add(x,y):
return x+y
class TestAssert:
def test_a(self):
assert 2 == add(1,1)
def test_b(self):
assert add(1,1) == 3
4、setup和teardown
- 前置setup初始化函数
- 后置teardown销毁函数
import time
def add(x,y):
return x+y
class TestAssert:
# 获取并打印开始时间,每个测试函数执行前会打印一次
def setup_method(self):
print("start-time",time.time())
# 获取并打印结束时间,每个测试函数执行前会打印一次
def teardown_method(self):
print("end-time",time.time())
def test_a(self):
assert 2 == add(1,1)
def test_b(self):
assert add(1,1) == 3
5、配置文件
步骤:
1、项目下新建scripts模块
2、测试脚本存放在scripts模块中
3、项目下新建pytest.ini配置文件
4、配置文件内容时,第一行为[pytest]
5、命令行运行时,会使用配置文件中的配置
** 应用场景**
使用配置文件,可以通过配置项来选择执行目录下的哪些测试模块
编码pytest.ini
[pytest]
adopts = -s
testpaths = ./scripts
python_files = test_*.py
python_classes = Test*
python_functions = test_*
6、测试报告插件
- 应用场景:自动化测试脚本最终执行是否通过,需要通过测试报告进行体现
- 安装:pip install pytest-html
- 使用:在配置文件命令行参数中,增加addopts = -s --html=report/report.html
- 生成步骤:命令行运行pytest;项目目录会出现report文件夹,里面有个html文件即测试报告
如图所示,即可打开测试报告
7、数据参数化
应用场景:
- 登录功能都是用户名/密码等输入,点击登录
- 但是登录等用户名和密码如果想测试多组值时,就要用到数据参数化,好处是使**代码更整洁,可读性更好 **
方法
# 数据参数化,装饰器需要放在需要传多组值的函数上
@pytest.mark.parametrize(argname,argvalues)
argname:参数名
argvalues:参数值,类型必须为可迭代,一般是一个list列表
单一参数
# 不使用参数化,输出用户名zhangsan和lisi
import pytest
class TestLogin:
def test_a(self):
print("zhangsan")
def test_b(self):
print("lisi")
# 使用数据参数化(单一参数),修改上述代码
@pytest.mark.paramtrize("name",["zhangsan","lisi"])
def test_c(self,name):
print(name)
多个参数
# 使用数据参数化(单一参数),修改上述代码
import pytest
class TestDemo:
# 需求:使用数据参数化(多个参数),分别打印两组账号和密码:zhangsan/111111和lisi/222222
@pytest.mark.parametrize(("username", "password"), [("zhangsan", "111111"), ("lisi","222222")])
def test_demo(self, username, password):
print(username + "------" + password)
# 使用元组可以传多个值,("zhangsan",111111)
# 使用字典参数化的话,变量名和变量值则更加清晰(推荐方法)
@pytest.mark.parametrize("dict",[{"username":"zhangsan","password":"111111"},
{"username":"lisi","password":"222222"}])
def test_demo1(self,dict):
print(dict)
版权归原作者 桃饱网会员啊 所有, 如有侵权,请联系我们删除。