ariadne/tests/test_hermes_incident_evidence_section.py

156 lines
4.8 KiB
Python
Raw Permalink Normal View History

"""Tests for showing the failure itself in a triage issue."""
from __future__ import annotations
import pytest
from ariadne.services import hermes_incident_evidence_section as module
from ariadne.services import hermes_incident_body as body
TRACE = (
"tests/test_utils.py:212: in test_safe_error_detail\n"
" assert 'bad things' in safe_error_detail(exc)\n"
"E AssertionError: assert 'bad things' in 'http 400'"
)
def _bundle(**jenkins):
return {"jenkins": jenkins}
def test_the_traceback_is_shown_not_merely_cited() -> None:
"""Citing a console line number makes a maintainer reconstruct the failure."""
section = module.evidence_section(
_bundle(failed_tests=[{"name": "t", "errorStackTrace": TRACE}])
)
assert section.startswith("## Evidence")
assert "The failing test's traceback" in section
assert "AssertionError: assert 'bad things' in 'http 400'" in section
assert section.count("```") == 2
def test_the_stack_trace_is_preferred_over_the_assertion_line() -> None:
"""The assertion says what was wrong; the trace says where."""
section = module.evidence_section(
_bundle(failed_tests=[{"errorDetails": "AssertionError: nope", "errorStackTrace": TRACE}])
)
assert "tests/test_utils.py:212" in section
assert "AssertionError: nope" not in section
def test_the_assertion_is_used_when_no_trace_was_published() -> None:
section = module.evidence_section(
_bundle(failed_tests=[{"errorDetails": "AssertionError: nope"}])
)
assert "AssertionError: nope" in section
def test_a_test_without_either_field_is_skipped() -> None:
section = module.evidence_section(
_bundle(
failed_tests=[
{"name": "a"},
{"name": "b", "errorStackTrace": " "},
"not-a-dict",
{"name": "c", "errorStackTrace": TRACE},
]
)
)
assert "tests/test_utils.py:212" in section
def test_the_console_region_is_used_when_no_tests_were_published() -> None:
"""A build whose runner published nothing still has a console to quote."""
section = module.evidence_section(
_bundle(console_failures=[{"text": "Traceback\n File x\nValueError: boom"}])
)
assert "The earliest failure region" in section
assert "ValueError: boom" in section
def test_the_region_keeps_its_last_lines_when_it_is_long() -> None:
"""The tail of a failure region holds the failure; the head approaches it."""
text = "\n".join([f"line {i}" for i in range(100)] + ["ValueError: boom"])
section = module.evidence_section(_bundle(console_failures=[{"text": text}]))
assert "ValueError: boom" in section
assert "line 0" not in section
def test_a_long_trace_is_truncated_with_a_pointer_to_the_build() -> None:
section = module.evidence_section(
_bundle(failed_tests=[{"errorStackTrace": "x" * 9000}])
)
assert len(section) < 3000
assert "truncated" in section
assert section.rstrip().endswith("```")
def test_a_fence_inside_the_excerpt_cannot_end_the_block_early() -> None:
"""Raw log text must not be able to break out into the rendered issue."""
section = module.evidence_section(
_bundle(failed_tests=[{"errorStackTrace": "before\n```\nafter"}])
)
assert section.count("```") == 2
assert "after" in section
@pytest.mark.parametrize(
"bundle",
[
None,
{},
"not-a-dict",
{"jenkins": "not-a-dict"},
{"jenkins": {}},
{"jenkins": {"failed_tests": [], "console_failures": []}},
{"jenkins": {"failed_tests": None, "console_failures": None}},
{"jenkins": {"console_failures": [{"text": " "}, "not-a-dict"]}},
],
)
def test_a_bundle_with_nothing_to_quote_renders_no_heading(bundle) -> None:
"""An empty Evidence heading is worse than no heading."""
assert module.evidence_section(bundle) == ""
def test_the_issue_body_carries_the_excerpt_and_keeps_its_marker() -> None:
rendered = body.issue_body(
{
"incident_id": "ariadne/408",
"job": "ariadne",
"build_number": 408,
"classification": "pytest_test_failure",
"reason": "a repository test failure",
"run_id": "run-1",
"bundle": _bundle(failed_tests=[{"errorStackTrace": TRACE}]),
}
)
assert "## Evidence" in rendered
assert "tests/test_utils.py:212" in rendered
assert rendered.index("## Evidence") < rendered.index("## Links")
assert rendered.rstrip().endswith("-->")
def test_an_issue_without_a_bundle_still_renders() -> None:
rendered = body.issue_body(
{"incident_id": "a/1", "job": "a", "build_number": 1, "reason": "r", "run_id": "x"}
)
assert "## Evidence" not in rendered
assert rendered.rstrip().endswith("-->")