如何调用Pytest仅执行报告生成函数而不运行测试用例?
实现仅执行Pytest报告函数并重新生成HTML报告的方案
问题背景
已开发基于Pytest的测试框架,将测试流程与报告函数分离:
- 测试用例格式:
def test_testcase001() - 对应报告函数:
def reporter_testcase001(meas_file)
需求:仅指定已有测量文件夹,通过pytest-html重新生成HTML报告,仅执行reporter_开头的报告函数,不运行test_开头的测试用例。
具体实现步骤
1. 添加自定义命令行参数
在conftest.py中添加参数,用于指定已有测量文件夹的根目录:
def pytest_addoption(parser): parser.addoption( "--measurement-root", action="store", help="指定已有的测量文件夹根目录,用于重新生成报告" )
2. 标记报告函数
给所有reporter_开头的报告函数添加专属标记,方便后续筛选执行:
import pytest class TestMyCases: def test_testcase001(self): # 原有测试逻辑 pass @pytest.mark.report_only def reporter_testcase001(self, meas_file): # 原有报告生成逻辑 pass
3. 修改自动Fixture逻辑
调整_intermediate_setup_teardown fixture,根据命令行参数判断是否跳过测试执行,直接复用指定的测量文件夹:
import os import pytest @pytest.fixture(autouse=True, scope='function') def _intermediate_setup_teardown(request, overall_setup_teardown, load_parameter_set): request.config.test_params = None try: request.config.test_params = request.node.callspec.params except: pass # 获取命令行传入的测量根目录 measurement_root = request.config.getoption("--measurement-root") # 判断是否处于仅报告模式 is_report_only = request.node.get_closest_marker("report_only") is not None if is_report_only: # 仅报告模式:直接匹配对应测量文件夹 testname = request.function.__name__.replace("reporter_", "") if request.config.test_params: testname = f'{testname}_{"_".join(map(str, request.config.test_params.values()))}' testdir = os.path.join(measurement_root, request.node.cls.__name__, testname) request.config.measurement_folder = testdir yield # 直接执行当前报告函数 meas_file = os.path.join(testdir, 'meas.mat') if request.config.test_params is None: request.function(meas_file) else: request.function(meas_file, request) else: # 原有测试执行逻辑 testname = request.function.__name__ if request.config.test_params is None else f'{request.function.__name__}_{"_".join(map(str, request.config.test_params.values()))}' testdir = os.path.join(request.config.result_folder, request.node.cls.__name__, testname ) os.makedirs(testdir, exist_ok=True) request.config.measurement_folder = testdir setup_test = request.node.cls.setup_test if params := request.config.model_params: setup_test(params) else: setup_test() yield meas_file = os.path.join(testdir, 'meas.mat') teardown_test = request.node.cls.teardown_test teardown_test(meas_file) marker = request.node.get_closest_marker('report') if marker: report_name = marker.args[0] reporter = getattr(request.node.cls, f'report_{report_name}') reporter(meas_file) if request.config.test_params is None else reporter(meas_file, request)
4. 过滤测试用例(可选)
如果需要彻底排除test_开头的用例,在conftest.py中添加收集钩子:
def pytest_collection_modifyitems(config, items): measurement_root = config.getoption("--measurement-root") if measurement_root: # 仅保留带report_only标记的用例 items[:] = [item for item in items if item.get_closest_marker("report_only") is not None]
5. 适配报告图片生成Hook
确保从指定测量文件夹读取图片,修改钩子逻辑:
import os from base64 import b64encode @pytest.hookimpl(hookwrapper=True, tryfirst=True) def pytest_runtest_makereport(item, call): html = item.config.pluginmanager.getplugin('html') outcome = yield report = outcome.get_result() extra = getattr(report, 'extra', []) if report.when == 'teardown': meas_folder = item._request.config.measurement_folder if os.path.exists(meas_folder): for dirpath, _, files in os.walk(meas_folder): for f in files: if f.endswith('.png'): with open(os.path.join(dirpath, f), 'rb') as img_file: plot64 = b64encode(img_file.read()).decode('utf-8') png_html = f'<img src="data:image/png;base64,{plot64}" width="500" height="500" alt="测试图片">' extra.append(html.extras.html(png_html)) report.extra = extra
运行命令
执行以下命令即可仅生成报告,不运行测试用例:
pytest --measurement-root=/path/to/your/measurement/folder -m report_only --html=report.html
内容的提问来源于stack exchange,提问作者Ádám Varga
相关产品推荐
相关产品推荐

