From 537be6742dded39c5c461027675425bbf483c23d Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 26 Oct 2026 12:56:43 +0100 Subject: [PATCH] test(audit): pin the duplicate identity, nested test files, the exempt suffix and raises In the #103 review these parts of the test-quality gate could change with the gate's own tests green, and the review agreed to pin them in a follow-up: - each part of a test's signature in the duplicate identity: keyword-only and positional-only parameters, keyword-only defaults, `*args` and `**kwargs`; - `rglob` for both file patterns in `audit_tree`, so a test file in a subdirectory is audited; - the `(exempt)` suffix in the report, on an exempt test only; - `mock_echo` skipping a patched test that expects a raise. Each of the 10 mutants (one part of the identity dropped, `glob` for either pattern, the suffix never or always printed, `not t.raises` dropped) passed the gate's tests and now fails one. Test-only change. Signed-off-by: Anton Volkov --- dokimi/tests/test_audit_test_quality.py | 58 ++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/dokimi/tests/test_audit_test_quality.py b/dokimi/tests/test_audit_test_quality.py index 1f54bae00..096dd8348 100644 --- a/dokimi/tests/test_audit_test_quality.py +++ b/dokimi/tests/test_audit_test_quality.py @@ -154,6 +154,38 @@ class TestTwo: def test_a(self): assert run() == 1 """, + # every part of the signature counts: keyword-only and positional-only fixtures, + # keyword-only defaults, *args and **kwargs + """ + def test_a(*, tmp_path): + assert run() == 1 + def test_b(*, monkeypatch): + assert run() == 1 + """, + """ + def test_a(tmp_path, /): + assert run() == 1 + def test_b(monkeypatch, /): + assert run() == 1 + """, + """ + def test_a(*, x=1): + assert transform(x) == x * 10 + def test_b(*, x=2): + assert transform(x) == x * 10 + """, + """ + def test_a(*args): + assert run() == 1 + def test_b(): + assert run() == 1 + """, + """ + def test_a(**kwargs): + assert run() == 1 + def test_b(): + assert run() == 1 + """, ]) def test_a_body_with_other_inputs_is_not_a_duplicate(source): assert "duplicate" not in {f for flags in _flags(source).values() for f in flags} @@ -262,13 +294,23 @@ def test_the_report_and_json_list_every_flagged_test(tmp_path, capsys): ("test_mod.py", "test_x", ["no_assert"], False)] -def test_every_file_pytest_collects_is_audited(tmp_path): +@pytest.mark.parametrize("where", [".", "unit/llm"]) +def test_every_file_pytest_collects_is_audited(tmp_path, where): + folder = tmp_path / where + folder.mkdir(parents=True, exist_ok=True) for name in ("test_a.py", "b_test.py"): - (tmp_path / name).write_text(textwrap.dedent(FLAGGED["no_assert"]), encoding="utf-8") + (folder / name).write_text(textwrap.dedent(FLAGGED["no_assert"]), encoding="utf-8") flagged, total = atq.audit_tree(tmp_path) assert (sorted(Path(a.file).name for a in flagged), total) == (["b_test.py", "test_a.py"], 2) +def test_the_report_marks_only_an_exempt_test_as_exempt(): + flagged = [atq.Audit("tests/test_m.py", 3, "test_x", ("no_assert",), exempt=True), + atq.Audit("tests/test_m.py", 7, "test_y", ("no_assert",))] + assert atq.report(flagged, 2).splitlines()[-2:] == [ + "tests/test_m.py::test_x no_assert (exempt)", "tests/test_m.py::test_y no_assert"] + + def test_constructor_tracking_invalidates_after_mutation(): """A mutation after construction invalidates the echo check.""" flags = _flags(""" @@ -293,6 +335,18 @@ def test_tuple_and_value(): assert "mock_echo" not in flags["test_tuple_and_value"] +def test_a_patched_test_that_expects_a_raise_is_not_a_mock_echo(): + """The raise is the outcome; the called check next to it does not make it an echo.""" + flags = _flags(""" + def test_x(): + with patch("m.y") as y: + with pytest.raises(ValueError): + run() + assert y.called + """) + assert "mock_echo" not in flags["test_x"] + + def test_weak_assert_with_asserting_helper_is_not_type_only(): """A weak direct assert plus an asserting helper counts as behavioral.""" flags = _flags("""