This commit is contained in:
parent
01b5e73ea4
commit
a068e4b612
2 changed files with 55 additions and 2 deletions
|
|
@ -96,15 +96,24 @@ def pytest_sessionfinish(session, exitstatus) -> None:
|
|||
unlisted = sorted(_observed_skips - _allowed_skips())
|
||||
if not unlisted:
|
||||
return
|
||||
print(
|
||||
f"\nНЕУЧТЁННЫЙ ПРОПУСК ({len(unlisted)}): проверка не исполнилась и не "
|
||||
head = (
|
||||
f"НЕУЧТЁННЫЙ ПРОПУСК ({len(unlisted)}): проверка не исполнилась и не "
|
||||
f"объявлена в {_SKIP_ALLOWLIST_PATH.name}:"
|
||||
)
|
||||
print(f"\n{head}")
|
||||
for nodeid in unlisted:
|
||||
print(f" - {nodeid}")
|
||||
print(
|
||||
"Почини тест либо внеси его в skip_allowlist.txt с причиной — "
|
||||
"пропуск без записи неотличим от пройденной проверки."
|
||||
)
|
||||
# #2871: под Actions дублируем в ::error:: — иначе сообщение тонет.
|
||||
# 13.08 этот сторож четыре прогона подряд ронял job'у совершенно правильно,
|
||||
# а его строка лежала посреди тысячи других (обычный print, по-русски) —
|
||||
# и поиск по «FAILED / ERROR» её не находил. Причину искали три часа
|
||||
# в диске, раннере, покрытии и кэше. Сторож, который роняет прогон,
|
||||
# обязан кричать так, чтобы его нашли.
|
||||
if os.environ.get("GITHUB_ACTIONS") or os.environ.get("CI"):
|
||||
print(f"::error::{head} " + "; ".join(unlisted))
|
||||
if exitstatus == 0:
|
||||
session.exitstatus = 1
|
||||
|
|
|
|||
44
backend/tests/test_skip_guard_loud.py
Normal file
44
backend/tests/test_skip_guard_loud.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
"""Проверка, что сторож пропусков кричит под Actions (#2871)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import types
|
||||
|
||||
import tests.conftest as ct
|
||||
|
||||
|
||||
def _run_guard(monkeypatch, capsys, *, ci: bool, observed: set[str]) -> str:
|
||||
monkeypatch.setattr(ct, "_observed_skips", observed)
|
||||
monkeypatch.setattr(ct, "_allowed_skips", lambda: set())
|
||||
monkeypatch.delenv("GITHUB_ACTIONS", raising=False)
|
||||
monkeypatch.delenv("CI", raising=False)
|
||||
if ci:
|
||||
monkeypatch.setenv("GITHUB_ACTIONS", "true")
|
||||
session = types.SimpleNamespace(exitstatus=0)
|
||||
ct.pytest_sessionfinish(session, 0)
|
||||
return capsys.readouterr().out, session.exitstatus
|
||||
|
||||
|
||||
def test_guard_emits_error_annotation_under_actions(monkeypatch, capsys) -> None:
|
||||
out, rc = _run_guard(monkeypatch, capsys, ci=True, observed={"tests/x.py::test_y"})
|
||||
assert "::error::" in out, "под Actions сторож обязан подниматься в аннотации"
|
||||
assert "tests/x.py::test_y" in out
|
||||
assert rc == 1
|
||||
|
||||
|
||||
def test_guard_stays_quiet_locally(monkeypatch, capsys) -> None:
|
||||
"""Контроль: локально ::error:: не нужен, человеческое сообщение остаётся."""
|
||||
out, rc = _run_guard(monkeypatch, capsys, ci=False, observed={"tests/x.py::test_y"})
|
||||
assert "::error::" not in out
|
||||
assert "НЕУЧТЁННЫЙ ПРОПУСК" in out
|
||||
assert rc == 1
|
||||
|
||||
|
||||
def test_guard_silent_when_all_skips_declared(monkeypatch, capsys) -> None:
|
||||
"""Контроль: без незадекларированных пропусков сторож молчит и не роняет."""
|
||||
monkeypatch.setattr(ct, "_observed_skips", set())
|
||||
monkeypatch.setattr(ct, "_allowed_skips", lambda: set())
|
||||
session = types.SimpleNamespace(exitstatus=0)
|
||||
ct.pytest_sessionfinish(session, 0)
|
||||
assert capsys.readouterr().out == ""
|
||||
assert session.exitstatus == 0
|
||||
Loading…
Add table
Reference in a new issue