Skip to content

Commit ac7fabf

Browse files
authored
Merge pull request #21 from SmithChart/post-mortem
Add post-mortem information collection for failed tests
2 parents b659473 + 23ce352 commit ac7fabf

File tree

4 files changed

+80
-1
lines changed

4 files changed

+80
-1
lines changed

conftest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
import pytest
77

8+
pytest_plugins = ["postmortem"]
9+
810

911
@pytest.fixture(scope="function")
1012
def barebox(strategy):

lxatacstrategy.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,31 @@ def activate_optionals(self):
204204
if self.ethmux:
205205
self.target.activate(self.ethmux)
206206
self.ethmux.set(True) # Connect upstream Ethernet to Lab network as default
207+
208+
def postmortem_info(self) -> dict[str, list[str]]:
209+
pm_info: dict[str, list[str]] = {"status": [self.status.name]}
210+
211+
def get_info(shell, command):
212+
pm_info[command] = shell.run_check(command)
213+
214+
if self.status == Status.barebox:
215+
get_info(self.barebox, "version")
216+
get_info(self.barebox, "mount")
217+
get_info(self.barebox, "global")
218+
get_info(self.barebox, "nv")
219+
get_info(self.barebox, "dmesg")
220+
elif self.status == Status.shell:
221+
get_info(self.shell, "uname -a")
222+
get_info(self.shell, "cat /etc/os-release")
223+
get_info(self.shell, "cat /etc/buildinfo")
224+
get_info(self.shell, "dmesg -l 5")
225+
get_info(self.shell, "findmnt")
226+
get_info(self.shell, "lsns")
227+
get_info(self.shell, "ip -brief address")
228+
get_info(self.shell, "ip -brief route")
229+
get_info(self.shell, "ip -brief -6 route")
230+
get_info(self.shell, "df --human-readable")
231+
get_info(self.shell, "free -m")
232+
get_info(self.shell, "systemctl list-units --failed")
233+
234+
return pm_info

postmortem.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import logging
2+
3+
import pytest
4+
from pytest import CollectReport, StashKey
5+
6+
_phase_report_key = StashKey[dict[str, CollectReport]]()
7+
_pm_logger = logging.getLogger("post-mortem")
8+
9+
10+
@pytest.hookimpl(wrapper=True, tryfirst=True)
11+
def pytest_runtest_makereport(item: pytest.Item, call: pytest.CallInfo[None]):
12+
"""
13+
Make the report for a step available in the item's stash, so that
14+
fixtures can read the result in their teardown phase.
15+
Heavily inspired by: https://docs.pytest.org/en/latest/example/simple.html#making-test-result-information-available-in-fixtures
16+
Implements the runtest_makereport-hook: https://docs.pytest.org/en/latest/reference/reference.html#std-hook-pytest_runtest_makereport
17+
18+
:param item: The item the report is generated for.
19+
:param call: CallInfo for this phase
20+
:return: The report re received from the previous hook.
21+
"""
22+
rep = yield
23+
24+
# store test results for each phase of a call, which can
25+
# be "setup", "call", "teardown"
26+
item.stash.setdefault(_phase_report_key, {})[rep.when] = rep
27+
return rep
28+
29+
30+
@pytest.fixture(autouse=True)
31+
def pm_system(request: pytest.FixtureRequest, strategy, record_property):
32+
"""
33+
Retrieves post-mortem diagnosis information from the strategy and emits the information to the log with level
34+
WARNING and also adds the information to the `junit.xml`.
35+
36+
The strategy must implement a strategy.postmotem_info().
37+
It is up to the strategy to decide which information to collect depending on the DUTs status and the connections
38+
available (e.g. serial or ssh).
39+
"""
40+
yield
41+
42+
report = request.node.stash[_phase_report_key]
43+
if "call" in report and report["call"].failed:
44+
post_mortem_info: dict[str, list[str]] = strategy.postmortem_info()
45+
record_property("postmortem", post_mortem_info)
46+
for key, value in post_mortem_info.items():
47+
_pm_logger.warning(f"POST-MORTEM INFO: {key}")
48+
for line in value:
49+
_pm_logger.warning(f"| {line}")

tests/test_tacd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def test_tacd_http_temperature(strategy, shell):
3434
(-0.01, 14, "v1/iobus/feedback/voltage"),
3535
),
3636
)
37-
def test_tacd_http_adc(strategy, low, high, endpoint):
37+
def test_tacd_http_adc(strategy, shell, low, high, endpoint):
3838
"""Test tacd ADC endpoints."""
3939
r = requests.get(f"http://{strategy.network.address}/{endpoint}")
4040
assert r.status_code == 200

0 commit comments

Comments
 (0)