pytest 数据驱动
1.pytest 如何收集到用例的?
2.pytest 如何把 python 代码,转换成 pytest 测试用例(又称 item) ?
pytest如何做到收集到用例的?
conftest编写以下 hook 函数:
conftest.py
def pytest_collect_file(file_path: Path, parent):
case_data = {}
if file_path.suffix in [".yaml", ".yml", ".json", ] and file_path.name.startswith("test"):
if file_path.suffix == ".yaml" or file_path.suffix == ".yml":
# 解析 yaml 内容
logger.info(f'解析文件-> {file_path}')
case_data = yaml.safe_load(file_path.open(encoding='utf-8'))
if file_path.suffix == ".json":
# 解析 json 内容
logger.info(f'解析文件-> {file_path}')
case_data = json.load(file_path.open(encoding='utf-8'))
if file_path.suffix == "xlsx":
# TODO: 解析 xlsx 内容
pass
# 动态创建函数
pytest_module = Module.from_parent(parent, path=file_path)
# 动态创建 module
module = types.ModuleType(file_path.stem)
for case_name, case_value in case_data.items():
if case_name == 'config':
# 初始化一些方法
vehicle_control =VehicleControl
continue
if not str(case_name).startswith('test'):
logger.warning(f'用例名称不规范-> {case_name}')
case_name = 'test_' + str(case_name)
case_data[case_name] = [case_value] if not isinstance(case_value, list) else case_value
def create_function(case_name): # noqa
def function_template(*args, **kwargs):
"""
测试用例-函数模块
"""
logger.info(f'执行文件-> {module.__name__}')
logger.info(f'运行用例-> {case_name}')
allure.dynamic.feature(f'{module.__name__}')
allure.dynamic.title(f'{module.__name__}')
for set_case in case_data[case_name]:
# 添加 allure 报告--> step
with allure.step(f'开始测试'):
pass
#具体用例遍历方法
runner(set_case, vehicle_control, logger)
return function_template
# 向 module 中加入函数
setattr(module, case_name, create_function(case_name))
# 重写_getobj 属性
pytest_module._getobj = lambda: module
return pytest_module
runner.py
runner(set_case, vehicle_control, logger)
for step_key, step_value in itme.items():
action_handlers = {
'setup': lambda: do_step(),
'click': lambda: do_click(step_value, vehicle_control, logger),
'time': lambda: do_step_time(step_key, step_value, logger),
'screenshot': lambda: do_screenshot(vehicle_control, logger),
'swipe': lambda: do_swipe(step_value, vehicle_control, logger),
'long_click': lambda: long_click(step_value, vehicle_control, logger),
'assert_image': lambda: assert_image(step_value, vehicle_control, logger),
'assert_text': lambda: assert_text(step_value, vehicle_control, logger),
'assert_image_pixel': lambda: assert_image_pixel(step_value, vehicle_control, logger),
'assert_element': lambda: assert_element(step_value, vehicle_control, logger),
'teardown': lambda: do_teardown(vehicle_control, logger),
}
if step_key in action_handlers:
action_handlers[step_key]()
else:
logger.error(f"Unsupported step_key: {step_key}")
pytest.fail(f"Unsupported step_key: {step_key}")
def do_step():
pass
通过反射调用不同的方法......