背景
全量自动化(用例数6k+)执行超时(异常中断),发现有部分用例未执行,由于用例总数很多,全量重跑显然不够现实,所以需要找出未执行的用例进行重试
解决方案
- 使用pytest的钩子函数(pytest_collection_modifyitems)实现只采集不执行的方式搜集所有满足执行条件的用例集合A;
- 使用脚本分析统计已执行用例的报告(日志),过滤出已经执行过的用例集合B;
- 集合A减去集合B就可以得出未执行的用例集合C;
- 将集合C的用例数据进行格式,生成一个测试缓存文件;
- 使用测试缓存,重新构建测试,
注: 本文只对第一步进行
代码实现
# conftest.py
def pytest_collection_modifyitems(config, items):
for item in items:
# 这里的 items 是一个列表,包含了所有收集到的测试用例
# 需要打印那些用例数据,根据需要调整
# 将所有测试用例名称等信息打印出来,有需要可以将其写入文件
print(item.path, item.parent.name, item.name)
# 因为不希望执行用例,使用断点进行中断
breakpoint()
使用方式
使用pytest命令行启动执行或者pycharm中配置使用,这里讲一下pycharm配置使用方法
修改执行配置,将配置路径修改为需要扫描的用例路径后生效即可。
钩子介绍
pytest_collection_modifyitems 是 pytest 中的一个钩子函数,用于在收集测试用例之后、执行测试用例之前对其进行修改。可以使用这个钩子函数来动态地修改测试用例的顺序、添加标记、跳过某些测试等。
配置
- 创建一个 conftest.py 文件:conftest.py 是一个特殊的文件,pytest 会自动加载其中的内容。
- 定义 pytest_collection_modifyitems 函数:在 conftest.py 文件中定义这个钩子函数。
- 修改收集到的测试用例:在函数内部,你可以对 items 列表进行操作,这个列表包含了所有收集到的测试用例。
其他使用场景
1、用例过滤排序
# conftest.py
def pytest_collection_modifyitems(config, items):
# 这里的 items 是一个列表,包含了所有收集到的测试用例
# 示例:将所有测试用例按名称排序
items.sort(key=lambda item: item.name)
# 示例:将所有测试用例按标记排序
# 先收集所有标记为 'slow' 的测试用例
slow_tests = [item for item in items if 'slow' in item.keywords]
# 再收集所有其他的测试用例
other_tests = [item for item in items if 'slow' not in item.keywords]
# 重新排列测试用例,先运行其他测试,再运行慢速测试
items[:] = other_tests + slow_tests
2、 用例信息打印、过滤
# conftest.py
import pytest
def pytest_collection_modifyitems(config, items):
for item in items:
# 这里的 items 是一个列表,包含了所有收集到的测试用例
# 打印指定用例标签(T2)的用例信息
if item.get_closest_marker('T2'):
print(item.path, item.parent.name, item.name)
# 跳过指定用例(相当于用例打上skip标签)
if item.name == 'test_demo_1':
item.add_marker(pytest.mark.skip(reason="Skipping this test"))
# 添加自定义标签
if item.parent.name == 'TestLevel1':
item.add_marker(pytest.mark.Level1)
3、 跳过指定用例
示例为读取系统架构,在X86系统中直接跳过执行ARM用例
def pytest_collection_modifyitems(config, items):
# 读取系统架构
sys_arch = os.getenv('SYS_ARCH', 'X86')
new_items = []
for item in items:
if sys_arch == 'ARM' and item.get_closest_marker('ARM'):
# X86环境跳过ARM环境用例
new_items.append(item)
# 这里必须这样写,否则有问题
items[:] = new_items