文章目录
- 前言
- 应用场景
- 插件安装
- 参数分析
- 使用方法
- 拓展-定制化报告
前言
在软件开发过程中,测试是确保代码质量的关键环节。
而测试报告则是测试过程中不可或缺的输出物,它为我们提供了关于测试用例执行情况的详细信息,帮助我们快速定位和解决问题。
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, "偶数失败,奇数通过"
执行结果
页面效果