Add pytest_report_serialize and pytest_report_unserialize hooks
These hooks will be used by pytest-xdist and pytest-subtests to serialize and customize reports.
This commit is contained in:
parent
0c63f99016
commit
7b9a414524
|
@ -140,6 +140,7 @@ default_plugins = (
|
||||||
"stepwise",
|
"stepwise",
|
||||||
"warnings",
|
"warnings",
|
||||||
"logging",
|
"logging",
|
||||||
|
"reports",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -375,6 +375,41 @@ def pytest_runtest_logreport(report):
|
||||||
the respective phase of executing a test. """
|
the respective phase of executing a test. """
|
||||||
|
|
||||||
|
|
||||||
|
@hookspec(firstresult=True)
|
||||||
|
def pytest_report_serialize(config, report):
|
||||||
|
"""
|
||||||
|
.. warning::
|
||||||
|
This hook is experimental and subject to change between pytest releases, even
|
||||||
|
bug fixes.
|
||||||
|
|
||||||
|
The intent is for this to be used by plugins maintained by the core-devs, such
|
||||||
|
as ``pytest-xdist``, ``pytest-subtests``, and as a replacement for the internal
|
||||||
|
'resultlog' plugin.
|
||||||
|
|
||||||
|
In the future it might become part of the public hook API.
|
||||||
|
|
||||||
|
Serializes the given report object into a data structure suitable for sending
|
||||||
|
over the wire, or converted to JSON.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@hookspec(firstresult=True)
|
||||||
|
def pytest_report_unserialize(config, data):
|
||||||
|
"""
|
||||||
|
.. warning::
|
||||||
|
This hook is experimental and subject to change between pytest releases, even
|
||||||
|
bug fixes.
|
||||||
|
|
||||||
|
The intent is for this to be used by plugins maintained by the core-devs, such
|
||||||
|
as ``pytest-xdist``, ``pytest-subtests``, and as a replacement for the internal
|
||||||
|
'resultlog' plugin.
|
||||||
|
|
||||||
|
In the future it might become part of the public hook API.
|
||||||
|
|
||||||
|
Restores a report object previously serialized with pytest_report_serialize().;
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# Fixture related hooks
|
# Fixture related hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
|
@ -404,3 +404,19 @@ class CollectErrorRepr(TerminalRepr):
|
||||||
|
|
||||||
def toterminal(self, out):
|
def toterminal(self, out):
|
||||||
out.line(self.longrepr, red=True)
|
out.line(self.longrepr, red=True)
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_report_serialize(report):
|
||||||
|
if isinstance(report, (TestReport, CollectReport)):
|
||||||
|
data = report._to_json()
|
||||||
|
data["_report_type"] = report.__class__.__name__
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_report_unserialize(data):
|
||||||
|
if "_report_type" in data:
|
||||||
|
if data["_report_type"] == "TestReport":
|
||||||
|
return TestReport._from_json(data)
|
||||||
|
elif data["_report_type"] == "CollectReport":
|
||||||
|
return CollectReport._from_json(data)
|
||||||
|
assert "Unknown report_type unserialize data: {}".format(data["_report_type"])
|
||||||
|
|
|
@ -181,3 +181,53 @@ class TestReportSerialization(object):
|
||||||
assert newrep.skipped == rep.skipped
|
assert newrep.skipped == rep.skipped
|
||||||
if rep.failed:
|
if rep.failed:
|
||||||
assert newrep.longrepr == str(rep.longrepr)
|
assert newrep.longrepr == str(rep.longrepr)
|
||||||
|
|
||||||
|
|
||||||
|
class TestHooks:
|
||||||
|
"""Test that the hooks are working correctly for plugins"""
|
||||||
|
|
||||||
|
def test_test_report(self, testdir, pytestconfig):
|
||||||
|
testdir.makepyfile(
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
def test_a(): assert False
|
||||||
|
def test_b(): pass
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
reprec = testdir.inline_run()
|
||||||
|
reports = reprec.getreports("pytest_runtest_logreport")
|
||||||
|
assert len(reports) == 6
|
||||||
|
for rep in reports:
|
||||||
|
data = pytestconfig.hook.pytest_report_serialize(
|
||||||
|
config=pytestconfig, report=rep
|
||||||
|
)
|
||||||
|
assert data["_report_type"] == "TestReport"
|
||||||
|
new_rep = pytestconfig.hook.pytest_report_unserialize(
|
||||||
|
config=pytestconfig, data=data
|
||||||
|
)
|
||||||
|
assert new_rep.nodeid == rep.nodeid
|
||||||
|
assert new_rep.when == rep.when
|
||||||
|
assert new_rep.outcome == rep.outcome
|
||||||
|
|
||||||
|
def test_collect_report(self, testdir, pytestconfig):
|
||||||
|
testdir.makepyfile(
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
def test_a(): assert False
|
||||||
|
def test_b(): pass
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
reprec = testdir.inline_run()
|
||||||
|
reports = reprec.getreports("pytest_collectreport")
|
||||||
|
assert len(reports) == 2
|
||||||
|
for rep in reports:
|
||||||
|
data = pytestconfig.hook.pytest_report_serialize(
|
||||||
|
config=pytestconfig, report=rep
|
||||||
|
)
|
||||||
|
assert data["_report_type"] == "CollectReport"
|
||||||
|
new_rep = pytestconfig.hook.pytest_report_unserialize(
|
||||||
|
config=pytestconfig, data=data
|
||||||
|
)
|
||||||
|
assert new_rep.nodeid == rep.nodeid
|
||||||
|
assert new_rep.when == "collect"
|
||||||
|
assert new_rep.outcome == rep.outcome
|
||||||
|
|
Loading…
Reference in New Issue