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)")
 
+
+@pytest.fixture
+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
pytest-commit@python.org
http://mail.python.org/mailman/listinfo/pytest-commit

Reply via email to