Side by Side Diff

Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Keyboard Shortcuts

File
u :up to issue
m :publish + mail comments
M :edit review message
j / k :jump to file after / before current file
J / K :jump to next file with a comment after / before current file
Side-by-side diff
i :toggle intra-line diffs
e :expand all comments
c :collapse all comments
s :toggle showing all comments
n / p :next / previous diff chunk or comment
N / P :next / previous comment
<Up> / <Down> :next / previous line
<Enter> :respond to / edit current comment
d :mark current comment as done
Issue
u :up to list of issues
m :publish + mail comments
j / k :jump to patch after / before current patch
o / <Enter> :open current patch in side-by-side view
i :open current patch in unified diff view
Issue List
j / k :jump to issue after / before current issue
o / <Enter> :open current issue
# : close issue
Comment/message editing
<Ctrl> + s or <Ctrl> + Enter :save comment
<Esc> :cancel edit
Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(245)
Issues Repositories Search
Open Issues | Closed Issues | All Issues | Sign in with your Google Account to create issues and add comments

Side by Side Diff: Lib/unittest.py

Issue 32080: [issue2578] additional unittest type equality methods Base URL: http://svn.python.org/view/*checkout*/python/trunk/
Patch Set: minor cleanup Created 16 years, 9 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« Lib/test/test_unittest.py ('K') | « Lib/test/test_unittest.py ('k') | no next file » | no next file with comments »
('i') | ('e') | ('c') | ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 ''' 2 '''
3 Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's 3 Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
4 Smalltalk testing framework. 4 Smalltalk testing framework.
5 5
6 This module contains the core framework classes that form the basis of 6 This module contains the core framework classes that form the basis of
7 specific test cases and suites (TestCase, TestSuite etc.), and also a 7 specific test cases and suites (TestCase, TestSuite etc.), and also a
8 text-based utility class for running the tests and reporting the results 8 text-based utility class for running the tests and reporting the results
9 (TextTestRunner). 9 (TextTestRunner).
10 10
(...skipping 27 matching lines...) Loading...
38 THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 38 THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
39 DAMAGE. 39 DAMAGE.
40 40
41 THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 41 THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
42 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 42 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
43 PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, 43 PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
44 AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, 44 AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
45 SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 45 SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
46 ''' 46 '''
47 47
48 import difflib
49 import functools
50 import os
51 import pprint
52 import re
53 import sys
48 import time 54 import time
49 import sys
50 import traceback 55 import traceback
51 import os
52 import types 56 import types
53 import functools
54 57
55 ############################################################################## 58 ##############################################################################
56 # Exported classes and functions 59 # Exported classes and functions
57 ############################################################################## 60 ##############################################################################
58 __all__ = ['TestResult', 'TestCase', 'TestSuite', 'ClassTestSuite', 61 __all__ = ['TestResult', 'TestCase', 'TestSuite', 'ClassTestSuite',
59 'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main', 62 'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
60 'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless', 63 'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
61 'expectedFailure'] 64 'expectedFailure']
62 65
63 # Expose obsolete functions for backwards compatibility 66 # Expose obsolete functions for backwards compatibility
(...skipping 180 matching lines...) | | Loading...
244 length += 1 247 length += 1
245 tb = tb.tb_next 248 tb = tb.tb_next
246 return length 249 return length
247 250
248 def __repr__(self): 251 def __repr__(self):
249 return "<%s run=%i errors=%i failures=%i>" % \ 252 return "<%s run=%i errors=%i failures=%i>" % \
250 (_strclass(self.__class__), self.testsRun, len(self.errors), 253 (_strclass(self.__class__), self.testsRun, len(self.errors),
251 len(self.failures)) 254 len(self.failures))
252 255
253 256
254 class AssertRaisesContext(object): 257 class AssertRaisesContext(object):
GvR 2009年03月31日 15:01:06 While you're at it, can you add a docstring?
While you're at it, can you add a docstring?
gregory.p.smith 2009年03月31日 16:37:02 Done. We also decided that this should be private
On 2009年03月31日 15:01:06, GvR wrote: > While you're at it, can you add a docstring?
Done. We also decided that this should be private so I've added an _.
255 258
256 def __init__(self, expected, test_case): 259 def __init__(self, expected, test_case, expected_regexp=None):
257 self.expected = expected 260 self.expected = expected
258 self.failureException = test_case.failureException 261 self.failureException = test_case.failureException
259 262 self.expected_regex = expected_regexp
263 ········
260 def __enter__(self): 264 def __enter__(self):
261 pass 265 pass
262 266
263 def __exit__(self, exc_type, exc_value, traceback): 267 def __exit__(self, exc_type, exc_value, traceback):
264 if exc_type is None: 268 if exc_type is None:
265 try: 269 try:
266 exc_name = self.expected.__name__ 270 exc_name = self.expected.__name__
267 except AttributeError: 271 except AttributeError:
268 exc_name = str(self.expected) 272 exc_name = str(self.expected)
269 raise self.failureException( 273 raise self.failureException(
270 "{0} not raised".format(exc_name)) 274 "{0} not raised".format(exc_name))
271 if issubclass(exc_type, self.expected): 275 if not issubclass(exc_type, self.expected):
276 # let unexpexted exceptions pass through
277 return False
278 if self.expected_regex is None:
272 return True 279 return True
273 # Let unexpected exceptions skip through 280 ········
274 return False 281 expected_regexp = self.expected_regex
282 if isinstance(expected_regexp, basestring):
283 expected_regexp = re.compile(expected_regexp)
284 if not expected_regexp.search(str(exc_value)):
285 raise self.failureException('"%s" does not match "%s"' %
286 (expected_regexp.pattern, str(exc_value)))
287 return True
288
275 289
276 290
277 class TestCase(object): 291 class TestCase(object):
278 """A class whose instances are single test cases. 292 """A class whose instances are single test cases.
279 293
280 By default, the test code itself should be placed in a method named 294 By default, the test code itself should be placed in a method named
281 'runTest'. 295 'runTest'.
282 296
283 If the fixture may be used for many test cases, create as 297 If the fixture may be used for many test cases, create as
284 many test methods as are needed. When instantiating such a TestCase 298 many test methods as are needed. When instantiating such a TestCase
(...skipping 23 matching lines...) Loading...
308 not have a method with the specified name. 322 not have a method with the specified name.
309 """ 323 """
310 self._testMethodName = methodName 324 self._testMethodName = methodName
311 try: 325 try:
312 testMethod = getattr(self, methodName) 326 testMethod = getattr(self, methodName)
313 except AttributeError: 327 except AttributeError:
314 raise ValueError("no such test method in %s: %s" % \ 328 raise ValueError("no such test method in %s: %s" % \
315 (self.__class__, methodName)) 329 (self.__class__, methodName))
316 self._testMethodDoc = testMethod.__doc__ 330 self._testMethodDoc = testMethod.__doc__
317 331
332 # Map types to custom assertEquals functions that will compare
GvR 2009年03月31日 15:01:06 assertEquals -> assertEqual
assertEquals -> assertEqual
gregory.p.smith 2009年03月31日 16:37:02 Done.
On 2009年03月31日 15:01:06, GvR wrote: > assertEquals -> assertEqual
Done.
333 # instances of said type in more detail to generate a more useful
334 # error message.
335 self.__type_equality_funcs = {}
336 self.addTypeEqualityFunc(dict, self.assertDictEquals)
337 self.addTypeEqualityFunc(list, self.assertListEquals)
338 self.addTypeEqualityFunc(tuple, self.assertTupleEquals)
339 self.addTypeEqualityFunc(set, self.assertSetEquals)
340 self.addTypeEqualityFunc(frozenset, self.assertSetEquals)
341
342 def addTypeEqualityFunc(self, typeobj, function):
343 """Add a type specific assertEqual style function to compare a type.
344
345 This method is for use by TestCase subclasses that need to register
346 their own type equality functions to provide nicer error messages.
347
348 Args:
349 typeobj: The data type to call this function on when both values
350 are of the same type in assertEquals().
351 function: The callable taking two arguments and an optional
352 msg= argument that raises self.failureException with a
353 useful error message when the two arguments are not equal.
354 """
355 self.__type_equality_funcs[typeobj] = function
356
318 def setUp(self): 357 def setUp(self):
319 "Hook method for setting up the test fixture before exercising it." 358 "Hook method for setting up the test fixture before exercising it."
320 pass 359 pass
321 360
322 def tearDown(self): 361 def tearDown(self):
323 "Hook method for deconstructing the test fixture after testing it." 362 "Hook method for deconstructing the test fixture after testing it."
324 pass 363 pass
325 364
326 def countTestCases(self): 365 def countTestCases(self):
327 return 1 366 return 1
328 367
329 def defaultTestResult(self): 368 def defaultTestResult(self):
330 return TestResult() 369 return TestResult()
331 370
332 def shortDescription(self): 371 def shortDescription(self):
333 """Returns a one-line description of the test, or None if no 372 """Returns both the test method name and first line of its docstring.
334 description has been provided.
335 373
336 The default implementation of this method returns the first line of 374 If no docstring is given, only returns the method name.
337 the specified test method's docstring. 375
376 This method overrides unittest.TestCase.shortDescription(), which
377 only returns the first line of the docstring, obscuring the name
378 of the test upon failure.
338 """ 379 """
339 doc = self._testMethodDoc 380 desc = str(self)
340 return doc and doc.split("\n")[0].strip() or None 381 doc_first_line = None
382
383 if self._testMethodDoc:
384 doc_first_line = self._testMethodDoc.split("\n")[0].strip()
385 if doc_first_line:
386 desc = '\n'.join((desc, doc_first_line))
387 return desc
341 388
342 def id(self): 389 def id(self):
343 return "%s.%s" % (_strclass(self.__class__), self._testMethodName) 390 return "%s.%s" % (_strclass(self.__class__), self._testMethodName)
344 391
345 def __eq__(self, other): 392 def __eq__(self, other):
346 if type(self) is not type(other): 393 if type(self) is not type(other):
347 return NotImplemented 394 return NotImplemented
348 395
349 return self._testMethodName == other._testMethodName 396 return self._testMethodName == other._testMethodName
350 397
(...skipping 91 matching lines...) | | Loading...
442 489
443 with self.failUnlessRaises(some_error_class): 490 with self.failUnlessRaises(some_error_class):
444 do_something() 491 do_something()
445 """ 492 """
446 context = AssertRaisesContext(excClass, self) 493 context = AssertRaisesContext(excClass, self)
447 if callableObj is None: 494 if callableObj is None:
448 return context 495 return context
449 with context: 496 with context:
450 callableObj(*args, **kwargs) 497 callableObj(*args, **kwargs)
451 498
499 def _getAssertEqualityFunc(self, first, second):
500 """Get a detailed comparison function for the types of the two args.
501 ········
502 Returns: A callable accepting (first, second, msg=None) that will
503 raise a failure exception if first != second with a useful human
504 readable error message for those types.
505 """
506 #
507 # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
508 # and vice versa. I opted for the conservative approach in case
509 # subclasses are not intended to be compared in detail to their super
510 # class instances using a type equality func. This means testing
511 # subtypes won't automagically use the detailed comparison. Callers
512 # should use their type specific assertSpamEquals method to compare
GvR 2009年03月31日 15:01:06 assertSpamEqual
assertSpamEqual
gregory.p.smith 2009年03月31日 16:37:02 Done.
On 2009年03月31日 15:01:06, GvR wrote: > assertSpamEqual
Done.
513 # subclasses if the detailed comparison is desired and appropriate.
514 # See the discussion in http://bugs.python.org/issue2578.
515 #
516 if type(first) is type(second):
517 return self.__type_equality_funcs.get(type(first),
518 self._baseAssertEquals)
519 return self._baseAssertEquals
520
521 def _baseAssertEquals(self, first, second, msg=None):
GvR 2009年03月31日 15:01:06 Mind dropping the trailing 's'?
Mind dropping the trailing 's'?
gregory.p.smith 2009年03月31日 16:37:02 Done.
On 2009年03月31日 15:01:06, GvR wrote: > Mind dropping the trailing 's'?
Done.
522 """The default assertEquals implementation, not type specific."""
523 if not first == second:
524 raise self.failureException(msg or '%r != %r' % (first, second))
525
452 def failUnlessEqual(self, first, second, msg=None): 526 def failUnlessEqual(self, first, second, msg=None):
GvR 2009年03月31日 15:01:06 We had talked about making the 'def' define the re
We had talked about making the 'def' define the recommended name, e.g. assertNotEqual, and using aliases to keep the other names. Do you want to do that at the same time as this change or in a separate one?
gregory.p.smith 2009年03月31日 16:37:02 Yes I'm going to do that in the next revision imme
On 2009年03月31日 15:01:06, GvR wrote: > We had talked about making the 'def' define the recommended name, e.g. > assertNotEqual, and using aliases to keep the other names. Do you want to do > that at the same time as this change or in a separate one?
Yes I'm going to do that in the next revision immediately after this one.
453 """Fail if the two objects are unequal as determined by the '==' 527 """Fail if the two objects are unequal as determined by the '=='
454 operator. 528 operator.
455 """ 529 """
456 if not first == second: 530 assertion_func = self._getAssertEqualityFunc(first, second)
457 raise self.failureException(msg or '%r != %r' % (first, second)) 531 assertion_func(first, second, msg=msg)
458 532
459 def failIfEqual(self, first, second, msg=None): 533 def failIfEqual(self, first, second, msg=None):
460 """Fail if the two objects are equal as determined by the '==' 534 """Fail if the two objects are equal as determined by the '=='
461 operator. 535 operator.
462 """ 536 """
463 if first == second: 537 if first == second:
464 raise self.failureException(msg or '%r == %r' % (first, second)) 538 raise self.failureException(msg or '%r == %r' % (first, second))
465 539
466 def failUnlessAlmostEqual(self, first, second, places=7, msg=None): 540 def failUnlessAlmostEqual(self, first, second, places=7, msg=None):
467 """Fail if the two objects are unequal as determined by their 541 """Fail if the two objects are unequal as determined by their
(...skipping 29 matching lines...) Loading...
497 571
498 assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual 572 assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual
499 573
500 assertRaises = failUnlessRaises 574 assertRaises = failUnlessRaises
501 575
502 assert_ = assertTrue = failUnless 576 assert_ = assertTrue = failUnless
503 577
504 assertFalse = failIf 578 assertFalse = failIf
505 579
506 580
581 def assertSequenceEquals(self, seq1, seq2, msg=None, seq_type=None):
GvR 2009年03月31日 15:01:06 Drop the trailing 's' in the name?
Drop the trailing 's' in the name?
gregory.p.smith 2009年03月31日 16:37:02 Done.
On 2009年03月31日 15:01:06, GvR wrote: > Drop the trailing 's' in the name?
Done.
582 """An equality assertion for ordered sequences (like lists and tuples).
583
584 For the purposes of this function, a valid orderd sequence type is one
585 which can be indexed, has a length, and has an equality operator.
586
587 Args:
588 seq1: The first sequence to compare.
589 seq2: The second sequence to compare.
590 seq_type: The expected datatype of the sequences, or None if no
591 datatype should be enforced.
592 msg: Optional message to use on failure instead of a list of
593 differences.
594 """
595 if seq_type != None:
596 seq_type_name = seq_type.__name__
597 if not isinstance(seq1, seq_type):
598 raise self.failureException('First sequence is not a %s: %r'·
599 % (seq_type_name, seq1))
600 if not isinstance(seq2, seq_type):
601 raise self.failureException('Second sequence is not a %s: %r'·
602 % (seq_type_name, seq2))
603 else:
604 seq_type_name = "sequence"
605
606 differing = None
607 try:
608 len1 = len(seq1)
609 except (TypeError, NotImplementedError):
610 differing = 'First %s has no length. Non-sequence?' % (
611 seq_type_name)
612
613 if differing is None:
614 try:
615 len2 = len(seq2)
616 except (TypeError, NotImplementedError):
617 differing = 'Second %s has no length. Non-sequence?' % (
618 seq_type_name)
619
620 if differing is None:
621 if seq1 == seq2:
622 return
623
624 for i in xrange(min(len1, len2)):
625 try:
626 item1 = seq1[i]
627 except (TypeError, IndexError, NotImplementedError):
628 differing = ('Unable to index element %d of first %s\n' %
629 (i, seq_type_name))
630 break
631
632 try:
633 item2 = seq2[i]
634 except (TypeError, IndexError, NotImplementedError):
635 differing = ('Unable to index element %d of second %s\n' %
636 (i, seq_type_name))
637 break
638
639 if item1 != item2:
640 differing = ('First differing element %d:\n%s\n%s\n' %
641 (i, item1, item2))
642 break
643 else:
644 if (len1 == len2 and seq_type is None and
645 type(seq1) != type(seq2)):
646 # The sequences are the same, but have differing types.
647 return
648 # A catch-all message for handling arbitrary user-defined
649 # sequences.
650 differing = '%ss differ:\n' % seq_type_name.capitalize()
651 if len1 > len2:
652 differing = ('First %s contains %d additional '
653 'elements.\n' % (seq_type_name, len1 - len2))
654 try:
655 differing += ('First extra element %d:\n%s\n' %
656 (len2, seq1[len2]))
657 except (TypeError, IndexError, NotImplementedError):
658 differing += ('Unable to index element %d '
659 'of first %s\n' % (len2, seq_type_name))
660 elif len1 < len2:
661 differing = ('Second %s contains %d additional '
662 'elements.\n' % (seq_type_name, len2 - len1))
663 try:
664 differing += ('First extra element %d:\n%s\n' %
665 (len1, seq2[len1]))
666 except (TypeError, IndexError, NotImplementedError):
667 differing += ('Unable to index element %d '
668 'of second %s\n' % (len1, seq_type_name))
669 if not msg:
670 msg = '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(),
671 pprint.pformat(seq2).splitlines()))
672 self.fail(differing + msg)
673
674 def assertListEquals(self, list1, list2, msg=None):
675 """A list-specific equality assertion.
676
677 Args:
678 list1: The first list to compare.
679 list2: The second list to compare.
680 msg: Optional message to use on failure instead of a list of
681 differences.
682
683 """
684 self.assertSequenceEquals(list1, list2, msg, seq_type=list)
685
686 def assertTupleEquals(self, tuple1, tuple2, msg=None):
687 """A tuple-specific equality assertion.
688
689 Args:
690 tuple1: The first tuple to compare.
691 tuple2: The second tuple to compare.
692 msg: Optional message to use on failure instead of a list of
693 differences.
694 """
695 self.assertSequenceEquals(tuple1, tuple2, msg, seq_type=tuple)
696
697 def assertSetEquals(self, set1, set2, msg=None):
698 """A set-specific equality assertion.
699
700 Args:
701 set1: The first set to compare.
702 set2: The second set to compare.
703 msg: Optional message to use on failure instead of a list of
704 differences.
705
706 For more general containership equality, assertSameElements will work
707 with things other than sets. This uses ducktyping to support
708 different types of sets, and is optimized for sets specifically
709 (parameters must support a difference method).
710 """
711 try:
712 difference1 = set1.difference(set2)
713 except TypeError, e:
714 self.fail('invalid type when attempting set difference: %s' % e)
715 except AttributeError, e:
716 self.fail('first argument does not support set difference: %s' % e)
717
718 try:
719 difference2 = set2.difference(set1)
720 except TypeError, e:
721 self.fail('invalid type when attempting set difference: %s' % e)
722 except AttributeError, e:
723 self.fail('second argument does not support set difference: %s' % e)
724
725 if not (difference1 or difference2):
726 return
727
728 if msg is not None:
729 self.fail(msg)
730
731 lines = []
732 if difference1:
733 lines.append('Items in the first set but not the second:')
734 for item in difference1:
735 lines.append(repr(item))
736 if difference2:
737 lines.append('Items in the second set but not the first:')
738 for item in difference2:
739 lines.append(repr(item))
740 self.fail('\n'.join(lines))
741
742 def assertIn(self, a, b, msg=None):
743 """Just like self.assert_(a in b), but with a nicer default message."""
744 if msg is None:
745 msg = '"%s" not found in "%s"' % (a, b)
746 self.assert_(a in b, msg)
747
748 def assertNotIn(self, a, b, msg=None):
749 """Just like self.assert_(a not in b), but with a nicer default message. """
750 if msg is None:
751 msg = '"%s" unexpectedly found in "%s"' % (a, b)
752 self.assert_(a not in b, msg)
753
754 def assertDictEquals(self, d1, d2, msg=None):
755 self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
756 self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary' )
757
758 if d1 != d2:
759 self.fail(msg or ('\n' + '\n'.join(difflib.ndiff(
760 pprint.pformat(d1).splitlines(),
761 pprint.pformat(d2).splitlines()))))
762
763 def assertDictContainsSubset(self, expected, actual, msg=None):
764 """Checks whether actual is a superset of expected."""
765 missing = []
766 mismatched = []
767 for key, value in expected.iteritems():
768 if key not in actual:
769 missing.append(key)
770 elif value != actual[key]:
771 mismatched.append('%s, expected: %s, actual: %s' % (key, value,
772 actual[key]))
773
774 if not (missing or mismatched):
775 return
776
777 missing_msg = mismatched_msg = ''
778 if missing:
779 missing_msg = 'Missing: %s' % ','.join(missing)
780 if mismatched:
781 mismatched_msg = 'Mismatched values: %s' % ','.join(mismatched)
782
783 if msg:
784 msg = '%s: %s; %s' % (msg, missing_msg, mismatched_msg)
785 else:
786 msg = '%s; %s' % (missing_msg, mismatched_msg)
787 self.fail(msg)
788
789 def assertSameElements(self, expected_seq, actual_seq, msg=None):
790 """An unordered sequence specific comparison.
791
792 Raises with an error message listing which elements of expected_seq
793 are missing from actual_seq and vice versa if any.
794 """
795 try:
796 expected = set(expected_seq)
797 actual = set(actual_seq)
798 missing = list(expected.difference(actual))
799 unexpected = list(actual.difference(expected))
800 missing.sort()
801 unexpected.sort()
802 except TypeError:
803 # Fall back to slower list-compare if any of the objects are
804 # not hashable.
805 expected = list(expected_seq)
806 actual = list(actual_seq)
807 expected.sort()
808 actual.sort()
809 missing, unexpected = _SortedListDifference(expected, actual)
810 errors = []
811 if missing:
812 errors.append('Expected, but missing:\n %r\n' % missing)
813 if unexpected:
814 errors.append('Unexpected, but present:\n %r\n' % unexpected)
815 if errors:
816 self.fail(msg or ''.join(errors))
817
818 def assertMultiLineEquals(self, first, second, msg=None):
819 """Assert that two multi-line strings are equal."""
820 self.assert_(isinstance(first, types.StringTypes), (
821 'First argument is not a string'))
822 self.assert_(isinstance(second, types.StringTypes), (
823 'Second argument is not a string'))
824
825 if first != second:
826 raise self.failureException(
827 msg or '\n' + ''.join(difflib.ndiff(first.splitlines(True),
828 second.splitlines(True))))
829
830 def assertLess(self, a, b, msg=None):
831 """Just like self.assert_(a < b), but with a nicer default message."""
832 if msg is None:
833 msg = '"%r" unexpectedly not less than "%r"' % (a, b)
834 self.assert_(a < b, msg)
835
836 def assertLessEqual(self, a, b, msg=None):
837 """Just like self.assert_(a <= b), but with a nicer default message."""
838 if msg is None:
839 msg = '"%r" unexpectedly not less than or equal to "%r"' % (a, b)
840 self.assert_(a <= b, msg)
841
842 def assertGreater(self, a, b, msg=None):
843 """Just like self.assert_(a > b), but with a nicer default message."""
844 if msg is None:
845 msg = '"%r" unexpectedly not greater than "%r"' % (a, b)
846 self.assert_(a > b, msg)
847
848 def assertGreaterEqual(self, a, b, msg=None):
849 """Just like self.assert_(a >= b), but with a nicer default message."""
850 if msg is None:
851 msg = '"%r" unexpectedly not greater than or equal to "%r"' % (a, b)
852 self.assert_(a >= b, msg)
853
854 def assertIsNone(self, obj, msg=None):
855 """Same as self.assert_(obj is None), with a nicer default message."""
856 if msg is None:
857 msg = '"%s" unexpectedly not None' % obj
858 self.assert_(obj is None, msg)
859
860 def assertIsNotNone(self, obj, msg='unexpectedly None'):
861 """Included for symmetry with assertIsNone."""
862 self.assert_(obj is not None, msg)
863
864 def assertRaisesRegexp(self, expected_exception, expected_regexp,
865 callable_obj=None, *args, **kwargs):
866 """Asserts that the message in a raised exception matches a regexp.
867
868 Args:
869 expected_exception: Exception class expected to be raised.
870 expected_regexp: Regexp (re pattern object or string) expected
871 to be found in error message.
872 callable_obj: Function to be called.
873 args: Extra args.
874 kwargs: Extra kwargs.
875 """
876 context = AssertRaisesContext(expected_exception, self, expected_regexp)
877 if callable_obj is None:
878 return context
879 with context:
880 callable_obj(*args, **kwargs)
881
882 def assertRegexpMatches(self, text, expected_regex, msg=None):
883 if isinstance(expected_regex, basestring):
884 expected_regex = re.compile(expected_regex)
885 if not expected_regex.search(text):
886 msg = msg or "Regexp didn't match"
887 msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text)
888 raise self.failureException(msg)
889
890
891 def _SortedListDifference(expected, actual):
892 """Finds elements in only one or the other of two, sorted input lists.
893
894 Returns a two-element tuple of lists. The first list contains those
895 elements in the "expected" list but not in the "actual" list, and the
896 second contains those elements in the "actual" list but not in the
897 "expected" list. Duplicate elements in either input list are ignored.
898 """
899 i = j = 0
900 missing = []
901 unexpected = []
902 while True:
903 try:
904 e = expected[i]
905 a = actual[j]
906 if e < a:
907 missing.append(e)
908 i += 1
909 while expected[i] == e:
910 i += 1
911 elif e > a:
912 unexpected.append(a)
913 j += 1
914 while actual[j] == a:
915 j += 1
916 else:
917 i += 1
918 try:
919 while expected[i] == e:
920 i += 1
921 finally:
922 j += 1
923 while actual[j] == a:
924 j += 1
925 except IndexError:
926 missing.extend(expected[i:])
927 unexpected.extend(actual[j:])
928 break
929 return missing, unexpected
930
507 931
508 class TestSuite(object): 932 class TestSuite(object):
509 """A test suite is a composite test consisting of a number of TestCases. 933 """A test suite is a composite test consisting of a number of TestCases.
510 934
511 For use, create an instance of TestSuite, then add test case instances. 935 For use, create an instance of TestSuite, then add test case instances.
512 When all tests have been added, the suite can be passed to a test 936 When all tests have been added, the suite can be passed to a test
513 runner, such as TextTestRunner. It will run the individual test cases 937 runner, such as TextTestRunner. It will run the individual test cases
514 in the order in which they were added, aggregating the results. When 938 in the order in which they were added, aggregating the results. When
515 subclassing, do not forget to call the base class constructor. 939 subclassing, do not forget to call the base class constructor.
516 """ 940 """
(...skipping 525 matching lines...) | | Loading...
1042 1466
1043 main = TestProgram 1467 main = TestProgram
1044 1468
1045 1469
1046 ############################################################################## 1470 ##############################################################################
1047 # Executing this module from the command line 1471 # Executing this module from the command line
1048 ############################################################################## 1472 ##############################################################################
1049 1473
1050 if __name__ == "__main__": 1474 if __name__ == "__main__":
1051 main(module=None) 1475 main(module=None)
OLDNEW
« Lib/test/test_unittest.py ('K') | « Lib/test/test_unittest.py ('k') | no next file » | no next file with comments »
Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b

AltStyle によって変換されたページ (->オリジナル) /