文章目录
- 前言
- 应用场景
- 插件安装
- 参数分析
- 使用方法
- 拓展-定制化报告
前言
在软件开发过程中,测试是确保代码质量的关键环节。
而测试报告则是测试过程中不可或缺的输出物,它为我们提供了关于测试用例执行情况的详细信息,帮助我们快速定位和解决问题。
pytest
是一个流行的 Python 测试框架,而pytest-html
是一个为pytest
提供的插件,用于生成HTML
格式的测试报告。
这个报告不仅包含了测试用例的执行情况,如成功、失败、跳过等,还会展示每个测试用例的输出信息、错误堆栈、截图等,使得测试结果更加直观和易于理解。
应用场景
项目交付与验收:
- 当项目即将交付给客户或进行验收时,提供一个详细的
HTML
测试报告
可以帮助客户或团队成员快速了解软件的测试覆盖率和质量。持续集成/持续部署(CI/CD):
- 在
CI/CD
流程中,每次代码提交或构建都会触发自动化测试。
pytest-html
可以生成易于阅读的HTML
报告,帮助团队成员快速查看测试结果。问题定位与调试:
- 当测试用例失败时,
HTML
报告中的详细信息可以帮助开发人员快速定位问题所在,提高调试效率。回归测试:
- 在软件发布新版本时,确保之前的功能没有出现问题至关重要。
pytest-html
可以帮助测试人员快速浏览之前的测试报告,了解哪些测试用例已经覆盖过相关功能。
插件安装
安装命令:
pip install pytest-html
参数分析
pytest-html插件支持多种参数来定制生成的HTML报告。
以下是一些常用的参数:
–html=path/to/report.html:
- 指定生成的
HTML
报告的文件路径和名称。–self-contained-html:
- 生成自包含的
HTML
报告- 即CSS、JavaScript、图片等都嵌入到
HTML
文件中,无需外部依赖。–no-screenshots:
- 禁用失败测试用例的截图功能。
–metadata:
- 为报告添加元数据,如项目名称、版本信息等。
使用方法
示例代码
import pytest def test_case_01(): """测试函数01""" print("测试函数01执行完成") def test_case_02(): """测试函数02""" print("测试函数02执行完成") def test_case_03(): """测试函数03""" print("测试函数03执行完成") assert False @pytest.mark.parametrize("data", [1, 3, 5, 7, 8]) def test_case_04(data): """测试函数04""" print("测试函数04执行完成") assert data % 2 != 0, "偶数失败,奇数通过"
复制
命令:
pytest -v -s --html=report.html --self-contained-html
执行结果
页面效果
拓展-定制化报告
pytest-html 插件生成的测试报告通常包含以下五个主要部分:
- Title(标题): 报告的顶部通常有一个标题,显示测试运行的基本信息,如运行时间、测试用例的总数等。
- Environment(环境): 这部分显示了运行测试时的环境信息,包括操作系统、Python 版本、pytest 版本以及任何通过配置添加的其他环境细节。
- Summary(摘要): 摘要部分提供了测试运行的概览,包括通过、失败、跳过和错误的测试用例数量。
- Results(结果): 结果部分详细列出了每个测试用例的执行情况,包括测试用例的名称、结果状态(通过/失败/跳过/错误)以及任何与测试相关的输出或错误消息。
- Results Table(结果表格): 结果表格是报告的核心部分,它以表格形式展示了每个测试用例的详细信息,包括持续时间、链接(如果有的话)和其他自定义列。
pytest-html 的钩子函数
pytest-html
插件提供了一系列钩子函数,允许用户定制报告的生成过程。这些钩子函数需要在
conftest.py
文件中定义,以便在pytest
运行时自动加载和使用。钩子函数允许我们自定义报告的各个部分,例如:
- 修改表格的头部:使用
pytest_html_results_table_header
钩子- 自定义表格的行内容:使用
pytest_html_results_table_row
钩子- 添加额外的报告细节:使用
pytest_html_report_sections
钩子
关于 pytest-metadata
某些高版本的
pytest
可能会推荐使用pytest-metadata
插件来更好地管理测试元数据。
pytest-metadata
提供了一种机制来存储和检索与测试用例相关的元数据,这对于在报告中显示额外的信息非常有用。如果需要使用
pytest-metadata
,可以通过以下命令进行安装:
pip install pytest-metadata
复制
官方文档:https://pytest-html.readthedocs.io/en/latest/user_guide.html#creating-a-self-contained-report
conftest.py
文件示例代码
import os import json import pytest import logging from datetime import datetime from pytest_metadata.plugin import metadata_key # 1、修改报告标题 def pytest_html_report_title(report): report.title = "我的测试报告标题" # 2、运行测试前修改环境信息 def pytest_configure(config): config.stash[metadata_key]["项目名称"] = "我的测试项目名称" config.stash[metadata_key]["接口模块"] = "我的测试接口模块" config.stash[metadata_key]["接口地址"] = "我的测试接口地址" # 3、动态生成log文件的名称,哪怕配置文件中配置了log_file选项也不会生效 time_now = datetime.now().strftime('%Y%m%d%H%M%S') config.option.log_file = os.path.join(config.rootdir, 'log', f'{time_now}.log') # 4、修改摘要信息 def pytest_html_results_summary(prefix, summary, postfix): prefix.extend(["<p>所属部门: 测试xxx部门</p>"]) prefix.extend(["<p>测试人员: 张三xxxxxx</p>"]) # 5、修改测试结果表格中的列(插入列) def pytest_html_results_table_header(cells): cells.insert(2, "<th>描述</th>") cells.insert(1, '<th class="sortable time" data-column-type="time">测试时间</th>') # 6、修改测试结果表格中的列(插入数据) def pytest_html_results_table_row(report, cells): cells.insert(2, f"<td>{report.description}</td>") cells.insert(1, f'<td class="col-time">{datetime.utcnow()}</td>') # 7、获取测试函数中的doc注释 @pytest.hookimpl(hookwrapper=True) def pytest_runtest_makereport(item, call): outcome = yield report = outcome.get_result() report.description = str(item.function.__doc__) # 8、获取测试函数中的异常错误信息 if call.excinfo is not None: msg = { "module": item.location[0], "function": item.name, "line": item.location[1], "message": str(call.excinfo.value).replace("\n", ":") } logging.error(json.dumps(msg, indent=4, ensure_ascii=False))
复制
pytest.ini
文件示例代码
[pytest] ;打印详细日志,相当于命令行加 -vs addopts = --capture=no --tb=long --html=report.html --self-contained-html --log-cli-level=INFO ;日志开关 true/false log_cli = true ;输出到终端 ;日志级别 log_cli_level = info ;日志格式 log_cli_format = %(asctime)s --> %(filename)-10s [line:%(lineno)-3d] --> %(levelname)-5s --> %(message)s ;日志时间格式 log_cli_date_format = %Y-%m-%d %H:%M:%S ; 输出到文件 ;日志文件位置 log_file = ./log/test.log ;日志文件等级 log_file_level = info ;日志文件格式 log_file_format = %(asctime)s --> %(filename)-10s [line:%(lineno)-3d] --> %(levelname)-5s --> %(message)s ;日志文件日期格式 log_file_date_format = %Y-%m-%d %H:%M:%S
复制
test_case_01.py
示例代码
import pytest import logging log = logging.getLogger(__name__) def test_case_01(): """测试函数01""" log.info("111") print("测试函数01执行完成") def test_case_02(): """测试函数02""" print("测试函数02执行完成") def test_case_03(): """测试函数03""" print("测试函数03执行完成") log.info(f"断言:1 == 2") assert False @pytest.mark.parametrize("data", [1, 3, 5, 7, 8]) def test_case_04(data): """测试函数04""" print("测试函数04执行完成") assert data % 2 != 0, "偶数失败,奇数通过"
复制
执行结果
页面效果