| 万叶集 |
|---|
| 隐约雷鸣,阴霾天空。 |
| 但盼风雨来,能留你在此。 |
前言:
✌ 作者简介:渴望力量的哈士奇 ✌,大家可以叫我 哈士奇 ,一位致力于 TFS 赋能的博主 ✌
CSDN博客专家认证、新星计划第三季全栈赛道 top_1 、华为云享专家、阿里云专家博主
如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步
人生格言:优于别人,并不高贵,真正的高贵应该是优于过去的自己。
如果感觉博主的文章还不错的话,还请关注、点赞、收藏三连支持一下博主哦
专栏系列(点击解锁) 学习路线指引 知识定位 Python全栈白皮书 零基础入门篇 以浅显易懂的方式轻松入门,让你彻底爱上Python的魅力。 语法进阶篇 主要围绕多线程编程、正则表达式学习、含贴近实战的项目练习 。 自动化办公篇 实现日常办公软件的自动化操作,节省时间、提高办公效率。 自动化测试实战篇 从实战的角度出发,先人一步,快速转型测试开发工程师。 数据库开发实战篇 更新中 爬虫入门与实战 更新中 数据分析篇 更新中 前端入门+flask 全栈篇 更新中 django+vue全栈篇 更新中 拓展-人工智能入门 更新中 网络安全之路 踩坑篇 记录学习及演练过程中遇到的坑,便于后来居上者 网安知识扫盲篇 三天打鱼,不深入了解原理,只会让你成为脚本小子。 vulhub靶场漏洞复现 让漏洞复现变得简单,让安全研究者更加专注于漏洞原理本身。 shell编程篇 不涉及linux基础,最终案例会偏向于安全加固方向。 [待完结] WEB漏洞攻防篇 2021年9月3日停止更新,转战先知社区等安全社区及小密圈 渗透工具使用集锦 2021年9月3日停止更新,转战先知社区等安全社区及小密圈 点点点工程师 测试神器 - Charles 软件测试数据包抓包分析神器 测试神器 - Fiddler 一文学会 fiddle ,学不会倒立吃翔,稀得! 测试神器 - Jmeter 不仅是性能测试神器,更可用于搭建轻量级接口自动化测试框架。 RobotFrameWork Python实现的自动化测试利器,该篇章仅介绍UI自动化部分。 Java实现UI自动化 文档写于2016年,Java实现的UI自动化,仍有借鉴意义。 MonkeyRunner 该工具目前的应用场景已不多,文档已删,为了排版好看才留着。
文章目录
- 自动化测试模型
- 实现在 PO模式 中应用数据驱动
- ddt(数据驱动)模块简介与常用的方法
- xlrd模块简介与常用的方法
- 利用 ddt 与 xlrd 实现数据驱动的实战案例演示
书承上一章节,我们现在做的自动化测试呢因为使用了 PO模式 ,就有了一套标准的设计模式与架构。但是缺少了在测试中所缺少的一个独特的东西,那就是测试数据。测试的过程中不会像开发那样编写一套代码那么容易,测试会有多种多养的场景与多种多样的数据。
就比如上一章节登录的Case,只是使用了正确的用户名与密码去登录;但是在测试的过程中,我们会使用到一些反例,比如账户被冻结的情况下,登录状态与提示是什么样的?密码错误的情况下又会是怎样的登录状态与提示等等等等。这样就会在同一个脚本中,产生多组的不同数据。
这个时候就要应用到数据驱动,或者说的更通俗一些,在其他的测试过程中也会叫做 参数化 。
所以接下来这一章节我们主要介绍两个点:
自动化测试模型
- 第一点:自动化测试模型介绍
- 第二点:在上一章节实现的 PO模式中应用数据驱动
- 线性测试:其实在最早期做自动化测试的时候(包括我自己也是),编写脚本大多数都是做一些线性的代码编写。就像我们之前写的最开始的没有任何框架辅助的自上而下的脚本一样,脚本文件都是独立编写测试内容等,任何一个脚本都可以拿出来独立单独执行,这是编写线性脚本的优点。但是缺点也很明显,那就是开发的重复性非常高、维护起来的也非常困难。这是最早期自动化测试脚本编写的模式,随着时代的进步与测试技术的发展,逐步出现了下面即将介绍的 "模块化驱动测试" 。
- 模块化驱动测试:上一章节介绍的 PO模式 其实就是一种模块化的方式;所谓的模块化驱动就是把一些重复的操作,单独成立公共模块。这样的模块设计有两种模式,一种是 PO模式 ,另外一种就是 分层模式。(这种 分层模式 就是把设计思维从页面模式中抽离出来做成一个业务化的思路,什么意思呢?其实就是可能会有一个业务流程横跨多个页面,但是只要它是一个固化的流程就OK了。) 这两种模块化设计的模式究竟哪一种更好,现在依然是众说纷纭,没有一个定性。不过我个人比较倾向于 PO模式 ,原因是我们做的自动化毕竟是页面的交互,考虑的编写的成本与维护性,所以我个人更倾向于 PO模式 。尽管有线性测试、模块化驱动测试的存在,但是它们的存在都没有解决我们在文章开头提到的数据的问题。
- 数据驱动模式:如果同一个场景存在多种数据要怎么办?所以这个时候诞生了 数据驱动测试 。这个模式的提出就是因为测试数据的多样性和变化性影响到了测试脚本的编写和方式,所以这个时候就需要将测试数据变为一个参数化的方式。这样不仅能够解决脚本重复的问题,还增加了脚本的复用性与可维护性,毕竟因测试数据修改了,就不要在修改代码了啊。
- 关键字驱动模式:这种模式在行业内、市场上,更多的是为平台、一些商业化工具来使用。它的方式其实就是将底层代码做一个高度封装(对于平台来说就再也看不到 “selenium” 的代码了,暴露出给用户的其实就是高度封装了底层代码的关键字。),用户使用这些关键字可以做出一些图形可视化的处理。从脚本编写上减少了代码的编写,从而降低了脚本的编写难度。
PS:在编写代码的时候大家会发现,从一个框架的代码来说,数据驱动模式要远比关键字驱动要好,所以这也是最后测试研发人员会转向数据驱动更多的原因。
实现在 PO模式 中应用数据驱动
OK,接下来我们就看一下,如何去完成一个标准化的数据驱动(其实就是读取excel表格内的参数)。
数据驱动使用到的第三方模块:
- ddt 模块:ddt 全称为 Data-Driven Tests ,即数据驱动测试,可以实现不同数据运行同一个测试用例(通过数据的不同来驱动测试结果的不同);正常情况下搭配unittest测试框架使用,实现数据驱动测试。
- xlrd 模块:python操作 excel 最常用的两个库之一,xlrd 是读 excel 的库, xlwt 是写 excel 的库 。
ddt(数据驱动)模块简介与常用的方法
ddt:全称 Data-Driven Tests ,即数据驱动测试。可以实现不同数据运行同一个测试用例(通过数据的不同来驱动测试结果的不同)。
ddt本质:其实就是装饰器,一组数据一个场景。
ddt的装饰器:模块包含了一个类的装饰器 ddt(@ddt) 和 三个方法的装饰器(@data、@unpack、@file_data)
@data:包含多个想要传给测试用例的参数,可以为列表、元组、字典等;
@file_data:会从json或yaml中加载数据;(注意,如果文件以”.yml”或者”.yaml”结尾,ddt会作为yaml类型处理,其他所有文件都会作为json文件处理。如txt文件)
@unpack:分割元素。(需要搭配unittest测试框架使用,实现数据驱动测试)
ps:通过使用数据驱动测试的方法,可以在需要验证多组数据测试场景中,使用外部数据源实现对输入输出与期望值的参数化,避免在测试中使用硬编码的数据,也就是测试数据和用例脚本代码分离。
使用 ddt 的意义:
1.代码复用率高:一个测试逻辑只需要写一次,可以多条测试数据复用,同时提高测试脚本的编写效率。
2.异常排查效率高:根据测试数据,每条数据生成一条测试用例,用例相互分离,一条失败的情况下不会影响其他测试用例。
3.代码可维护性高:简洁明了的测试框架,利于其他同事阅读,提高代码的可维护性。
ddt 的安装与导入
安装:pip install ddt
导入:import ddt 或者 from ddt import ddt, data, unpack
ddt 的使用:
- @ddt:装饰测试类
- @ddt 做的事情其实就等同于这句代码:TestCase = ddt(TestCase),把具体的类名传给ddt,告诉ddt是这个测试用例类要使用数据驱动。
- @data:装饰测试用例
- @data 做的事情就是把测试数据作为一个参数传递给测试用例,一个数据对应生成一条测试用例,如果data里面有多个数据那么就对应生成多条测试用例。如果data里放的类似是元组、列表等这样的序列类型的数据,data会把他们当成是一个整体,即一个测试数据。
- @unpack:装饰测试用例
- 如果想一次行传递多个参数给测试用例,需要自行在脚本中对数据进行分解或者使用 @unpack 分解数据。就好比传入的参数 case 是一个字典,字典中已经包含多个数据,直接用 key 获取对应的值即可。@unpack 的作用则是可以把这一类序列类型的数据拆分为多个,以多个参数传给测试用例,但测试用例也需要定义同等数量的参数来接收。
xlrd模块简介与常用的方法
xlrd 是用来从Excel中读写数据的,但我们通常只用它进行读操作,写操作会相对于专门写入的模块麻烦一些。其实,后面的 rd 可以看出是 reader 的缩小。
类比于 xlrd 的 reader,那么 xlwt 就相对于 writer,而且很纯正的一点就是它只能对 Excel 进行写操作。xlwt 和 xlrd 不光名字像,连很多函数和操作格式也是完全相同。下面让我们慢慢介绍。
安装与使用:
- pip install xlrd
- pip install xlwt
导入:
- import xlrd
- from xlrd import open_workbook
xlrd 常用的方法与功能
1、打开&关闭 excel 文件:
excelFile = xlrd.open_workbook(name) 先导入模块而后使用open_workbook()函数来读取指定的一个工作簿对象。这里的参数name是Excel文件的名字,一般使用的是相对路径的名字或者是绝对路径
excelFile.release_resources() 释放打开的表格
2、查看工作簿中所有sheet
- excelFile.sheet_names() 可以得到以列表形式嵌字符串的 excel 中所有的 sheet 的名称。
3、选择某一个工作表
table=df.sheets()[0] #列表是从0开始计数 table=df.sheet_by_index(0) table=df.sheet_by_name('name')
第一行代码是获取第一个工作表的意思,写法是根据内置的列表格式来选取的。
第二行代码顾名思义是通过索引获取第一个工作表,(index 索引,只不过对象换成了工作表)
第三行代码是通过表的名称选择工作表,如果工作表是有自己的名字的情况下,那么这个读取方式是最方便的。
4、获取表格的行数和列数
需要注意的是,这里不需要在函数后面加小括号,否则你可能debug时都头痛于错在哪。
row=table.nrows col=table.ncols
5、获取整行和整列的值
这里需要注意两个参数:num1和num2
table.row_values(num1) table.column_values(num2)
num1在row_values()中,指的是选取的行数是多少,例如我们选取第一行所有字段名称数据,那么这个num1就是0。
同理,column_values()的参数就是第几列的意思。
它出来的值是一个列表的形式。调用第一行代码,可以得到如下结果。
6、通过循环读取表格的所有行
在上文第5个知识点,我们实现了读取单行单列的数据,那么我们就用循环来将所有行打印出来。
for i in range(table.nrows): print (table.row_values(i))
7、获取单元格的值
代码很简单,有点像VBA
cell1=table.row(0)[0].value cell1=table.cell(0,0).value cell1=table.col(0)[0].value
第一行获取单元格值的方式是通过调取指定行数据进行筛选。
第二行是以二维的形式获取,即(第i行,第j列)形式。
第三行与第一行类似是通过列索引调用。
以上就是 xlrd 常用的方法 。
利用 ddt 与 xlrd 实现数据驱动的实战案例演示代码示例如下:
# coding:utf-8
import unittest
from time import sleep
from selenium import webdriver
from pages.home_page import HomePage
from pages.login_page import LoginPage
from pages.order_page import OrderPage
from ddt import ddt, data
from xlrd import open_workbook
'''
1、初始化 - 打开浏览器,设置浏览器大小
2、最终操作 - 关闭浏览器
3、用例部分 - 登录 - 测试数据集
'''
def GetExcelData():
"""
读取 excel 文件中的数据,本身和 TestTravel 测试类没关系,所以将其单独提取出来作为一个方法来使用
:return:
返回的是读取 excel 文件获取的测试数据集
"""
excelFile = open_workbook("data.xlsx") # 获取excel的工作簿
sheet = excelFile.sheet_by_index(0) # 获取 0 索引,第一个 sheet
rowNumber = sheet.nrows # 获取行数
dataList = [] # 定义空列表,用来临时存储 excel 中的测试数据集
for i in range(1, rowNumber): # 循环 excel 中的测试数据集,第一行内容是标题,所以我们从 1 索引 位开始获取测试数据
dataList.append(sheet.row_values(i))
return dataList # 返回 dataList
@ddt # 将测试类添加 ddt 装饰器,只有这样才可使用 ddt 所提供的数据驱动的功能
class TestTravel(unittest.TestCase):
def setUp(self): # 每个测试类在加载之前执行一次 setUpClass ,初始化方法
self.driver = webdriver.Chrome()
self.driver.maximize_window()
@data(*GetExcelData()) # * : 星号表示的意思是传入的参数不固定;即使用 GetExcelData() 方法传入的不固定参数
def test_a_order(self, data):
#初始化参数
username, password = tuple(data)
#初始化界面
home_page = HomePage(driver=self.driver, path="http://django.t.mukewang.com/#/")
login_page = LoginPage(driver=self.driver)
order_page = OrderPage(driver=self.driver)
#跳转登录
home_page.cross_to_login()
#登录
login_page.login(username, password)
sleep(2)
def tearDown(self):
self.driver.quit() # 彻底退出浏览器
if __name__ == '__main__':
unittest.main()
运行结果如下:



