1 new commit in pytest:
https://bitbucket.org/hpk42/pytest/commits/10c697d004b0/
Changeset: 10c697d004b0
User: flub
Date: 2013-03-28 02:39:01
Summary: Attempt to improve detailed failure reporting
* If --verbose is used do not truncate.
* Add a special dict comparison instead of diffing
pprint output.
Affected #: 3 files
diff -r 05c01a1dd99d958629c15cc579f273bd738045c3 -r
10c697d004b0543b80a6b74f2ccc001bd04031f9 _pytest/assertion/util.py
--- a/_pytest/assertion/util.py
+++ b/_pytest/assertion/util.py
@@ -83,8 +83,8 @@
basestring = str
-def assertrepr_compare(op, left, right):
- """return specialised explanations for some operators/operands"""
+def assertrepr_compare(config, op, left, right):
+ """Return specialised explanations for some operators/operands"""
width = 80 - 15 - len(op) - 2 # 15 chars indentation, 1 space around op
left_repr = py.io.saferepr(left, maxsize=int(width/2))
right_repr = py.io.saferepr(right, maxsize=width-len(left_repr))
@@ -95,21 +95,21 @@
isdict = lambda x: isinstance(x, dict)
isset = lambda x: isinstance(x, set)
+ verbose = config.getoption('verbose')
explanation = None
try:
if op == '==':
if istext(left) and istext(right):
- explanation = _diff_text(left, right)
+ explanation = _diff_text(left, right, verbose)
elif issequence(left) and issequence(right):
- explanation = _compare_eq_sequence(left, right)
+ explanation = _compare_eq_sequence(left, right, verbose)
elif isset(left) and isset(right):
- explanation = _compare_eq_set(left, right)
+ explanation = _compare_eq_set(left, right, verbose)
elif isdict(left) and isdict(right):
- explanation = _diff_text(py.std.pprint.pformat(left),
- py.std.pprint.pformat(right))
+ explanation = _compare_eq_dict(left, right, verbose)
elif op == 'not in':
if istext(left) and istext(right):
- explanation = _notin_text(left, right)
+ explanation = _notin_text(left, right, verbose)
except py.builtin._sysex:
raise
except:
@@ -121,44 +121,44 @@
if not explanation:
return None
-
return [summary] + explanation
-def _diff_text(left, right):
+def _diff_text(left, right, verbose=False):
"""Return the explanation for the diff between text
- This will skip leading and trailing characters which are
- identical to keep the diff minimal.
+ Unless --verbose is used this will skip leading and trailing
+ characters which are identical to keep the diff minimal.
"""
explanation = []
- i = 0 # just in case left or right has zero length
- for i in range(min(len(left), len(right))):
- if left[i] != right[i]:
- break
- if i > 42:
- i -= 10 # Provide some context
- explanation = ['Skipping %s identical '
- 'leading characters in diff' % i]
- left = left[i:]
- right = right[i:]
- if len(left) == len(right):
- for i in range(len(left)):
- if left[-i] != right[-i]:
+ if not verbose:
+ i = 0 # just in case left or right has zero length
+ for i in range(min(len(left), len(right))):
+ if left[i] != right[i]:
break
if i > 42:
- i -= 10 # Provide some context
- explanation += ['Skipping %s identical '
- 'trailing characters in diff' % i]
- left = left[:-i]
- right = right[:-i]
+ i -= 10 # Provide some context
+ explanation = ['Skipping %s identical leading '
+ 'characters in diff, use -v to show' % i]
+ left = left[i:]
+ right = right[i:]
+ if len(left) == len(right):
+ for i in range(len(left)):
+ if left[-i] != right[-i]:
+ break
+ if i > 42:
+ i -= 10 # Provide some context
+ explanation += ['Skipping %s identical trailing '
+ 'characters in diff, use -v to show' % i]
+ left = left[:-i]
+ right = right[:-i]
explanation += [line.strip('\n')
for line in py.std.difflib.ndiff(left.splitlines(),
right.splitlines())]
return explanation
-def _compare_eq_sequence(left, right):
+def _compare_eq_sequence(left, right, verbose=False):
explanation = []
for i in range(min(len(left), len(right))):
if left[i] != right[i]:
@@ -175,7 +175,7 @@
# py.std.pprint.pformat(right))
-def _compare_eq_set(left, right):
+def _compare_eq_set(left, right, verbose=False):
explanation = []
diff_left = left - right
diff_right = right - left
@@ -190,12 +190,41 @@
return explanation
-def _notin_text(term, text):
+def _compare_eq_dict(left, right, verbose=False):
+ explanation = []
+ common = set(left).intersection(set(right))
+ same = dict((k, left[k]) for k in common if left[k] == right[k])
+ if same and not verbose:
+ explanation += ['Hiding %s identical items, use -v to show' %
+ len(same)]
+ elif same:
+ explanation += ['Common items:']
+ explanation += py.std.pprint.pformat(same).splitlines()
+ diff = set(k for k in common if left[k] != right[k])
+ if diff:
+ explanation += ['Differing items:']
+ for k in diff:
+ explanation += [py.io.saferepr({k: left[k]}) + ' != ' +
+ py.io.saferepr({k: right[k]})]
+ extra_left = set(left) - set(right)
+ if extra_left:
+ explanation.append('Left contains more items:')
+ explanation.extend(py.std.pprint.pformat(
+ dict((k, left[k]) for k in extra_left)).splitlines())
+ extra_right = set(right) - set(left)
+ if extra_right:
+ explanation.append('Right contains more items:')
+ explanation.extend(py.std.pprint.pformat(
+ dict((k, right[k]) for k in extra_right)).splitlines())
+ return explanation
+
+
+def _notin_text(term, text, verbose=False):
index = text.find(term)
head = text[:index]
tail = text[index+len(term):]
correct_text = head + tail
- diff = _diff_text(correct_text, text)
+ diff = _diff_text(correct_text, text, verbose)
newdiff = ['%s is contained here:' % py.io.saferepr(term, maxsize=42)]
for line in diff:
if line.startswith('Skipping'):
diff -r 05c01a1dd99d958629c15cc579f273bd738045c3 -r
10c697d004b0543b80a6b74f2ccc001bd04031f9
doc/en/example/assertion/failure_demo.py
--- a/doc/en/example/assertion/failure_demo.py
+++ b/doc/en/example/assertion/failure_demo.py
@@ -66,7 +66,7 @@
assert a == b
def test_eq_dict(self):
- assert {'a': 0, 'b': 1} == {'a': 0, 'b': 2}
+ assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
def test_eq_set(self):
assert set([0, 10, 11, 12]) == set([0, 20, 21])
diff -r 05c01a1dd99d958629c15cc579f273bd738045c3 -r
10c697d004b0543b80a6b74f2ccc001bd04031f9 testing/test_assertion.py
--- a/testing/test_assertion.py
+++ b/testing/test_assertion.py
@@ -6,6 +6,18 @@
needsnewassert = pytest.mark.skipif("sys.version_info < (2,6)")
+
[email protected]
+def mock_config():
+ class Config(object):
+ verbose = False
+ def getoption(self, name):
+ if name == 'verbose':
+ return self.verbose
+ raise KeyError('Not mocked out: %s' % name)
+ return Config()
+
+
def interpret(expr):
return reinterpret.reinterpret(expr, py.code.Frame(sys._getframe(1)))
@@ -32,8 +44,11 @@
"*test_check*PASS*",
])
-def callequal(left, right):
- return plugin.pytest_assertrepr_compare('==', left, right)
+def callequal(left, right, verbose=False):
+ config = mock_config()
+ config.verbose = verbose
+ return plugin.pytest_assertrepr_compare(config, '==', left, right)
+
class TestAssert_reprcompare:
def test_different_types(self):
@@ -48,6 +63,17 @@
assert '- spam' in diff
assert '+ eggs' in diff
+ def test_text_skipping(self):
+ lines = callequal('a'*50 + 'spam', 'a'*50 + 'eggs')
+ assert 'Skipping' in lines[1]
+ for line in lines:
+ assert 'a'*50 not in line
+
+ def test_text_skipping_verbose(self):
+ lines = callequal('a'*50 + 'spam', 'a'*50 + 'eggs', verbose=True)
+ assert '- ' + 'a'*50 + 'spam' in lines
+ assert '+ ' + 'a'*50 + 'eggs' in lines
+
def test_multiline_text_diff(self):
left = 'foo\nspam\nbar'
right = 'foo\neggs\nbar'
@@ -124,8 +150,9 @@
""")
assert testdir.runpytest().ret == 0
-def test_reprcompare_notin():
- detail = plugin.pytest_assertrepr_compare('not in', 'foo', 'aaafoobbb')[1:]
+def test_reprcompare_notin(mock_config):
+ detail = plugin.pytest_assertrepr_compare(
+ mock_config, 'not in', 'foo', 'aaafoobbb')[1:]
assert detail == ["'foo' is contained here:", ' aaafoobbb', '? +++']
@needsnewassert
Repository URL: https://bitbucket.org/hpk42/pytest/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
pytest-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pytest-commit