- 框架简介
- 0.去年也写了一个测试框架,不过用例需要用代码来编写
- 1.第一步我先写一个环境配置文件
- 2.我写一个读取文件的类
- 方法测试:
- 3.环境配置总开关
- 4.写一个读取并处理配置文件信息的方法,使用我之前写的读取ymal的方法,把数据组合起来
- 5.初步封装requests方法,大部分接口都是这2个请求场景,针对公司接口格式封装
- 测试请求数据读取情况,读出来最终url,headers,data
- 6.yaml格式用例设计
- 测试读取,按照注释的格式来(设计时各种报错)
- 7.编写用例请求参数依赖方法(接口返回值提取和接口参数依赖),一个图截不下啊
- 搞个代码
- 测试
- 8.写一个读取用例数据的迭代器,可以判断是否需要执行,把请求参数表达式替换为具体的值,测试结果也截图了,但是这个方法只能读取单个文件的数据,后续处理多个文件。或者直接读取整个文件,还可以设置排除用例文件的方式运行
- 测试代码这里使用了生成器来一条一条的返回 生成器我之前写过一篇 [python生成器+pytest实现参数化](https://blog.csdn.net/aaaaaaaaanjjj/article/details/125218219)
- 9.设计处理断言列表的方法,这里我发现没有替换成功,i=i.replace(json_path,value)需要把值接住才可以
- 我把新列表(已经把json表达式替换成了值)遍历解析每一个断言元素时遇到 requires string as left operand, not int报错,大概意思就是
- 我在把这个12加上了单引号["'12' in '123'", 'ig == $.ig'], 然后后面的 'ig == $.ig'又出现了新问题,ig变量未定义,ig本来是‘ig’为字符串,但是被eval()函数处理后就会变成ig,是一个变量
- 于是我又给ig加上了引号
- 可是被替换为值的TheShy被eval()函数处理后又成了变量,我想着给"$.ig"加上引号,可是在jsonpath提取时出现了问题
- 打印下我的提取表达式提取表达式格式错误了,没取到值。发现我给之前的表达式加上了引号,我提取表达式是通过符号的索引位置到最后一个索引位置,现在我只能取倒数第二个索引位置
- 经过我的一顿操作,勉强解决问题,需要完善一下这个方法
- 方法完善,大改一波,测试结果,但是这里出现的问题,不得不修改用例模板断言列表的编写格式
- 代码
- 10.用例格式更改,还是使用原始列表格式写断言列表
- 11.pytest初次登场
- pytest.ini 配置pytest运行规则,要位于项目根目录下
- 我准备写一个主方法(结合之前写的参数处理,断言处理等方法)来运行从yaml里面读取的用例数据
- 运行pytest文件
- 12.pytest 获取用例参数
- 13.日志文件以前写过直接拿来用
- 14.实现get请求用例
- 发现个问题,我使用jsonpath时提取了非json的数据
- 解决方案:对返回结果进行了处理,后续还得考虑非json格式返回的问题
- 15.实现post请求和使用参数提取和参数依赖(好多坑,裂开)
- 处理用例执行返回断言结果
- 测试post请求时接口一直报错,查日志发现是传参格式的问题,之前在headers里面没有设置,补充一下
- 16.出现bug参数池保存完成后,下次读取时参数池重置
- 排除问题查看池子信息提取信息
- 忙活了半天,猜测估计是一个类方法在2个py页面使用时使用的参数池就不是一样的了,下一个使用的是重置的参数池
- 后来我把这个参数替换和参数提取放着了一个方法里面,这样就是共用一个参数池了
- 17.日志写到该写的地方(日志不要太复杂)
- 看下最终走进了的请求信息,判断接口失败或者成功的信息
- 这个方法又运行接口和处理参数提取
- 断言方法,通过接口返回结果和断言表达式列表来处理
- 主方法,加个用例开始执行,这个方法越简洁越好
- 日志的最终效果
- 18.使用allure(配置环境)
- 配置环境
- 18.allure简单封装并使用
- 使用记录用例标题
- 最终请求信息使用报告描述记录
- 这里记录下用例数据里面的描述信息
- 19.allure报告生成
- 运行启动文件,清空之前的文件,直接打开报告
- 20.allure生成本地报告(命令解析)
- pytest运行后产生了report目录和data目录然后开始运行os.system('allure generate report/data -o report/html --clean')直接生成html目录(里面包含了html文件)
- 21.发现bug(因为之前get请求方法里面没有写处理参数提取的,导致使用get请求没有到提取参数)
- 给get请求也加上参数提取处理,我看都加的话代码看起来好丑,直接封装为一个方法,直接用好一点
- 代码
- 22.使用一个用到框架比较多的用例(3个接口,我自己fastapi写的)
- 其中一个接口,另外几个看我写的fastapi的那个文章
- 测试结果
- 23.增加随机几位数字、字符,获取当前时间的方法,并写在用例里面使用
- 3个方法
- 在参数提取这里加上一个函数处理,但是一开始没有导入这几个方法报错了
- 导入方法,虽然是灰色的,但是在运行过程中会使用到
- 用例文件使用
- 最终运行结果,函数已经替换为了具体的时间,数字和字符
- 用例模板更新一下(加入函数使用)
- 24.多目录多文件用例处理,实现一个通过目录和文件排除一些用例文件的方法,来返回要运行测试用例文件
- 第一版(有bug)
- 最新读取文件的方法代码(有点bug)
- 第二版
- bug修复后代码
- 使用(细节)
- 字典拼接知识点
- 当前最终读取文件代码
- test_case文件ReadFile.read_case()方法的参数注意去掉
- 报告,最终运行了2个文件下的用例,但是现在没有标识用例出自于那个文件
''' 基于pytest+yaml+allure+requests搭建的接口自动化框架(提供测试接口基于fastapi) tool功能: __init__: 读取具体的环境配置信息给requests_使用 requests_请求接口:requests二次封装,自动获取headers和域名信息 read_file文件读取:读取目录下yaml文件,支持排除指定文件和目录,最终返回字典格式的用例数据 parameter_setting参数设置:提供参数池,支持接口返回参数提取保存和接口请求参数提取(解决参数依赖) log日志:保存运行日志记录 function函数:支持随机几位数的字符,数字和当前时间函数,直接在用例文件中使用 assert_断言操作:处理多个断言表达式,返回最终断言结果 case_test用例执行:处理从read_file读取出的原始用例数据,使用parameter_setting进行参数存储和提取,使用assert_进行断言,最后返回用例执行结果 allure_报告定制:allure.dynamic动态属性的简单封装 '''0.去年也写了一个测试框架,不过用例需要用代码来编写
基于pytest搭建接口自动化测试框架,提供源码
1.第一步我先写一个环境配置文件按自己公司环境配置,我这边只有测试和生产环境,配置协议,域名和headers。后续我只有提供地址和请求参数就可以发起接口访问
准备用于处理文件相关,现在只有读取yaml问的方法,后续准备写读取execl、execl和yaml用例数据转换,用例数据处理。
一开始我是想把环境这个参数放着请求时填写的,最后发现比较麻烦,一切以简单明了为好
截图+截图666
data_is_replace()判断数据需不需要替换,data有可能是空,因为一些接口不需要请求参数,或者不需要提取接口返回值
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
@time : 2022/6/14
@Author : LL
@File : parameter_setting.py
参数处理
'''
from jsonpath import jsonpath
class ParameterSetting:
# 参数存放和提取
access_value = {'b': 213, 'g': 21}
@classmethod
def data_is_replace(cls, data):
'''
:param data: 请求参数data和提取参数extract_key
:return: 返回参数是否需要被替换
'''
if data is None:
return False
for k, v in data.items():
if '$.' in v:
return True
return False
@classmethod
def parameter_setting(cls, data: dict, type='get'):
'''
:param data: 返回结果提取和参数依赖使用dict 例:{'bill': '$.bill'}
:param type: save :把数据存到参数池里面无返回,get读取参数池数据并返回新值
:return:
'''
if type == 'get':
# {'b': '$.b','g':'$.g'} 提取格式键+提取表达式
for k, v in data.items():
if '$.' in v:
v = jsonpath(cls.access_value, v)[0]
data[k] = v
print(f'最终返回参数:{data}')
return data
elif type == 'save':
# {'a':44,'a1':144} 键 + 明确的值
for k, v in data.items():
# 把data的键值添加到参数池里面
cls.access_value[k] = v
if __name__ == '__main__':
# 测试参数存储
ParameterSetting.parameter_setting({'a': 44, 'a1': 144}, 'save')
# 测试参数读取
ParameterSetting.parameter_setting({'b': '$.b', 'g': '$.g'})
print(f'最终的参数池{ParameterSetting.access_value}')
测试
8.写一个读取用例数据的迭代器,可以判断是否需要执行,把请求参数表达式替换为具体的值,测试结果也截图了,但是这个方法只能读取单个文件的数据,后续处理多个文件。或者直接读取整个文件,还可以设置排除用例文件的方式运行
测试代码这里使用了生成器来一条一条的返回 生成器我之前写过一篇 python生成器+pytest实现参数化
9.设计处理断言列表的方法,这里我发现没有替换成功,i=i.replace(json_path,value)需要把值接住才可以
我把新列表(已经把json表达式替换成了值)遍历解析每一个断言元素时遇到 requires string as left operand, not int报错,大概意思就是
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
@time : 2022/6/15
@Author : LL
@File : assert_.py
断言格式 ["1=='1'", "cc=='dad'", "12 in '123'", 'ig in $.lpl.ig']
'''
from jsonpath import jsonpath
class Assert:
@classmethod
def assert_response(cls, assert_list: list, api_response: dict):
new_assert_list = []
for i in assert_list:
if '$.' in i:
# 获取$的索引位置
wz = i.find('$')
# 切片出表达式
json_path = i[wz:len(i) - 1]
# 把表达式转换为值
value = jsonpath(api_response, json_path)
if not value:
print('表达式提取失败,请检查')
return False
value = value[0]
# 用值把表达式替换掉(注意这个需要用变量接住这个替换的新值)
i = i.replace(json_path, value)
new_assert_list.append(i)
print(f'断言新列表:{new_assert_list}')
#判断每个断言的成功或者失败
assert_result_list=[]
for i in new_assert_list:
assert_result = eval(i)
print(f'断言表达式{i},断言结果{assert_result}')
assert_result_list.append(assert_result)
#如果断言结果列表里面有一个失败,那就断言失败
if False in assert_result_list:
return False
return True
if __name__ == '__main__':
print(Assert.assert_response(["'12' in '123'", '"ig" == "$.ig"', '1==1'], {'id': 1, 'ig': 'TheShy'}))
10.用例格式更改,还是使用原始列表格式写断言列表
11.pytest初次登场
pytest.ini 配置pytest运行规则,要位于项目根目录下
testpaths = tool 设置运行用例文件位置
数据通过我写的生成器方法一条一条的读进来了,然后要处理他们
logging 学习最终版-配置的不同级别日志打印的颜色
14.实现get请求用例 发现个问题,我使用jsonpath时提取了非json的数据 解决方案:对返回结果进行了处理,后续还得考虑非json格式返回的问题 15.实现post请求和使用参数提取和参数依赖(好多坑,裂开)这个方法还是要简洁,不然断言失败时pytest的日志里面会带上这个方法的代码,不利于查看错误,我把用例请求和参数提取和参数依赖和断言写在了一个方法里面,这里只需要给一个用例数据就行了
之前参数替换我写在了文件读取里面
可以查看参数池情况,提取失败查找具体原因
allure报告文件,2.8版本,0积分下载(应该是免费把),我自己上传的资源
配置环境
这是allure.dynamic动态使用,不需要装饰器,装饰器不适应这种框架,这个动态的想放在哪里都行
配置下pytest运行命令保存报告
这个addopts =是配置pytest的运行命令
–alluredir ./report/data 是生成report目录和data目录,data里面存放的用例执行的相关数据
os.system(‘allure serve report/data’) 这个命令是处理data目录下的数据直接以服务器的形式启动报告,不生成文件,这个报告地址在公司局域网内都是可以打开的。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
@time : 2022/6/15
@Author : LL
@File : case.py
'''
from tool.allure_ import allure_description
from tool.assert_ import Assert
from tool.parameter_setting import ParameterSetting
from tool.request_ import Requests
from tool.log import logger
def replace_(extract_key,api_response):
'''参数提取处理'''
# 判断是否有参数提取
logger.info(f'提取参数字典{extract_key}')
if extract_key:
# 把表达式替换为具体的值
extract_value = ParameterSetting.extract_value(api_response, extract_key)
# 参数提取到参数池
ParameterSetting.parameter_setting(extract_value, 'save')
def case_assert_result(case_data):
'''
:param case_data: yaml读出来的用例数据
:return:
get请求暂时没有写参数依赖
'''
allure_description(case_data['remark'])
logger.info(f'用例原始数据:{case_data}')
if case_data['method'] == 'get':
api_response = Requests.get(case_data['path'])
extract_key = case_data['extract_key']
replace_(extract_key, api_response)
assert_result = Assert.assert_response(case_data['assert_expression'], api_response)
elif case_data['method'] == 'post':
'''参数替换和参数依赖操作必须在一个页面里面,不然页面切换参数池会重置为{}'''
# 判断是否需要替换请求参数
if ParameterSetting.data_is_replace(case_data['data']):
# 参数替换
data = ParameterSetting.parameter_setting(case_data['data'],'get')
data = case_data['data']
api_response = Requests.post(case_data['path'], data)
extract_key = case_data['extract_key']
replace_(extract_key,api_response)
assert_result = Assert.assert_response(case_data['assert_expression'], api_response)
else:
assert_result = False
case_title = case_data['case_title']
logger.info(f'-----"{case_title}"用例运行完成------')
return assert_result
22.使用一个用到框架比较多的用例(3个接口,我自己fastapi写的)
基于fastapi实现6个接口(token拦截, 2个业务流程,接口参数依赖校验)
用例文件 yaml文件
创建账单:
path: /create_bill
method: post
remark: 创建账单
is_run: True
data:
{
"create_month": "6月",
"create_name": "小江"
}
extract_key:
bill_no: $.bill_no
create_name: $.bill_info.create_name
assert_expression:
['"lj1314"=="$.bill_no"']
确认账单:
path: /affirm_bill
method: post
remark: 确认账单
is_run: True
data:
{
"affirm_name": "小江",
"bill_no":$.bill_no
}
extract_key:
affirm_name: $.bill_info.affirm_name
assert_expression:
['"小江"=="$.bill_info.affirm_name"']
核销账单:
path: /write_off_bill
method: post
remark: 核销账单
is_run: True
data:
{
"affirm_name": $.affirm_name,
"bill_no":$.bill_no,
"create_name":$.create_name
}
extract_key:
assert_expression:
['"小江"=="$.bill_info.affirm_name"','"小江"=="$.bill_info.create_name"',]
其中一个接口,另外几个看我写的fastapi的那个文章
测试结果
23.增加随机几位数字、字符,获取当前时间的方法,并写在用例里面使用
3个方法
在参数提取这里加上一个函数处理,但是一开始没有导入这几个方法报错了
导入方法,虽然是灰色的,但是在运行过程中会使用到
用例文件使用
最终运行结果,函数已经替换为了具体的时间,数字和字符
用例模板更新一下(加入函数使用)
24.多目录多文件用例处理,实现一个通过目录和文件排除一些用例文件的方法,来返回要运行测试用例文件
第一版(有bug)
这个是初级版本,直接返回case目录下的所有文件(最多支持2级目录)
最终版本
:param exclude_dir: 要排除的目录(二级目录)例子:ctms
:param exclude_file: 要排除的文件(case目录下所有文件)例子:case/ctms/test.yaml case/waybill.yaml
:return: 获取case下的所有用例文件列表,最多支持二级目录,通用排除文件返回最终要执行的用例文件
注意看我的目录结构
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
@time : 2022/6/10
@Author : LL
@File : read_file.py
'''
from pathlib import Path
import yaml
from tool.parameter_setting import ParameterSetting
import os
class ReadFile:
# 获取当前项目目录D:python2022pytest_api_2022.6.10
project_directory = str(Path(__file__).parent.parent) + '/'
@classmethod
def read_yaml(cls, path):
'''读取yaml文件'''
path = cls.project_directory + path
file = open(path, 'r', encoding='utf-8')
with file as doc:
content = yaml.load(doc, Loader=yaml.Loader)
return content
'''需要文件排除,文件筛选'''
@classmethod
def read_case(cls, path):
# 这是一个用例文件的情况 {"用例标题1":{"data":{},"path":'/ff'},"用例标题2":{"data":{},"path":'/ff'}}
case_data = cls.read_yaml(path)
for k, v in case_data.items():
# k为用例名称,v为用例数据
case_name = k
# 如果用例需要执行
if v['is_run'] == True:
# 把用例标题写进最终请求数据中
v['case_title'] = case_name
yield v
@classmethod
def file_execute_list(cls, exclude_file: list, exclude_dir: list):
'''
:param exclude_dir: 要排除的目录(二级目录)例子:ctms
:param exclude_file: 要排除的文件(case目录下所有文件)例子:case/ctms/test.yaml case/waybill.yaml
:return: 获取case下的所有用例文件列表,最多支持二级目录,通用排除文件返回最终要执行的用例文件
'''
file_list = []
case_path = cls.project_directory + 'case'
# case目录下的所有文件
for filename in os.listdir(case_path):
if 'yaml' in filename:
# 要储存为case开头的目录,方便读取用例使用
file_list.append('case/' + filename)
else:
# 遍历case下面的二级目录
for i in os.listdir(case_path + '/' + filename):
# 检查这个二级目录是否需要被排除
if filename in exclude_dir:
continue
# 要储存为case开头的目录,方便读取用例使用,这是二级目录得把二级目录拼接上
file_list.append('case/' + filename + '/' + i)
#找出要排除的文件和已经找出来的文件的并集
exclude_file = list(set(exclude_file) & set(file_list))
#最后把它踢出去
file_list.remove(exclude_file[0])
print(file_list)
if __name__ == '__main__':
ReadFile.file_execute_list(['case/waybill.yaml'], ['ctms'])
# 路径使用读取文件的相对路径
# 读取环境配置文件测试
# print(ReadFile.read_yaml('config/environment.yaml'))
# 读取用例文件测试
# case_data = ReadFile.read_yaml('case/test.yaml')
# print(case_data)
# 测试用例数据生成器返回
# case_list=ReadFile.read_case('case/test.yaml')
# for i in case_list:
# print(i)
第二版
bug修复后代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
@time : 2022/6/10
@Author : LL
@File : read_file.py
'''
from pathlib import Path
import yaml
from tool.parameter_setting import ParameterSetting
import os
class ReadFile:
# 获取当前项目目录D:python2022pytest_api_2022.6.10
project_directory = str(Path(__file__).parent.parent) + '/'
@classmethod
def read_yaml(cls, path):
'''读取yaml文件'''
path = cls.project_directory + path
file = open(path, 'r', encoding='utf-8')
with file as doc:
content = yaml.load(doc, Loader=yaml.Loader)
return content
'''需要文件排除,文件筛选'''
@classmethod
def read_case(cls, path):
# 这是一个用例文件的情况 {"用例标题1":{"data":{},"path":'/ff'},"用例标题2":{"data":{},"path":'/ff'}}
case_data = cls.read_yaml(path)
for k, v in case_data.items():
# k为用例名称,v为用例数据
case_name = k
# 如果用例需要执行
if v['is_run'] == True:
# 把用例标题写进最终请求数据中
v['case_title'] = case_name
yield v
@classmethod
def file_execute_list(cls, exclude_file: list, exclude_dir: list):
'''
:param exclude_dir: 要排除的目录(二级目录)例子:ctms
:param exclude_file: 要排除的文件(case目录下所有文件)例子:case/ctms/test.yaml case/waybill.yaml
:return: 获取case下的所有用例文件列表,最多支持二级目录,通用排除文件返回最终要执行的用例文件
'''
file_list = []
case_path = cls.project_directory + 'case'
# case目录下的所有文件
for filename in os.listdir(case_path):
if 'yaml' in filename:
# 要储存为case开头的目录,方便读取用例使用
file_list.append('case/' + filename)
else:
# 遍历case下面的二级目录
for i in os.listdir(case_path + '/' + filename):
# 检查这个二级目录是否需要被排除
if filename in exclude_dir:
continue
# 要储存为case开头的目录,方便读取用例使用,这是二级目录得把二级目录拼接上
file_list.append('case/' + filename + '/' + i)
#文件列表不为空的话一个一个的排除掉这些文件
if exclude_file !=[]:
for i in exclude_file:
file_list.remove(i)
print(file_list)
if __name__ == '__main__':
ReadFile.file_execute_list(['case/ctms/test.yaml'],[])
# 路径使用读取文件的相对路径
# 读取环境配置文件测试
# print(ReadFile.read_yaml('config/environment.yaml'))
# 读取用例文件测试
# case_data = ReadFile.read_yaml('case/test.yaml')
# print(case_data)
# 测试用例数据生成器返回
# case_list=ReadFile.read_case('case/test.yaml')
# for i in case_list:
# print(i)
使用(细节)
之前都是单文件用例处理,现在变成了多文件,我取消了之前的path参数,现在路径是一个路径列表,需要把列表里的路径循环遍历的都读取一遍,读出每个文件的数据{“用例标题1”:{“data”:{},“path”:‘/ff’},“用例标题2”:{“data”:{},“path”:‘/ff’}},然后把这些文件的数据拼接成一个字典,搞出最终要执行的用例数据
[2022-06-24 16:46:21] read_file.py -> read_case line:38 [INFO] : 最终执行的用例数据:{
'创建账单': {'path': '/create_bill', 'method': 'post', 'remark': '创建账单', 'is_run': True, 'data': {'create_month': '6月', 'create_name': '小江'}, 'extract_key': {'bill_no': '$.bill_no', 'create_name': '$.bill_info.create_name'}, 'assert_expression': ['"lj1314"=="$.bill_no"']},
'确认账单': {'path': '/affirm_bill', 'method': 'post', 'remark': '确认账单', 'is_run': True, 'data': {'affirm_name': '小江', 'bill_no': '$.bill_no'}, 'extract_key': {'affirm_name': '$.bill_info.affirm_name'}, 'assert_expression': ['"小江"=="$.bill_info.affirm_name"']},
'核销账单': {'path': '/write_off_bill', 'method': 'post', 'remark': '核销账单', 'is_run': True, 'data': {'affirm_name': '$.affirm_name', 'bill_no': '$.bill_no', 'create_name': '$.create_name'}, 'extract_key': None, 'assert_expression': ['"小江"=="$.bill_info.affirm_name"', '"小江"=="$.bill_info.create_name"']},
'获取运单号': {'path': '/get_waybill_no', 'method': 'get', 'remark': '获取运单号,提取运单号', 'is_run': True, 'data': None, 'extract_key': {'waybill_no': '$.waybill_no'}, 'assert_expression': ['"lj520"=="$.waybill_no"']},
'录单': {'path': '/lu_dan', 'method': 'post', 'remark': '录单,使用运单号', 'is_run': True, 'data': {'waybill_no': '$.waybill_no', 'lu_dan_ren': '小江', 'time': 'random_time()', 'str': 'random_str(6)', 'int': 'random_number(5)'}, 'extract_key': None, 'assert_expression': ['"运单创建成功"=="$.msg"']}}
字典拼接知识点
#字典拼接
d={}
for i in [{1:1},{2:2},{3:3,4:4}]:
d.update(i)
print(d) #{1: 1, 2: 2, 3: 3, 4: 4}
当前最终读取文件代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
@time : 2022/6/10
@Author : LL
@File : read_file.py
'''
from pathlib import Path
from tool.log import logger
import yaml
from config.config import exclude_file, exclude_dir
from tool.parameter_setting import ParameterSetting
import os
class ReadFile:
# 获取当前项目目录D:python2022pytest_api_2022.6.10
project_directory = str(Path(__file__).parent.parent) + '/'
@classmethod
def read_yaml(cls, path):
'''读取yaml文件,以字典格式返回{'用例标题':{'path':'/test','data':{'id':1}}}'''
path = cls.project_directory + path
file = open(path, 'r', encoding='utf-8')
with file as doc:
content = yaml.load(doc, Loader=yaml.Loader)
return content
@classmethod
def read_case(cls):
'''读取case下需要执行的用例文件并返回用例数据'''
# 这是多个用例文件 ['case/fastapi_test/bill.yaml', 'case/waybill.yaml']
path_list = cls.file_execute_list()
# 用例文件的情况 {"用例标题1":{"data":{},"path":'/ff'},"用例标题2":{"data":{},"path":'/ff'}}
case_data = {}
for i in path_list:
case_data.update(cls.read_yaml(i))
logger.info(f'最终执行的用例数据:{case_data}')
for k, v in case_data.items():
# k为用例名称,v为用例数据
case_name = k
# 如果用例需要执行
if v['is_run'] == True:
# 把用例标题写进最终请求数据中
v['case_title'] = case_name
yield v
@classmethod
def file_execute_list(cls, exclude_file=exclude_file, exclude_dir=exclude_dir):
'''
:param exclude_dir: 要排除的目录(二级目录)例子:ctms list格式
:param exclude_file: 要排除的文件(case目录下所有文件)例子:case/ctms/test.yaml case/waybill.yaml list格式
:return: 获取case下的所有用例文件列表,最多支持二级目录,通用排除文件返回最终要执行的用例文件
'''
file_list = []
case_path = cls.project_directory + 'case'
# case目录下的所有文件
for filename in os.listdir(case_path):
if 'yaml' in filename:
# 要储存为case开头的目录,方便读取用例使用
file_list.append('case/' + filename)
else:
# 遍历case下面的二级目录
for i in os.listdir(case_path + '/' + filename):
# 检查这个二级目录是否需要被排除
if filename in exclude_dir:
continue
# 要储存为case开头的目录,方便读取用例使用,这是二级目录得把二级目录拼接上
file_list.append('case/' + filename + '/' + i)
# 文件列表不为空的话一个一个的排除掉这些文件
if exclude_file != []:
for i in exclude_file:
file_list.remove(i)
return file_list
if __name__ == '__main__':
ReadFile.file_execute_list([], ['c', 'ctms'])
# 路径使用读取文件的相对路径
# 读取环境配置文件测试
# print(ReadFile.read_yaml('config/environment.yaml'))
# 读取用例文件测试
# case_data = ReadFile.read_yaml('case/test.yaml')
# print(case_data)
# 测试用例数据生成器返回
# case_list=ReadFile.read_case('case/test.yaml')
# for i in case_list:
# print(i)
test_case文件ReadFile.read_case()方法的参数注意去掉
这个方法现在已经不需要参数了



