前文啰嗦
接口自动化介入时间确定:
答:越早越好,因为测试左移可以为测试侧腾出更充分的时间执行测试,效率提升的同时,以避免了日后项目更改或者delay而压缩测试的时间,从而忙的焦头烂额,还容易出现各种问题。
编写:只有api定义好了,就可以写代码
调试:模块开发完毕就可以调试,未开发完毕就可以采用mock模拟测试:https://blog.csdn.net/qq_40207262/article/details/129468858?spm=1001.2014.3001.5502
项目业务流程的自动化测试持续集成:pycharm+git+jenkins项目持续集成和自动化框架构建(CentOs7.9)
不再做过多赘述
通过python执行接口自动化总共分为三大步:
第一步:准备框架
第二步:写代码(本文是通过excel实现读写实现本地接口自动化测试,没有太多优化)
第三步:优化
正文:
框架基础介绍
框架结构:python+excel
,其他框架的实现可查看作者相关文章
- 基本工具:
python
pycharm- 下载地址:
- python官网(最新3.12):https://www.python.org/
- pycharm官网(社区版本即可):https://www.jetbrains.com.cn/pycharm/download/#section=windows
- fiddler:自行下载
- 下载地址:
- 搭建环境:
python安装:python安装教程超详细
pycharm安装:https://www.cnblogs.com/cal780-love/p/17192460.html - 接口数据来源:
接口文档
fiddler自己抓包
swagger在线接口文档 - 自动化测试框架选择:
pytest
+allure+jenkins+gitlab
+jira
(pytest框架写代码、allure工具生成报告、jenkins构建持续集成、gitlab仓库服务器类型)
本文只简单介绍本地代码通过excel获取数据并写入结果部分
- 创建项目下分类目录 6包4夹总计10个,一个项目基本够用
common
:公共的,baseApi.py
libs
:基本代码库包
test_case
:测试用例包
configs
:代码配置包
tools
:工具库包,用于读取文件信息代码
util
:常规方法包
datas
:测试数据/用例文件夹
logs
:测试日志文件夹
reports
:测试报告文件夹
docs
:项目相关文档文件夹
- 测试用例类型
xmind思维导图形式,常见手工测试比较常用
excel用例,自动化使用
yaml用例,自动化使用
json/word/数据库等
本文采用excel用例形式
- 脚本头模板展示信息编辑规范
- 打开pycharm-》文件-》设置-》编辑-》代码样式-》文件和代码模板-》python Script
录入:
- 打开pycharm-》文件-》设置-》编辑-》代码样式-》文件和代码模板-》python Script
# _*_ coding: UTF-8 _*_
#@File ${NAME}.py
#@Time ${DATE}{TIME}
#@Name xxxxxxxxxx
#@Email xxxx@163.com
#@Software ${PRODUCT_NAME}
-
- 三方库的安装整个接口自动化框架会用到的三方库:可以提前安装一下通过pip
pip install allure-pytest
pip install PyYMAL
pip install request
pip install xlwt
pip install xlrd
pip install xlutils
大概就这么多,其他临时用到可以临时安装
编写接口代码
列举一个项目实例操作,来自采用常见的项目框架为:基于sping boot
+vue.js
前端的前后端分离的架构。
百听不厌的登录接口编写
1、 **首先分析一个登录接口大概的思路步骤:
-
需要url->发送请求,请求方法,请求体(账户、密码);
-
返回响应信息(token、status)
- 新建python文件:命名
login.py
,编写在*libs*基础代码库包中
- 新建python文件:命名
-
- 数据获取:开发的接口文档或者fiddler抓包
以58同城登录为例抓包
fiddler抓包验证:
- 数据获取:开发的接口文档或者fiddler抓包
-
基本请求接口
-
- 正常通过手动加密密码输入的情况下,接口通了
但是登录密码加密了,这里就引入加密的概念:
- 正常通过手动加密密码输入的情况下,接口通了
-
1、Java常用加密方式
Base64加密算法(编码方式)
MD5加密(消息摘要算法,验证信息完整性)
对称加密算法
非对称加密算法
数字签名算法
数字证书 -
2、应用场景
- 1、 Base64应用场景:图片转码(应用于邮件,img标签,http加密)
- 2、 MD5应用场景:密码加密、imei加密、文件校验
- 3、非对称加密:电商订单付款、银行相关业务
登录密码采用MD5加密:
import hashlib
#MD5加密
def get_md5(psw):
indata = hashlib.md5() #实例化对象
indata.update(psw.encode('utf-8')) #加密操作
# 调用hexdigest方法,获取加密结果,hexdigest是一个十六进制的字符串值。
print(indata.hexdigest()) #默认32位小写加密数据
print((indata.hexdigest()).lower()) #输出32位小写加密数据
print((indata.hexdigest()).upper()) #输出32位大写加密数据
print((indata.hexdigest())[8:-8].lower()) #输出16位小写加密数据
print((indata.hexdigest())[8:-8].upper()) #输出16位大写加密数据
if __name__ == '__main__':
get_md5('123456')
- 登录接口自动化还需要加入MD5加密的代码
上述固定写法
加上MD5加密方法后的登录接口脚本:
:indata:登录的参数,根据用例详情可知,是json格式的键值对{"username":" xxx","psw":"xxx"},所以关联MD5加密方法处理为: indata[psw]=get_md5(indata['psw])
将加密方法移到utils
公共包后,调整调用get_md5
方法:
-
返回的
token
的处理 -
- 以便后续模块关联使用
:根据响应结果报文中提取到token值:return resp.json()['data']['token']
- 以便后续模块关联使用
-
处理测试用例数据
- 采用excel测试用例自动化流程:
- 1、读取excel数据关键列数据(ID/path/body/response列等)
- 2、把数据关联到代码中
- 3、实际结果和预期结果对比,结果写入excel测试用例实际列
-
-
- 用例表头格式:
读取excel表语法:在tools
包下新建.py文件“getExcelData.py
”
- 用例表头格式:
-
- 补充下表基础知识:
Book(class)
:由xlrd.open_work(“example.xls”)返回
Sheet(class)
由Book object相关方法返回
sheets
: sheet列表
sheet_names
: sheet名称列表
Book.sheet_by_name(sheet_name)
: 按名称提取sheet
Book.sheet_by_index(sheetx)
: 按序号提取sheet
nrows
: 行数
ncols
: 列数
cell(rowx,colx)
: 第rows行colx列的单元格(行和列定位)
cell_type(rowx,colx)
: 数据类型(行和列定位)
cell_value(rows,colx)
: 单元格数值(行和列定位)
col(colx)
: 第colx列所有单元格组成的列表
col_types(colx,start_rowx=0,end_rowx=None)
: 第colx列指定单元格数值类型组成的列表
col_values(colx,start_rowx=0,end_rowx=None)
: 第colx列指定单元格数值组成的列表
读取表格库有pandas / openpyxl / xlrd
我们选择xlrd
,因为它可以保留表格原始格式,方便处理
表格处理分两步:读取数据和写入数据两部分`
import xlrd # 导入读取excel模块
from xlutils.copy import copy # 导入copy模块
# 读取excel文档
def get_exceldata(sheetName, caseName): # 定义sheet名称,用例编号名称
loginlist = []
# 用例路径
excel_dir = '../datas/TestCases_V1.0.xls'
# 打开excel文档,读取数据保持表格格式:xlrd.open_workbook(path, formatting_info=True)
Book = xlrd.open_workbook(excel_dir, formatting_info=True)
# 获取指定sheet页并读取对应sheet表内容
Sheet = Book.sheet_by_name(sheetName)
# 遍历读取每个单元格需要的请求参数和预期响应数据,打包放入登录列表备用
indx = 0
for i in Sheet.col_values(0): # 第0列为case编号命名,col_value(0)第0列组成的列表
if caseName in i: # caseName在i所在的元素中(模糊匹配用例id编号Login00x)
reqdata = Sheet.cell_value(indx, 9) # sheet第9列为请求参数数据
respdata = Sheet.cell_value(indx, 11) # sheet11列为预期响应数据
reqdata=json.loads(reqdata) #将json转为字典格式,因为用例是json格式,需要与登录接口代码保持一致
respdata=json.loads(respdata) #将json转为字典格式,因为用例是json格式,需要与登录接口代码保持一致
loginlist.append((reqdata, respdata)) # 将传参和响应打包成一个元组放入登录备用列表
indx += 1 # 遍历一行加1
# pprint.pprint(loginlist)
return loginlist #返回请求传参和响应数据,列表形式
# 单独copy一个新的excel操作写入数据保证原始数据不变,导入copy模块
def edit_excel():
# 用例路径
excel_dir = '../datas/TestCases_V1.0.xls'
# 打开excel文档,读取数据保持表格格式:xlrd.open_workbook(path, formatting_info=True)
Book = xlrd.open_workbook(excel_dir, formatting_info=True)
# copy一份表对象,用法:新表=copy(旧表)
Booknew = copy(Book)
# 读取新表的sheet页:get_sheet(xxx),0表示excel簿第一个sheet页
Sheetnew = Booknew.get_sheet(0)
return Booknew, Sheetnew #返回新的excel表对象和Sheet信息
if __name__ == '__main__':
# pprint.pprint(get_exceldata('登录模块', 'Login'))
get_exceldata('登录模块', 'Login')
写入执行结果:
要操作excel,仅仅通过xlrd库或者xlwt库无法完成,需要引入xlutils库。为保证源数据,copy一份生成新的文档进行编辑。xlrd/xlwt/xlutils关系
新建文件testcase.py
,在test_case
包下:
# _*_ coding: UTF-8 _*_
# @File testpytest.py
# @Time 2023/3/16{TIME}
# @Name xxxxxxxx
# @Email xxxxxx@163.com
# @Software PyCharm
# 1、读取数据
from toolst.getexceldata import get_exceldata, edit_excel # 导入读取用例方法和副本文件
datalist = get_exceldata('登录模块', 'Login') # 准备好读取后列表形式的数据,格式:[({},{}),({},{}),({},{})]--列表(元组{字典})
Booknew, Sheetnew = edit_excel() # 格式为元组
# 2、关联数据
from libs.login import Login # 导入登录方法
for i in datalist: # i为元组 #遍历每一条用例,登录输入的账户密码数据。i在列表(),(),……以元组形式存在
act_resp = Login().login(i[0], False) # 实际值,调用登录方法:i[0],0指的是每个元组的第一个数据,即:字典形式的{}的账户密码数据,False是token布尔值为否
exp_resp = i[1]['msg'] # 期望值,i[1],即:字典形式的响应数据,通过msg对比结果是否一致没所以获取msg值
# 3、写结果
if act_resp['msg'] == exp_resp: # 对比实际值和期望值是否一致
print('PASS')
# sheet.write(行号,列号,值),list.index(i)通过i索引定位当前行,+1为实际对应行,因为从0开始算,写入数据
Sheetnew.write(datalist.index(i) + 1, 12, 'pass')
else:
print('failed')
Sheetnew.write(datalist.index(i) + 1, 12, 'failed')
Booknew.save('../datas/result_excel.xls') # 保存,book.save(路径)
最终会在../datas/result_excel.xls
路径下自动生成新的exccel文档并写入测试结果
打开查看: