Skip to content

Commit 946434c

Browse files
committed
Improve full diff output for lists
Massage text input for difflib when comparing pformat output of different line lengths. Also do not strip ndiff output on the left, which currently already removes indenting for lines with no differences. Before: E AssertionError: assert ['version', '...version_info'] == ['version', '...version', ...] E Right contains 3 more items, first extra item: ' ' E Full diff: E - ['version', 'version_info', 'sys.version', 'sys.version_info'] E + ['version', E + 'version_info', E + 'sys.version', E + 'sys.version_info', E + ' ', E + 'sys.version', E + 'sys.version_info'] After: E AssertionError: assert ['version', '...version_info'] == ['version', '...version', ...] E Right contains 3 more items, first extra item: ' ' E Full diff: E [ E 'version', E 'version_info', E 'sys.version', E 'sys.version_info', E + ' ', E + 'sys.version', E + 'sys.version_info', E ]
1 parent 5186635 commit 946434c

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

changelog/5924.feature.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
Improve verbose diff output with sequences.
2+
3+
Before:
4+
5+
.. code-block::
6+
7+
E AssertionError: assert ['version', '...version_info'] == ['version', '...version', ...]
8+
E Right contains 3 more items, first extra item: ' '
9+
E Full diff:
10+
E - ['version', 'version_info', 'sys.version', 'sys.version_info']
11+
E + ['version',
12+
E + 'version_info',
13+
E + 'sys.version',
14+
E + 'sys.version_info',
15+
E + ' ',
16+
E + 'sys.version',
17+
E + 'sys.version_info']
18+
19+
After:
20+
21+
.. code-block::
22+
23+
E AssertionError: assert ['version', '...version_info'] == ['version', '...version', ...]
24+
E Right contains 3 more items, first extra item: ' '
25+
E Full diff:
26+
E [
27+
E 'version',
28+
E 'version_info',
29+
E 'sys.version',
30+
E 'sys.version_info',
31+
E + ' ',
32+
E + 'sys.version',
33+
E + 'sys.version_info',
34+
E ]

src/_pytest/assertion/util.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,18 @@ def _compare_eq_verbose(left, right):
246246
return explanation
247247

248248

249+
def _surrounding_parens_on_own_lines(lines): # type: (List) -> None
250+
"""Move opening/closing parenthesis/bracket to own lines."""
251+
opening = lines[0][:1]
252+
if opening in ["(", "[", "{"]:
253+
lines[0] = " " + lines[0][1:]
254+
lines[:] = [opening] + lines
255+
closing = lines[-1][-1:]
256+
if closing in [")", "]", "}"]:
257+
lines[-1] = lines[-1][:-1] + ","
258+
lines[:] = lines + [closing]
259+
260+
249261
def _compare_eq_iterable(left, right, verbose=0):
250262
if not verbose:
251263
return ["Use -v to get the full diff"]
@@ -254,9 +266,27 @@ def _compare_eq_iterable(left, right, verbose=0):
254266

255267
left_formatting = pprint.pformat(left).splitlines()
256268
right_formatting = pprint.pformat(right).splitlines()
269+
270+
# Re-format for different output lengths.
271+
lines_left = len(left_formatting)
272+
lines_right = len(right_formatting)
273+
if lines_left != lines_right:
274+
if lines_left > lines_right:
275+
max_width = min(len(x) for x in left_formatting)
276+
right_formatting = pprint.pformat(right, width=max_width).splitlines()
277+
lines_right = len(right_formatting)
278+
else:
279+
max_width = min(len(x) for x in right_formatting)
280+
left_formatting = pprint.pformat(left, width=max_width).splitlines()
281+
lines_left = len(left_formatting)
282+
283+
if lines_left > 1 or lines_right > 1:
284+
_surrounding_parens_on_own_lines(left_formatting)
285+
_surrounding_parens_on_own_lines(right_formatting)
286+
257287
explanation = ["Full diff:"]
258288
explanation.extend(
259-
line.strip() for line in difflib.ndiff(left_formatting, right_formatting)
289+
line.rstrip() for line in difflib.ndiff(left_formatting, right_formatting)
260290
)
261291
return explanation
262292

testing/test_assertion.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,55 @@ def test_list_different_lengths(self):
413413
expl = callequal([0, 1, 2], [0, 1])
414414
assert len(expl) > 1
415415

416+
def test_list_wrap_for_multiple_lines(self):
417+
long_d = "d" * 80
418+
l1 = ["a", "b", "c"]
419+
l2 = ["a", "b", "c", long_d]
420+
diff = callequal(l1, l2, verbose=True)
421+
assert diff == [
422+
"['a', 'b', 'c'] == ['a', 'b', 'c...dddddddddddd']",
423+
"Right contains one more item: '" + long_d + "'",
424+
"Full diff:",
425+
" [",
426+
" 'a',",
427+
" 'b',",
428+
" 'c',",
429+
"+ '" + long_d + "',",
430+
" ]",
431+
]
432+
433+
diff = callequal(l2, l1, verbose=True)
434+
assert diff == [
435+
"['a', 'b', 'c...dddddddddddd'] == ['a', 'b', 'c']",
436+
"Left contains one more item: '" + long_d + "'",
437+
"Full diff:",
438+
" [",
439+
" 'a',",
440+
" 'b',",
441+
" 'c',",
442+
"- '" + long_d + "',",
443+
" ]",
444+
]
445+
446+
def test_list_wrap_for_width_rewrap_same_length(self):
447+
long_a = "a" * 30
448+
long_b = "b" * 30
449+
long_c = "c" * 30
450+
l1 = [long_a, long_b, long_c]
451+
l2 = [long_b, long_c, long_a]
452+
diff = callequal(l1, l2, verbose=True)
453+
assert diff == [
454+
"['aaaaaaaaaaa...cccccccccccc'] == ['bbbbbbbbbbb...aaaaaaaaaaaa']",
455+
"At index 0 diff: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' != 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
456+
"Full diff:",
457+
" [",
458+
"- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
459+
" 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',",
460+
" 'cccccccccccccccccccccccccccccc',",
461+
"+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
462+
" ]",
463+
]
464+
416465
def test_dict(self):
417466
expl = callequal({"a": 0}, {"a": 1})
418467
assert len(expl) > 1

0 commit comments

Comments
 (0)