Index: Lib/unittest/test/test_case.py =================================================================== --- Lib/unittest/test/test_case.py (revision 86620) +++ Lib/unittest/test/test_case.py (working copy) @@ -711,7 +711,13 @@ 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() set2 = set() Index: Lib/unittest/case.py =================================================================== --- Lib/unittest/case.py (revision 86620) +++ Lib/unittest/case.py (working copy) @@ -6,6 +6,7 @@ import pprint import re import warnings +import collections from . import result from .util import ( @@ -843,8 +844,8 @@ 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:: + expected_seq and actual_seq contain the same elements in the same + quantities. It is the equivalent of:: self.assertEqual(sorted(expected_seq), sorted(actual_seq)) @@ -864,8 +865,8 @@ "comparing unequal types"]: warnings.filterwarnings("ignore", _msg, DeprecationWarning) try: - expected = sorted(expected_seq) - actual = sorted(actual_seq) + expected_cnt = collections.Counter(iter(expected_seq)) + actual_cnt = collections.Counter(iter(actual_seq)) except TypeError: # Unsortable items (example: set(), complex(), ...) expected = list(expected_seq) @@ -874,7 +875,8 @@ expected, actual, ignore_duplicate=False ) else: - return self.assertSequenceEqual(expected, actual, msg=msg) + missing = [i for i in expected_cnt if expected_cnt[i] != actual_cnt[i]] + unexpected = [i for i in actual_cnt if actual_cnt[i] != expected_cnt[i]] errors = [] if missing: