Skip to content

Commit 4f33f46

Browse files
authored
Merge pull request #5026 from blueyed/compare-len-diff
Display number of different items with sequence/dict comparisons
2 parents 8ad99c5 + 0f965e5 commit 4f33f46

File tree

3 files changed

+83
-18
lines changed

3 files changed

+83
-18
lines changed

changelog/5026.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Assertion failure messages for sequences and dicts contain the number of different items now.

src/_pytest/assertion/util.py

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -285,20 +285,30 @@ def _compare_eq_iterable(left, right, verbose=0):
285285

286286
def _compare_eq_sequence(left, right, verbose=0):
287287
explanation = []
288-
for i in range(min(len(left), len(right))):
288+
len_left = len(left)
289+
len_right = len(right)
290+
for i in range(min(len_left, len_right)):
289291
if left[i] != right[i]:
290292
explanation += [u"At index %s diff: %r != %r" % (i, left[i], right[i])]
291293
break
292-
if len(left) > len(right):
293-
explanation += [
294-
u"Left contains more items, first extra item: %s"
295-
% saferepr(left[len(right)])
296-
]
297-
elif len(left) < len(right):
298-
explanation += [
299-
u"Right contains more items, first extra item: %s"
300-
% saferepr(right[len(left)])
301-
]
294+
len_diff = len_left - len_right
295+
296+
if len_diff:
297+
if len_diff > 0:
298+
dir_with_more = "Left"
299+
extra = saferepr(left[len_right])
300+
else:
301+
len_diff = 0 - len_diff
302+
dir_with_more = "Right"
303+
extra = saferepr(right[len_left])
304+
305+
if len_diff == 1:
306+
explanation += [u"%s contains one more item: %s" % (dir_with_more, extra)]
307+
else:
308+
explanation += [
309+
u"%s contains %d more items, first extra item: %s"
310+
% (dir_with_more, len_diff, extra)
311+
]
302312
return explanation
303313

304314

@@ -319,7 +329,9 @@ def _compare_eq_set(left, right, verbose=0):
319329

320330
def _compare_eq_dict(left, right, verbose=0):
321331
explanation = []
322-
common = set(left).intersection(set(right))
332+
set_left = set(left)
333+
set_right = set(right)
334+
common = set_left.intersection(set_right)
323335
same = {k: left[k] for k in common if left[k] == right[k]}
324336
if same and verbose < 2:
325337
explanation += [u"Omitting %s identical items, use -vv to show" % len(same)]
@@ -331,15 +343,23 @@ def _compare_eq_dict(left, right, verbose=0):
331343
explanation += [u"Differing items:"]
332344
for k in diff:
333345
explanation += [saferepr({k: left[k]}) + " != " + saferepr({k: right[k]})]
334-
extra_left = set(left) - set(right)
335-
if extra_left:
336-
explanation.append(u"Left contains more items:")
346+
extra_left = set_left - set_right
347+
len_extra_left = len(extra_left)
348+
if len_extra_left:
349+
explanation.append(
350+
u"Left contains %d more item%s:"
351+
% (len_extra_left, "" if len_extra_left == 1 else "s")
352+
)
337353
explanation.extend(
338354
pprint.pformat({k: left[k] for k in extra_left}).splitlines()
339355
)
340-
extra_right = set(right) - set(left)
341-
if extra_right:
342-
explanation.append(u"Right contains more items:")
356+
extra_right = set_right - set_left
357+
len_extra_right = len(extra_right)
358+
if len_extra_right:
359+
explanation.append(
360+
u"Right contains %d more item%s:"
361+
% (len_extra_right, "" if len_extra_right == 1 else "s")
362+
)
343363
explanation.extend(
344364
pprint.pformat({k: right[k] for k in extra_right}).splitlines()
345365
)

testing/test_assertion.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,50 @@ def test_dict_omitting_with_verbosity_2(self):
446446
assert "Omitting" not in lines[1]
447447
assert lines[2] == "{'b': 1}"
448448

449+
def test_dict_different_items(self):
450+
lines = callequal({"a": 0}, {"b": 1, "c": 2}, verbose=2)
451+
assert lines == [
452+
"{'a': 0} == {'b': 1, 'c': 2}",
453+
"Left contains 1 more item:",
454+
"{'a': 0}",
455+
"Right contains 2 more items:",
456+
"{'b': 1, 'c': 2}",
457+
"Full diff:",
458+
"- {'a': 0}",
459+
"+ {'b': 1, 'c': 2}",
460+
]
461+
lines = callequal({"b": 1, "c": 2}, {"a": 0}, verbose=2)
462+
assert lines == [
463+
"{'b': 1, 'c': 2} == {'a': 0}",
464+
"Left contains 2 more items:",
465+
"{'b': 1, 'c': 2}",
466+
"Right contains 1 more item:",
467+
"{'a': 0}",
468+
"Full diff:",
469+
"- {'b': 1, 'c': 2}",
470+
"+ {'a': 0}",
471+
]
472+
473+
def test_sequence_different_items(self):
474+
lines = callequal((1, 2), (3, 4, 5), verbose=2)
475+
assert lines == [
476+
"(1, 2) == (3, 4, 5)",
477+
"At index 0 diff: 1 != 3",
478+
"Right contains one more item: 5",
479+
"Full diff:",
480+
"- (1, 2)",
481+
"+ (3, 4, 5)",
482+
]
483+
lines = callequal((1, 2, 3), (4,), verbose=2)
484+
assert lines == [
485+
"(1, 2, 3) == (4,)",
486+
"At index 0 diff: 1 != 4",
487+
"Left contains 2 more items, first extra item: 2",
488+
"Full diff:",
489+
"- (1, 2, 3)",
490+
"+ (4,)",
491+
]
492+
449493
def test_set(self):
450494
expl = callequal({0, 1}, {0, 2})
451495
assert len(expl) > 1

0 commit comments

Comments
 (0)