Skip to content

Commit ee04515

Browse files
[test] Cover the empty-iterable and plain-assert-mode branches
Adds two regression tests to close the patch-coverage gaps in ``callbinrepr`` reported by codecov on PR pytest-dev#14523: * a plugin returning a truthy-but-empty iterator (``iter([])``) to exercise the second ``if not new_expl: continue`` after ``materialize_with_truncation``. * a ``--assert=plain`` run to exercise the false branch of the ``assertmode == "rewrite"`` guard. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4ee9dfe commit ee04515

1 file changed

Lines changed: 48 additions & 2 deletions

File tree

testing/test_assertion.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2299,8 +2299,7 @@ def raise_exit(obj):
22992299
def test_plugin_hook_returning_none_is_skipped(pytester: Pytester) -> None:
23002300
"""A ``pytest_assertrepr_compare`` impl returning ``None`` is skipped
23012301
so the next impl (or the built-in) can produce the explanation.
2302-
Covers the ``if new_expl is None: continue`` branch in
2303-
``callbinrepr``.
2302+
Covers the ``if not new_expl: continue`` branch in ``callbinrepr``.
23042303
"""
23052304
pytester.makeconftest(
23062305
"""
@@ -2323,6 +2322,53 @@ def test_diff():
23232322
)
23242323

23252324

2325+
def test_plugin_hook_returning_empty_iterator_is_skipped(pytester: Pytester) -> None:
2326+
"""A plugin returning a truthy but ultimately empty iterable is
2327+
skipped after materialisation. Covers the second
2328+
``if not new_expl: continue`` branch in ``callbinrepr``.
2329+
"""
2330+
pytester.makeconftest(
2331+
"""
2332+
def pytest_assertrepr_compare(op, left, right):
2333+
# An iterator object is truthy, so it slips past the first
2334+
# falsy check; once materialised through truncation it is
2335+
# empty and the dispatcher must move on.
2336+
return iter([])
2337+
"""
2338+
)
2339+
pytester.makepyfile(
2340+
"""
2341+
def test_diff():
2342+
assert {1, 2} == {1, 3}
2343+
"""
2344+
)
2345+
result = pytester.runpytest()
2346+
# The built-in set-comparison explanation still reaches the user.
2347+
result.stdout.fnmatch_lines(
2348+
["*Extra items in the left set:*", "*Extra items in the right set:*"]
2349+
)
2350+
2351+
2352+
def test_callbinrepr_plain_assert_mode(pytester: Pytester) -> None:
2353+
"""In ``--assert=plain`` mode ``callbinrepr`` skips the ``%`` escape.
2354+
Covers the false branch of ``if item.config.getvalue("assertmode")
2355+
== "rewrite"``.
2356+
"""
2357+
pytester.makepyfile(
2358+
"""
2359+
def test_diff():
2360+
assert {1, 2} == {1, 3}
2361+
"""
2362+
)
2363+
result = pytester.runpytest("--assert=plain")
2364+
# In plain mode the comparator still runs via ``callbinrepr`` (it
2365+
# is the rewrite escaping that's skipped), so the explanation is
2366+
# still produced.
2367+
result.stdout.fnmatch_lines(
2368+
["*Extra items in the left set:*", "*Extra items in the right set:*"]
2369+
)
2370+
2371+
23262372
def test_exception_before_first_yield_emits_summary_and_notice(monkeypatch) -> None:
23272373
"""When the comparator raises *before* any explanation line has been
23282374
yielded, ``assertrepr_compare`` should still produce the summary so

0 commit comments

Comments
 (0)