插件项目地址:https://github.com/pytest-dev/pytest-html
官方文档地址:https://pytest-html.readthedocs.io/en/latest/
pip install pytest-html
pip install -e .
# 直接在当前目录生成名称为report.html的报告,同时会自动生成一个assets样式文件目录
pytest --html=report.html
# 直接在当前目录生成名称为report.html的报告,报告自带样式
pytest --html=report.html --self-contained-html
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样式生效了。
默认情况下,pytest-html会使用报告文件名作为报名标题,这里我们可以通过钩子函数pytest_html_report_title
更改报告标题。
def pytest_html_report_title(report):
report.title = "My very own title!"
找到项目根目录下的conftest.py文件,往里面粘贴上面的代码,其中标题是可以自定义的。
重新生成报告就可以看到效果了。
环境模块是由 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文件上增加如下代码
重新运行生成报告后,报告如下图所示
官方文档这部分功能,没有理解,大家如果搞定了可以给我留言,谢谢啦!
我们可以通过钩子函数pytest_html_results_summary
修改summary部分内容。
from py.xml import html
def pytest_html_results_summary(prefix, summary, postfix):
prefix.extend([html.p("追加的内容")])
在conftest.py文件上增加如下代码
重新运行生成报告后,报告如下图所示
我们能通过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’) |
注意:
当我们从文件中增加一个图片时,图片的路径可以是绝对路径或者相对路径。
当我们使用 --self-contained-html
, 图片也许无法按照预期的加载出来。(这里我试过,是可以正常加载的。)
官方文档说图片还可以使用如下格式:
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":
# always add url to report
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):
# only add additional html on failure
extra.append(pytest_html.extras.html("<div>Additional HTML</div>"))
report.extra = extra
首先修改我们的用例,让用例产生各种类型的数据,方便看效果。
我们在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":
# 增加URL
extra.append(pytest_html.extras.url("https://www.gitlink.org.cn"))
# 增加json
extra.append(pytest_html.extras.json({"name": "pytest"}))
# 增加plain text
extra.append(pytest_html.extras.text("这里是xxx自动化测试用例"))
xfail = hasattr(report, "wasxfail")
if (report.skipped and xfail) or (report.failed and not xfail):
# 增加HTML
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"))
# 增加图片,图片格式是svg
# extra.append(pytest_html.extras.image("2.svg"))
# 增加图片,使用extras指定svg格式添加
extra.append(pytest_html.extras.svg("2.svg"))
# 增加图片,图片是一个URL地址
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"))
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":
# 增加URL
extra.append(pytest_html.extras.url("https://www.gitlink.org.cn", name="gitlink"))
# 增加json
extra.append(pytest_html.extras.json({"name": "pytest"}, name="接口响应数据"))
# 增加plain text
extra.append(pytest_html.extras.text("这里是xxx自动化测试用例", name="文本"))
# 注意:实际报告上会直接显示图片,不会有图片的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):
# 增加HTML
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"))
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):
# 注意:这个语句不能放在xfail之后
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("这条用例跳过")
首先修改一下测试方法,给部分测试方法增加文档注释
在conftest.py中增加如下代码
from datetime import datetime
def pytest_html_results_table_header(cells):
"""
处理结果表的表头
"""
# 往表格增加一列Description,并且给Description列增加排序
cells.insert(2, html.th("Description", class_="sortable desc", col="desc"))
# 往表格增加一列Time,并且给Time列增加排序
cells.insert(1, html.th("Time", class_="sortable time", col="time"))
# 移除表格最后一列
cells.pop()
def pytest_html_results_table_row(report, cells):
"""
处理结果表的行
"""
# 往列 Description插入每行的值
cells.insert(2, html.th(report.description))
# 往列 Time 插入每行的值
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()
# 定义列 Description的值,默认为测试方法的文档注释,如果测试方法没有文档注释,就自定义Description的值
if str(item.function.__doc__) != "None":
# 结果表的description列的值 = 测试方法的文档注释
report.description = str(item.function.__doc__)
else:
# 结果表的description列的值 = 自定义的信息
# 注意:这里可以将测试用例中的用例标题或者描述作为列 Description的值
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"))
运行后产生的报告如下:
默认情况下,结果表中的所有行都是展开显示的。如下图所示:
我们可以通过在pytest的配置文件pytest.ini中设置来决定是否展开还是收起。
[pytest]
# 收起结果表中的所有行
render_collapsed = True
重新运行生成报告后如下图所示:
官方文档这里提出的设置查询参数,没有搞明白怎么设置,有搞明白的,欢迎给我留言~
官方文档这里提出的设置查询参数,没有搞明白怎么设置,有搞明白的,欢迎给我留言~
默认情况下,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