|
| 1 | +"""Extend the pytest-json-report plugin with a new "reruns" attribute. |
| 2 | +
|
| 3 | +Each test will (if it's run more than once) store its prior results in a |
| 4 | +`reruns` array attribute, where each item may have `setup` `call` and |
| 5 | +`teardown` sections. |
| 6 | +
|
| 7 | +See also: |
| 8 | + * https://github.com/pytest-dev/pytest-rerunfailures |
| 9 | + * https://github.com/numirias/pytest-json-report |
| 10 | + * https://getsentry.atlassian.net/browse/DEVINFRA-630 |
| 11 | +""" |
| 12 | + |
| 13 | +import pytest |
| 14 | +import pytest_jsonreport.plugin |
| 15 | + |
| 16 | +JSONTestItem = dict[str, list[object]] |
| 17 | +JSONTestItems = dict[str, JSONTestItem] |
| 18 | + |
| 19 | + |
| 20 | +def pytest_plugin_registered(plugin: object, manager: pytest.PytestPluginManager) -> None: |
| 21 | + """Only register if/when the plugin we're extending is registered.""" |
| 22 | + if isinstance(plugin, pytest_jsonreport.plugin.JSONReport): |
| 23 | + json_tests = getattr(plugin, "_json_tests") |
| 24 | + manager.register(PytestRerunJSONReporter(json_tests)) |
| 25 | + |
| 26 | + |
| 27 | +class PytestRerunJSONReporter: |
| 28 | + def __init__(self, json_tests: JSONTestItems): |
| 29 | + self.json_tests = json_tests |
| 30 | + |
| 31 | + def pytest_json_runtest_stage(self, report: pytest.TestReport) -> None: |
| 32 | + assert self.json_tests is not None |
| 33 | + |
| 34 | + nodeid = report.nodeid |
| 35 | + json_testitem = self.json_tests[nodeid] |
| 36 | + if report.when in json_testitem: |
| 37 | + # this is a new result of some kind -- record all prior data as a |
| 38 | + # "rerun" and start over fresh |
| 39 | + reruns = json_testitem.setdefault("reruns", []) |
| 40 | + reruns.append( |
| 41 | + { |
| 42 | + key: json_testitem.pop(key) |
| 43 | + for key in ("setup", "call", "teardown") |
| 44 | + if key in json_testitem |
| 45 | + } |
| 46 | + ) |
0 commit comments