Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/13652.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``contains one more item`` now reports the actual extra item in sequence diffs.
16 changes: 14 additions & 2 deletions src/_pytest/assertion/_compare_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ def _compare_eq_sequence(
comparing_bytes = isinstance(left, bytes) and isinstance(right, bytes)
len_left = len(left)
len_right = len(right)
found_diff = False
i = -1
for i in range(min(len_left, len_right)):
if left[i] != right[i]:
if comparing_bytes:
Expand All @@ -73,6 +75,7 @@ def _compare_eq_sequence(
f"At index {i} diff:"
f" {highlighter(repr(left_value))} != {highlighter(repr(right_value))}"
)
found_diff = True
break

if comparing_bytes:
Expand All @@ -84,11 +87,20 @@ def _compare_eq_sequence(
if len_diff:
if len_diff > 0:
dir_with_more = "Left"
extra = saferepr(left[len_right])
# If the longer side has exactly one extra item and the tails after
# the first differing index align (offset by one), that item is the
# insertion.
if found_diff and len_diff == 1 and left[i + 1 :] == right[i:]:
extra = saferepr(left[i])
else:
extra = saferepr(left[len_right])
else:
len_diff = 0 - len_diff
dir_with_more = "Right"
extra = saferepr(right[len_left])
if found_diff and len_diff == 1 and right[i + 1 :] == left[i:]:
extra = saferepr(right[i])
else:
extra = saferepr(right[len_left])

if len_diff == 1:
yield f"{dir_with_more} contains one more item: {highlighter(extra)}"
Expand Down
28 changes: 28 additions & 0 deletions testing/test_assertion.py
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,34 @@ def test_sequence_different_items(self) -> None:
" )",
]

@pytest.mark.parametrize(
("left", "right", "expected"),
[
([], [1], "Right contains one more item: 1"),
([1], [], "Left contains one more item: 1"),
([1, 2, 3], [0, 1, 2, 3], "Right contains one more item: 0"),
([1, 2, 3], [1, 2, 3, 4], "Right contains one more item: 4"),
([1, 2, 3], [1, 2, 0, 3], "Right contains one more item: 0"),
([1, 2, 0, 3], [1, 2, 3], "Left contains one more item: 0"),
([1, 1], [1, 0, 1], "Right contains one more item: 0"),
([3, 4, 5], [1, 2], "Left contains one more item: 5"),
# Fallback: single extra item but tails don't align
([1, 2, 3], [1, 9, 8, 3], "Right contains one more item: 3"),
([1, 9, 8, 3], [1, 2, 3], "Left contains one more item: 3"),
(
[1, 2, 3],
[0, 1, 2, 3, 4],
"Right contains 2 more items, first extra item: 3",
),
],
)
def test_sequence_extra_item_message(
self, left: list[object], right: list[object], expected: str
) -> None:
lines = callequal(left, right, verbose=1)
assert lines is not None
assert expected in lines

def test_set(self) -> None:
expl = callequal({0, 1}, {0, 2})
assert expl is not None
Expand Down
46 changes: 45 additions & 1 deletion testing/test_error_diffs.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def test_this():
> assert result == expected
E assert [1, 3] == [1, 2, 3]
E At index 1 diff: 3 != 2
E Right contains one more item: 3
E Right contains one more item: 2
E Full diff: (-: missing in left side, +: extra in left side)
E [
E 1,
Expand All @@ -76,6 +76,50 @@ def test_this():
""",
id="Compare lists, one item missing",
),
pytest.param(
"""
def test_this():
result = [1, 2, 3]
expected = [1, 2, 0, 3]
assert result == expected
""",
"""
> assert result == expected
E assert [1, 2, 3] == [1, 2, 0, 3]
E At index 2 diff: 3 != 0
E Right contains one more item: 0
E Full diff: (-: missing in left side, +: extra in left side)
E [
E 1,
E 2,
E - 0,
E 3,
E ]
""",
id="Compare lists, one extra item inserted mid-list",
),
pytest.param(
"""
def test_this():
result = [1, 2, 0, 3]
expected = [1, 2, 3]
assert result == expected
""",
"""
> assert result == expected
E assert [1, 2, 0, 3] == [1, 2, 3]
E At index 2 diff: 0 != 3
E Left contains one more item: 0
E Full diff: (-: missing in left side, +: extra in left side)
E [
E 1,
E 2,
E + 0,
E 3,
E ]
""",
id="Compare lists, one extra item inserted mid-list on left",
),
pytest.param(
"""
def test_this():
Expand Down