Skip to content

Commit fca462c

Browse files
authored
Merge pull request #5924 from blueyed/improve-list-diff
Improve full diff output for lists
2 parents 5186635 + 946434c commit fca462c

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)