A better unittest
Duncan Booth
duncan at NOSPAMrcp.co.uk
Thu Apr 17 06:13:51 EDT 2003
Thomas Heller <theller at python.net> wrote in news:d6jmqr2q.fsf at python.net:
> "Terry Reedy" <tjreedy at udel.edu> writes:
>> Hmmm. What I would really like is a structure comparison function
>> that spit out the first difference found so I did not have to print
>> each and compare by eye. That is not directly in the scope of your
>> problem, but it would be the most useful succinct display.
>
> As you say, it's a different problem.
> The patches simply rearrange the output.
>
Anyone fancy a patch that gives the output below? (I do hope it doesn't word wrap).
FFFF
======================================================================
FAIL: test_failUnlessEqual (__main__.Test)
----------------------------------------------------------------------
TestFailed: failUnlessEqual
'xxxxxxxxxxxxxxxxxx...xxxxyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...
... ^
'xxxxxxxxxxxxxxxxxx...xxxxazzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...
... ^
File "J:\temp\test.py", line 7, in test_failUnlessEqual
self.failUnlessEqual(s, t)
======================================================================
FAIL: test_failunlessEqual2 (__main__.Test)
----------------------------------------------------------------------
TestFailed: <object object at 0x007E63B8> != <object object at 0x007E63C0>
File "J:\temp\test.py", line 10, in test_failunlessEqual2
self.failUnlessEqual(object(), object())
======================================================================
FAIL: test_failunlessEqual3 (__main__.Test)
----------------------------------------------------------------------
TestFailed: failUnlessEqual
{'A': 65, 'C': 67, ...0, 'S': 83, 'R': 82, 'U': 85, 'T': 84, 'W': 87, 'V': 8...
... ^^^^^^
{'A': 65, 'C': 67, ...0, 'P ': 0, 'R': 82, 'U': 85, 'T': 84, 'W': 87, 'V': 8...
... ^^^^^^ ...
File "J:\temp\test.py", line 18, in test_failunlessEqual3
self.failUnlessEqual(d1, d2)
======================================================================
FAIL: test_failunlessEqual4 (__main__.Test)
----------------------------------------------------------------------
TestFailed: failUnlessEqual
{'A': 65, 'C': 67, ...0, 'P ': 0, 'R': 82, 'U': 85, 'T': 84, 'W': 87, 'V': 8...
... ^^^^^^ ...
{'A': 65, 'C': 67, ...0, 'S': 83, 'R': 82, 'U': 85, 'T': 84, 'W': 87, 'V': 8...
... ^^^^^^
File "J:\temp\test.py", line 26, in test_failunlessEqual4
self.failUnlessEqual(d2, d1)
----------------------------------------------------------------------
Ran 4 tests in 0.187s
FAILED (failures=4)
The patch follows (it assumes you already applied Thomas Heller's patch):
----- unittest.diff -----
*** unittest.py.orig Thu Apr 17 10:08:03 2003
--- unittest.py Thu Apr 17 11:07:19 2003
***************
*** 146,152 ****
class TestFailed(Exception):
pass
!
class TestCase:
"""A class whose instances are single test cases.
--- 146,199 ----
class TestFailed(Exception):
pass
!
! def shortdiff(x,y):
! '''shortdiff(x,y)
!
! Compare strings x and y and display differences.
! If the strings are too long, shorten them to fit
! in one line, while still keeping at least some difference.
! '''
! import difflib
! LINELEN = 79
! def limit(s):
! if len(s) > LINELEN:
! return s[:LINELEN-3] + '...'
! return s
!
! d = difflib.Differ()
! diffs = list(d._fancy_replace([x], 0, 1, [y], 0, 1))
! if len(diffs) == 3:
! if diffs[1].startswith('+ '):
! diffs.insert(1, '')
! else:
! diffs.append('')
! if len(diffs) != 4:
! # String were the same!
! #return '\n'.join(diffs)
! return limit(diffs[0][2:])
!
! # Remove '- ', '+ ', '? ' markers from start of lines,
! # and newlines from end.
! diffs = [ s[2:].rstrip() for s in diffs]
! if max([len(s) for s in diffs]) < LINELEN:
! return '\n'.join(diffs)
!
! # Need to shorten the string, but make sure
! # first difference is visible.
! diff1, diff2 = diffs[1], diffs[3]
! a = len(diff1) - len(diff1.lstrip())
! b = len(diff2) - len(diff2.lstrip())
! if a == 0 or (b != 0 and b < a):
! a = b
!
! if a > LINELEN/2:
! diffs = [ s[:LINELEN/4] + '...' + s[a - 4:]
! for s in diffs ]
!
! diffs = [ limit(s) for s in diffs ]
! return '\n'.join(diffs)
!
class TestCase:
"""A class whose instances are single test cases.
***************
*** 317,324 ****
operator.
"""
if first != second:
raise self.failureException, \
! (msg or '%s != %s' % (`first`, `second`))
def failIfEqual(self, first, second, msg=None):
"""Fail if the two objects are equal as determined by the '=='
--- 364,374 ----
operator.
"""
if first != second:
+ reprfirst, reprsecond = repr(first), repr(second)
+ if not msg and len(reprfirst) + len(reprsecond) > 60:
+ msg = "failUnlessEqual\n" + shortdiff(reprfirst, reprsecond)
raise self.failureException, \
! (msg or '%s != %s' % (reprfirst, reprsecond))
def failIfEqual(self, first, second, msg=None):
"""Fail if the two objects are equal as determined by the '=='
-------------------------
For completeness test.py with the failing tests
---- test.py ----
import unittest
class Test(unittest.TestCase):
def test_failUnlessEqual(self):
s = 5000*'x'+'y'+5000*'z'
t = 5000*'x'+'a'+5000*'z'
self.failUnlessEqual(s, t)
def test_failunlessEqual2(self):
self.failUnlessEqual(object(), object())
def test_failunlessEqual3(self):
d1 = {}
for i in range(65, 96):
d1[chr(i)] = i
d2 = {'P ': 0}
d2.update(d1)
self.failUnlessEqual(d1, d2)
def test_failunlessEqual4(self):
d1 = {}
for i in range(65, 96):
d1[chr(i)] = i
d2 = {'P ': 0}
d2.update(d1)
self.failUnlessEqual(d2, d1)
if __name__=='__main__':
try:
unittest.main()
except SystemExit:
pass
-----------------
--
Duncan Booth duncan at rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?
More information about the Python-list
mailing list