一、前言
插件项目地址:https://github.com/pytest-dev/pytest-html
官方文档地址:https://pytest-html.readthedocs.io/en/latest/
二、安装
依赖
直接安装
pip install pytest-html
从源码安装
pip install -e .
三、基本使用
pytest --html=report.html
pytest --html=report.html --self-contained-html
四、深度使用
1. 改变报告样式
pytest --html=report.html --css=自定义的样式文件的路径
示例
-
首先新建一个css文件,入如:report.css -
打开pytest-html生成的报告,用F12查看标签的相关信息,class,id,标签名等
3. 先尝试直接通过F12更改报告样式,看是否有效。(当前如果你很会css,可以忽略这个步骤)
-
拷贝样式代码到report.css -
运行测试时,指定该css文件:pytest --html=report.html --css=report.css -
再次打开报告,可以看到我们指定的css样式生效了。
2. 修改报告标题
默认情况下,pytest-html会使用报告文件名作为报名标题,这里我们可以通过钩子函数pytest_html_report_title 更改报告标题。
def pytest_html_report_title(report):
report.title = "My very own title!"
示例
-
找到项目根目录下的conftest.py文件,往里面粘贴上面的代码,其中标题是可以自定义的。 -
重新生成报告就可以看到效果了。
3. 修改Enviroment
环境模块是由 pytest-metadata 插件提供的。有两个钩子函数:pytest_configure ,pytest_sessionfinish
在测试运行前修改环境配置pytest_configure
def pytest_configure(config):
config._metadata["键"] = "值"
在测试运行后修改环境配置pytest_sessionfinish
import pytest
@pytest.hookimpl(tryfirst=True)
def pytest_sessionfinish(session, exitstatus):
session.config._metadata["键"] = "值"
注意:
@pytest.hookimpl(tryfirst=True) 非常重要;- 它可以使得
pytest_sessionfinish 在任何其他插件(包括pytest-html , pytest-metadata )运行前运行; - 如果我们没有增加
@pytest.hookimpl(tryfirst=True) ,就会导致环境表不会按照我们预想的发生变化。
示例
-
在conftest.py文件上增加如下代码 -
重新运行生成报告后,报告如下图所示
问题
官方文档这部分功能,没有理解,大家如果搞定了可以给我留言,谢谢啦!
4. 修改Summary
我们可以通过钩子函数pytest_html_results_summary 修改summary部分内容。
from py.xml import html
def pytest_html_results_summary(prefix, summary, postfix):
prefix.extend([html.p("追加的内容")])
示例
-
在conftest.py文件上增加如下代码 -
重新运行生成报告后,报告如下图所示
5. 增加额外的内容
我们能通过extra 给报告增加更多的详细信息。以下是我们可以增加的内容。
Type | Example |
---|
Raw HTML | extra.html(‘
Additional HTML
’) | JSON | extra.json({‘name’: ‘pytest’}) | Plain text | extra.text(‘Add some simple Text’) | URL | extra.url(‘http://www.example.com/’) | Image | extra.image(image, mime_type=‘image/gif’, extension=‘gif’) | Image | extra.image(‘/path/to/file.png’) | Image | extra.image(‘http://some_image.png’) |
注意:
Image format | Example |
---|
PNG | extra.png(image) | JPEG | extra.jpg(image) | SVG | extra.svg(image) |
但是我亲自尝试过,直接使用extras.image就可以加载上述类型的图片。上述指定格式显得稍有点多余。
而且注意:官方文档都是写的extra.image 或者 extra.svg , extra没有带s,实际示例中有s,实际使用也需要用extras。这里不知道是不是我理解的有问题,还是官方文档笔误,大家注意一下。
我们可以在conftest.py中通过钩子函数pytest_runtest_makereport 来增加这些额外的内容。
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
pytest_html = item.config.pluginmanager.getplugin("html")
outcome = yield
report = outcome.get_result()
extra = getattr(report, "extra", [])
if report.when == "call":
extra.append(pytest_html.extras.url("http://www.example.com/"))
xfail = hasattr(report, "wasxfail")
if (report.skipped and xfail) or (report.failed and not xfail):
extra.append(pytest_html.extras.html("<div>Additional HTML</div>"))
report.extra = extra
示例1
-
首先修改我们的用例,让用例产生各种类型的数据,方便看效果。 -
我们在conftest.py文件中增加如下代码
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
pytest_html = item.config.pluginmanager.getplugin("html")
outcome = yield
report = outcome.get_result()
extra = getattr(report, "extra", [])
if report.when == "call":
extra.append(pytest_html.extras.url("https://www.gitlink.org.cn"))
extra.append(pytest_html.extras.json({"name": "pytest"}))
extra.append(pytest_html.extras.text("这里是xxx自动化测试用例"))
xfail = hasattr(report, "wasxfail")
if (report.skipped and xfail) or (report.failed and not xfail):
extra.append(pytest_html.extras.html(
"<div style='background-color:red;text-align: center;font-size:16px;color:white;'>这条用例xfail 或者 failed</div>"))
extra.append(pytest_html.extras.image("111.gif", mime_type="image/gif", extension="gif"))
extra.append(pytest_html.extras.image("1.bmp"))
extra.append(pytest_html.extras.svg("2.svg"))
extra.append(pytest_html.extras.image("https://www.gitlink.org.cn/api/attachments/389903"))
report.extra = extra
3. 运行生成报告后如下图所示
我们还可以给除了html的其他类型来增加name 来改变增加内容的标题。
extra.append(pytest_html.extras.text("some string", name="Different title"))
示例2
- 修改conftest.py中的
pytest_runtest_makereport 的内容
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
pytest_html = item.config.pluginmanager.getplugin("html")
outcome = yield
report = outcome.get_result()
extra = getattr(report, "extra", [])
if report.when == "call":
extra.append(pytest_html.extras.url("https://www.gitlink.org.cn", name="gitlink"))
extra.append(pytest_html.extras.json({"name": "pytest"}, name="接口响应数据"))
extra.append(pytest_html.extras.text("这里是xxx自动化测试用例", name="文本"))
extra.append(pytest_html.extras.image("1.bmp", name="图片"))
xfail = hasattr(report, "wasxfail")
if (report.skipped and xfail) or (report.failed and not xfail):
extra.append(pytest_html.extras.html(
"<div style='background-color:red;text-align: center;font-size:16px;color:white;'>这条用例xfail 或者 failed</div>"))
report.extra = extra
- 运行生成报告后如下图所示
我们也可以直接在测试方法中将extra当做一个fixture使用,而不使用上述的钩子函数pytest_runtest_makereport 。
from pytest_html import extras
def test_extra(extra):
extra.append(extras.text("some string"))
示例3
- 在测试函数代码如下:
注意:原先conftest.py中的pytest_runtest_makereport 可以注释掉了。
import pytest
from pytest_html import extras
def test_demo_01(extra):
extra.append(extras.text("这是一条通过的用例", name="测试通过的文本"))
assert 1 == 1
def test_demo_02(extra):
extra.append(extras.json("这是一条失败的用例", name="测试失败的JSON"))
assert True == False
def test_demo_03(extra):
extra.append(extras.html(
"<div style='background-color:red;text-align: center;font-size:16px;color:white;'>这条用例xfail 或者 failed</div>"))
pytest.xfail("这是一条xfail的用例")
def test_demo_04():
pytest.skip("这条用例跳过")
- 运行生成报告后如下图所示
6. 修改结果表
增加description, Time列,移除Links列
-
首先修改一下测试方法,给部分测试方法增加文档注释 -
在conftest.py中增加如下代码
from datetime import datetime
def pytest_html_results_table_header(cells):
"""
处理结果表的表头
"""
cells.insert(2, html.th("Description", class_="sortable desc", col="desc"))
cells.insert(1, html.th("Time", class_="sortable time", col="time"))
cells.pop()
def pytest_html_results_table_row(report, cells):
"""
处理结果表的行
"""
cells.insert(2, html.th(report.description))
cells.insert(1, html.th(datetime.utcnow(), class_="col-time"))
cells.pop()
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
report = outcome.get_result()
if str(item.function.__doc__) != "None":
report.description = str(item.function.__doc__)
else:
report.description = "这里是描述信息"
- 运行生成报告后如下图所示
测试通过的情况下删除所有的单元格
注意:这种情况下,我们在报告中无法看到通过用例的任何信息。 在conftest.py中增加如下代码:
def pytest_html_results_table_row(report, cells):
if report.passed:
del cells[:]
钩子函数pytest_html_results_table_html 修改日志输出和其他HTML
在conftest.py中增加如下代码:
from py.xml import html
def pytest_html_results_table_html(report, data):
if report.passed:
del data[:]
data.append(html.div("这条用例通过啦!", class_="empty log"))
运行后产生的报告如下:
7. 自动收起所有的列
默认情况下,结果表中的所有行都是展开显示的。如下图所示:
我们可以通过在pytest的配置文件pytest.ini中设置来决定是否展开还是收起。
[pytest]
render_collapsed = True
重新运行生成报告后如下图所示:
官方文档这里提出的设置查询参数,没有搞明白怎么设置,有搞明白的,欢迎给我留言~
8. 设置哪些测试结果可见
官方文档这里提出的设置查询参数,没有搞明白怎么设置,有搞明白的,欢迎给我留言~
9. 格式化Duration列
默认情况下,Durations列是用得一个格式化的时间戳,使用的是%S.%f ,%S 是秒%f 是毫秒, 是通过duration_formatter 设置的。目前pytest-html是支持所有的格式化指令的。
但是我们可以在conftest.py文件中对Duration列进行格式化设置。
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
report = outcome.get_result()
setattr(report, "duration_formatter", "%H:%M:%S.%f")
NOTE: Milliseconds are always displayed with a precision of 2
|