Pytest-Bdd-Playwright 系列教程(18):使用 Jinja2 钩子函数生成自定义测试报告
Pytest-Bdd-Playwright 系列教程(18):使用 Jinja2 & 钩子函数生成自定义测试报告
- 1. 背景&目标
- 1.1 为什么需要自定义测试报告?
- 1.2 文章目标
- 2. Pytest 钩子函数概述
- 2.1 常见的 Pytest 钩子函数
- 3. Jinja2 模板引擎概述
- 3.1 Jinja2 的基本用法
- 4. 自定义测试报告的实现
- 4.1 编写 Jinja2 模板
- 4.2 使用 Pytest 钩子函数生成报告
- 4.3 代码解读
- 4.4 测试报告效果
- 5. 总结
1. 背景&目标
1.1 为什么需要自定义测试报告?
Pytest 提供了一些基本的报告格式,比如使用pytest-html
生成的 HTML 报告。这些默认报告虽然直观,但它们的内容和样式可能无法满足所有项目的需求。
有时,我们可能需要:
- 更详细的测试信息:如执行时间、失败原因等;
- 个性化报告样式:根据团队或项目的风格,设计独特的报告模板;
- 增加自定义字段:如测试环境、执行人员等元信息。
在这种情况下,我们可以通过 Pytest 的钩子函数和 Jinja2 模板引擎生成自定义的 HTML 测试报告,满足特定需求。
1.2 文章目标
本文的目标是:
- 介绍如何在 Pytest 中使用钩子函数(
pytest_terminal_summary
)来获取测试结果; - 使用 Jinja2 模板引擎生成自定义的 HTML 测试报告;
- 提供一个完整的代码示例,展示如何整合 Pytest、Jinja2 和钩子函数来生成专业的测试报告。
2. Pytest 钩子函数概述
在 Pytest 中,钩子函数是一种用于扩展 Pytest 功能的机制。钩子函数可以在 Pytest 执行不同阶段时被触发,允许用户插入自定义的逻辑。
2.1 常见的 Pytest 钩子函数
Pytest 提供了多个钩子函数,可以用来处理不同的任务。以下是几个常见的钩子函数:
pytest_collection_modifyitems
: 在 Pytest 收集测试用例时执行,可以用来修改测试用例。pytest_runtest_logreport
: 在每个测试用例执行时触发,用于记录每个测试的状态。pytest_terminal_summary
: 在测试执行完毕后,生成终端输出摘要,适合用来生成最终的测试报告。
在本文中,我们将使用 pytest_terminal_summary
钩子函数来处理测试结果并生成报告。
3. Jinja2 模板引擎概述
Jinja2 是 Python 的一个流行模板引擎,常用于动态生成 HTML、XML 等文件。它通过模板和数据的结合,生成最终的输出。
在测试报告生成中,Jinja2 可以帮助我们将测试数据填充到预先定义好的 HTML 模板中,从而实现报告的个性化。
3.1 Jinja2 的基本用法
Jinja2 模板由两部分组成:
- 模板文件:一个包含占位符的文件,Jinja2 将根据传入的数据填充这些占位符。
- 渲染过程:在代码中加载模板文件,并传入数据,Jinja2 会渲染模板并生成最终的 HTML 文件。
4. 自定义测试报告的实现
接下来,我们将展示如何结合使用 Pytest 的钩子函数和 Jinja2 模板引擎来生成自定义的 HTML 测试报告。
4.1 编写 Jinja2 模板
首先,我们需要编写一个 HTML 模板文件,为了方便演示,我们把Jinja2 模板直接放在conftest.py
文件。以下是一个简单的 Jinja2 模板:
from jinja2 import Template
html_template = '''<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.container {
width: 90%;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background-color: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 8px;
margin-top: 20px;
}
h2 {
text-align: center;
color: #333;
}
table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
th, td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #f2f2f2;
color: #333;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
tr:hover {
background-color: #f1f1f1;
}
.passed { color: green; }
.failed { color: red; }
.skipped { color: orange; }
.xfailed { color: purple; }
.xpassed { color: blue; }
</style>
</head>
<body>
<div class="container">
<h2>{{ title }}</h2>
<table>
<tr>
<th>测试函数</th>
<th>用例名称</th>
<th>状态</th>
<th>用例输出</th>
<th>执行时间</th>
</tr>
{% for result in results %}
<tr>
<td>{{ result.nodeid
.split("::")[0] }}</td>
<td>{{ result.nodeid.split("::")[-1] }}</td>
<td class="{{ result.outcome }}">{{ result.outcome }}</td>
<td>{{ result.longrepr }}</td>
<td>{{ result.duration }}</td>
</tr>
{% endfor %}
</table>
</div>
</body>
</html>'''
这个模板包括了一个简单的表格,用来展示每个测试的名称、状态、输出和执行时间。通过 Jinja2 的占位符,我们可以动态地填充这些数据。
4.2 使用 Pytest 钩子函数生成报告
然后,我们需要实现 Pytest 钩子函数 pytest_terminal_summary
,它将获取所有测试结果并使用 Jinja2 模板生成 HTML 报告。
# conftest.py
def pytest_terminal_summary(terminalreporter, exitstatus, config):
results = []
for status in ['passed', 'failed', 'skipped', 'xfailed', 'xpassed']:
if status in terminalreporter.stats:
results.extend(terminalreporter.stats[status])
html = Template(html_template).render(title='blues_C的测试报告', results=results)
with open('./reports/report.html', 'w', encoding='utf-8') as f:
f.write(html)
4.3 代码解读
- Jinja2 模板:在模板中,我们定义了 HTML 结构,并通过占位符
{{ title }}
和{{ result.* }}
来插入动态数据。 - pytest_terminal_summary 钩子函数:该函数会在测试执行完成后被调用。我们通过遍历测试结果并将其传入 Jinja2 模板,生成最终的 HTML 文件。生成的报告将保存在
./reports/report.html
文件中。
4.4 测试报告效果
运行 Pytest 后,我们将在 ./reports
目录下找到一个名为 report.html
的文件,打开后可以看到如下格式的报告:
- 每个测试用例的执行状态(通过、失败、跳过等);
- 测试失败的详细输出(如 traceback);
- 每个测试的执行时间。
5. 总结
在本文中,我们介绍了如何通过 Pytest 的钩子函数和 Jinja2 模板引擎自定义测试报告。通过这个方法,我们能够生成符合自己需求的 HTML 报告,包括个性化的样式和动态的数据展示。你可以根据项目需求进一步扩展这个报告,添加更多的功能,例如图表展示等。希望这个教程能帮助你提升自动化测试报告的质量和可读性!