Improve assertion failure reporting on iterables, by using ndiff and pprint.
This commit is contained in:
parent
49b7237581
commit
9a0f2a9fb7
|
@ -1,3 +1,8 @@
|
|||
Unreleased
|
||||
----------
|
||||
|
||||
- Improve assertion failure reporting on iterables, by using ndiff and pprint.
|
||||
|
||||
2.6.3
|
||||
-----------
|
||||
|
||||
|
|
|
@ -135,18 +135,32 @@ def assertrepr_compare(config, op, left, right):
|
|||
isdict = lambda x: isinstance(x, dict)
|
||||
isset = lambda x: isinstance(x, (set, frozenset))
|
||||
|
||||
def isiterable(obj):
|
||||
try:
|
||||
iter(obj)
|
||||
return not istext(obj)
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
verbose = config.getoption('verbose')
|
||||
explanation = None
|
||||
try:
|
||||
if op == '==':
|
||||
if istext(left) and istext(right):
|
||||
explanation = _diff_text(left, right, verbose)
|
||||
elif issequence(left) and issequence(right):
|
||||
explanation = _compare_eq_sequence(left, right, verbose)
|
||||
elif isset(left) and isset(right):
|
||||
explanation = _compare_eq_set(left, right, verbose)
|
||||
elif isdict(left) and isdict(right):
|
||||
explanation = _compare_eq_dict(left, right, verbose)
|
||||
else:
|
||||
if issequence(left) and issequence(right):
|
||||
explanation = _compare_eq_sequence(left, right, verbose)
|
||||
elif isset(left) and isset(right):
|
||||
explanation = _compare_eq_set(left, right, verbose)
|
||||
elif isdict(left) and isdict(right):
|
||||
explanation = _compare_eq_dict(left, right, verbose)
|
||||
if isiterable(left) and isiterable(right):
|
||||
expl = _compare_eq_iterable(left, right, verbose)
|
||||
if explanation is not None:
|
||||
explanation.extend(expl)
|
||||
else:
|
||||
explanation = expl
|
||||
elif op == 'not in':
|
||||
if istext(left) and istext(right):
|
||||
explanation = _notin_text(left, right, verbose)
|
||||
|
@ -203,6 +217,19 @@ def _diff_text(left, right, verbose=False):
|
|||
return explanation
|
||||
|
||||
|
||||
def _compare_eq_iterable(left, right, verbose=False):
|
||||
if not verbose:
|
||||
return [u('Use -v to get the full diff')]
|
||||
# dynamic import to speedup pytest
|
||||
import difflib
|
||||
|
||||
left = pprint.pformat(left).splitlines()
|
||||
right = pprint.pformat(right).splitlines()
|
||||
explanation = [u('Full diff:')]
|
||||
explanation.extend(line.strip() for line in difflib.ndiff(left, right))
|
||||
return explanation
|
||||
|
||||
|
||||
def _compare_eq_sequence(left, right, verbose=False):
|
||||
explanation = []
|
||||
for i in range(min(len(left), len(right))):
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
import py, pytest
|
||||
import _pytest.assertion as plugin
|
||||
from _pytest.assertion import reinterpret
|
||||
from _pytest.assertion import util
|
||||
|
||||
needsnewassert = pytest.mark.skipif("sys.version_info < (2,6)")
|
||||
PY3 = sys.version_info >= (3, 0)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -86,6 +89,48 @@ class TestAssert_reprcompare:
|
|||
expl = callequal([0, 1], [0, 2])
|
||||
assert len(expl) > 1
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
['left', 'right', 'expected'], [
|
||||
([0, 1], [0, 2], """
|
||||
Full diff:
|
||||
- [0, 1]
|
||||
? ^
|
||||
+ [0, 2]
|
||||
? ^
|
||||
"""),
|
||||
({0: 1}, {0: 2}, """
|
||||
Full diff:
|
||||
- {0: 1}
|
||||
? ^
|
||||
+ {0: 2}
|
||||
? ^
|
||||
"""),
|
||||
(set([0, 1]), set([0, 2]), """
|
||||
Full diff:
|
||||
- set([0, 1])
|
||||
? ^
|
||||
+ set([0, 2])
|
||||
? ^
|
||||
""" if not PY3 else """
|
||||
Full diff:
|
||||
- {0, 1}
|
||||
? ^
|
||||
+ {0, 2}
|
||||
? ^
|
||||
""")
|
||||
]
|
||||
)
|
||||
def test_iterable_full_diff(self, left, right, expected):
|
||||
"""Test the full diff assertion failure explanation.
|
||||
|
||||
When verbose is False, then just a -v notice to get the diff is rendered,
|
||||
when verbose is True, then ndiff of the pprint is returned.
|
||||
"""
|
||||
expl = callequal(left, right, verbose=False)
|
||||
assert expl[-1] == 'Use -v to get the full diff'
|
||||
expl = '\n'.join(callequal(left, right, verbose=True))
|
||||
assert expl.endswith(textwrap.dedent(expected).strip())
|
||||
|
||||
def test_list_different_lenghts(self):
|
||||
expl = callequal([0, 1], [0, 1, 2])
|
||||
assert len(expl) > 1
|
||||
|
|
Loading…
Reference in New Issue