前言
前面几个章节,我们主要是如何通过yaml文件的数据自动转换成测试用例,并按照关键字去执行,如下是之前我们通过参数化的形式手动执行用例。
from utils.run import RunByKey
# 获取文件路径
file_path = Path(__file__).parent.joinpath('data', 'login.yml')
@pytest.mark.parametrize('key, value', read_file.read_yaml(file_path)['data'])
def test_login(key, value, base_url):
print(f"测试用例名称: {value['name']}")
print(f"测试数据: {value['request']}") # data ---dict
print(f"base_url: {base_url}")
s = HttpSession(base_url=base_url)
run = RunByKey(s, read_file.read_yaml(file_path)['config'])
run.run(value)
现在我们继续封装,不进行手动参数化方式执行用例。也就是我们连上面的代码也无需写,只通过yaml文件直接执行用例。
如果认真点,我们就会发现,在05章节中的最后一张图中,也就是我们动态生成测试用例函数的时候,我们会发现一个问题:如下所示:
1.Python经典问题
上面的问题我们叫做python经典问题,如何去解决这个问题呢?
首先我们举个例子,来分析下这个问题形成的过程:
res = []
data = {"testa": "aaa", "testb": "bbb"}
for key, value in data.items():
def fun():
print(value)
res.append(fun)
print(res)
for f in res:
f()
打印结果:
[<function fun at 0x0000020D5DC76280>, <function fun at 0x0000020D5DDFC280>]
bbb
bbb
分析:
1.for 循环data里面的数据,函数在循环内部定义,但是未调用
2.在for循环内部将函数对象添加到res列表中
3.for循环调用函数f(),而此时的value值取最新的为第二个“bbb”,于是打印2个bbb
1.1 解决函数对象调用后,内部值被覆盖的问题
解决思路,我们首先需要确定函数被谁调用, 然后知道被谁调用后单独取出这个函数对应的值。
import inspect
import inspect
def fun():
# 被谁调用
call_function_name = inspect.getframeinfo(inspect.currentframe().f_back)[2]
print(call_function_name)
return "33"
def fun_x():
fun()
def fun_y():
fun()
fun_x()
fun_y()
打印:
fun_x
fun_y
于是我们在执行yaml的函数中,添加这个方法:
from pytest import Module, Function
import types
import yaml
from utils.run import RunYaml
import inspect
from utils.create_function import create_function_from_parameters
from inspect import Parameter
def pytest_collect_file(file_path, parent):
# 查找test开头的文件
if file_path.suffix in ['.yml', '.yaml'] and (file_path.name.startswith('test') or file_path.name.endstartswith('test')):
print(f'yaml文件路径:{file_path}')
print(f'yaml文件路径名称:{file_path.stem}')
# 构造 pytest 框架的 Module,module由Package构建,Package由系统构建
py_module = Module.from_parent(parent, path=file_path)
# 动态创建测试module模块(.py文件),这里才能给下面的_getobj进行导入
MyModule = types.ModuleType(file_path.stem)
from utils.read_file import read_yaml
from pathlib import Path
file_path = Path(__file__).parent.joinpath('data', 'login.yml')
raw_data = read_yaml(file_path)['data']
for key, value in raw_data:
def foo(arg):
print(f"执行的参数: {arg}")
call_function_name = inspect.getframeinfo(inspect.currentframe().f_back)[2]
raw_data_dict = dict(raw_data)
print(f"执行的内容: {raw_data_dict[call_function_name]}")
f = create_function_from_parameters(func=foo,
parameters=[Parameter('request', Parameter.POSITIONAL_OR_KEYWORD)],
documentation="some doc",
func_name=key,
func_filename="main.py")
# 向 module 中加入test 函数
setattr(MyModule, key, f)
# 重写_getobj,返回自己定义的Mymodule
py_module._getobj = lambda: MyModule
return py_module
标签:06,yaml,测试用例,file,import,fun,path,data
From: https://www.cnblogs.com/dack-zt-deng/p/17863088.html