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