]> granicus.if.org Git - python/commitdiff
Issue 10242. Switching unittest.TestCase.assertItemsEqual to use a collections.Counte...
authorMichael Foord <fuzzyman@voidspace.org.uk>
Sun, 19 Dec 2010 15:52:56 +0000 (15:52 +0000)
committerMichael Foord <fuzzyman@voidspace.org.uk>
Sun, 19 Dec 2010 15:52:56 +0000 (15:52 +0000)
This fixes bugs when comparing collections of items like sets that can be sorted without raising an exception but where sorting has no meaning.

Lib/unittest/case.py
Lib/unittest/test/test_case.py
Misc/NEWS

index 33ab47a4b59625167f15a75c1bf3d9360c2e8a86..cd8f4fa0092c8e8b34a92131e8acc5548587b84a 100644 (file)
@@ -1,5 +1,6 @@
 """Test case implementation"""
 
+import collections
 import sys
 import functools
 import difflib
@@ -850,14 +851,12 @@ class TestCase(object):
         self.fail(self._formatMessage(msg, standardMsg))
 
     def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
-        """An unordered sequence / set specific comparison. It asserts that
-        expected_seq and actual_seq contain the same elements. It is
-        the equivalent of::
+        """An unordered sequence specific comparison. It asserts that
+        actual_seq and expected_seq have the same element counts.
+        Equivalent to::
 
-            self.assertEqual(sorted(expected_seq), sorted(actual_seq))
-
-        Raises with an error message listing which elements of expected_seq
-        are missing from actual_seq and vice versa if any.
+            self.assertEqual(Counter(iter(actual_seq)),
+                             Counter(iter(expected_seq)))
 
         Asserts that each element has the same count in both sequences.
         Example:
@@ -872,17 +871,18 @@ class TestCase(object):
                              "comparing unequal types"]:
                     warnings.filterwarnings("ignore", _msg, DeprecationWarning)
             try:
-                expected = sorted(expected_seq)
-                actual = sorted(actual_seq)
+                actual = collections.Counter(iter(actual_seq))
+                expected = collections.Counter(iter(expected_seq))
             except TypeError:
                 # Unsortable items (example: set(), complex(), ...)
-                expected = list(expected_seq)
                 actual = list(actual_seq)
-                missing, unexpected = unorderable_list_difference(
-                    expected, actual, ignore_duplicate=False
-                )
+                expected = list(expected_seq)
+                missing, unexpected = unorderable_list_difference(expected, actual)
             else:
-                return self.assertSequenceEqual(expected, actual, msg=msg)
+                if actual == expected:
+                    return
+                missing = list(expected - actual)
+                unexpected = list(actual - expected)
 
         errors = []
         if missing:
index c42d98d82de5833581a02af08b6a8d2378bf1f92..250e9053528a67f5cb9038b8fe7c08bbaf7b5f2b 100644 (file)
@@ -711,6 +711,11 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
         self.assertRaises(self.failureException, self.assertItemsEqual,
                           [1, {'b': 2}, None, True], [{'b': 2}, True, None])
 
+        # Same elements which don't reliably compare, in
+        # different order, see issue 10242
+        a = [{2,4}, {1,2}]
+        b = a[::-1]
+        self.assertItemsEqual(a, b)
 
     def testAssertSetEqual(self):
         set1 = set()
index b1b026545de0ea3b6856594ac013f3fc50cb132e..dc80eb8f620dbabe027948c9acac982f7af15e7d 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -22,6 +22,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #10242: unittest.TestCase.assertItemsEqual makes too many assumgptions
+  about input.
+
 - Issue #10611: SystemExit should not cause a unittest test run to exit.
 
 - Issue #6791: Limit header line length (to 65535 bytes) in http.client,