From 8442a606b82683121fc38b462f54754e22be3535 Mon Sep 17 00:00:00 2001 From: Michael Foord Date: Sat, 20 Mar 2010 16:58:04 +0000 Subject: [PATCH] Adding assertItemsEqual with tests. Issue 7832. assertSameElements still needs to be deprecated plus documentation needs to be updated. --- Lib/test/test_unittest.py | 45 +++++++++++++++++++++++++++++++++++++-- Lib/unittest/case.py | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_unittest.py b/Lib/test/test_unittest.py index 453c48d6e83..cf734f7e169 100644 --- a/Lib/test/test_unittest.py +++ b/Lib/test/test_unittest.py @@ -2775,6 +2775,47 @@ class Test_TestCase(TestCase, TestEquality, TestHashing): self.assertRaises(self.failureException, self.assertSameElements, [{'a': 1}, {'b': 2}], [{'b': 2}, {'a': 2}]) + + def testAssertItemsEqual(self): + a = object() + self.assertItemsEqual([1, 2, 3], [3, 2, 1]) + self.assertItemsEqual(['foo', 'bar', 'baz'], ['bar', 'baz', 'foo']) + self.assertItemsEqual([a, a, 2, 2, 3], (a, 2, 3, a, 2)) + self.assertItemsEqual([1, "2", "a", "a"], ["a", "2", True, "a"]) + self.assertRaises(self.failureException, self.assertItemsEqual, + [1, 2] + [3] * 100, [1] * 100 + [2, 3]) + self.assertRaises(self.failureException, self.assertItemsEqual, + [1, "2", "a", "a"], ["a", "2", True, 1]) + self.assertRaises(self.failureException, self.assertItemsEqual, + [10], [10, 11]) + self.assertRaises(self.failureException, self.assertItemsEqual, + [10, 11], [10]) + self.assertRaises(self.failureException, self.assertItemsEqual, + [10, 11, 10], [10, 11]) + + # Test that sequences of unhashable objects can be tested for sameness: + self.assertItemsEqual([[1, 2], [3, 4], 0], [False, [3, 4], [1, 2]]) + + # hashable types, but not orderable + self.assertRaises(self.failureException, self.assertItemsEqual, + [], [divmod, 'x', 1, 5j, 2j, frozenset()]) + # comparing dicts raises a py3k warning + self.assertItemsEqual([{'a': 1}, {'b': 2}], [{'b': 2}, {'a': 1}]) + # comparing heterogenous non-hashable sequences raises a py3k warning + self.assertItemsEqual([1, 'x', divmod, []], [divmod, [], 'x', 1]) + self.assertRaises(self.failureException, self.assertItemsEqual, + [], [divmod, [], 'x', 1, 5j, 2j, set()]) + self.assertRaises(self.failureException, self.assertItemsEqual, + [[1]], [[2]]) + + # Same elements, but not same sequence length + self.assertRaises(self.failureException, self.assertItemsEqual, + [1, 1, 2], [2, 1]) + self.assertRaises(self.failureException, self.assertItemsEqual, + [1, 1, "2", "a", "a"], ["2", "2", True, "a"]) + self.assertRaises(self.failureException, self.assertItemsEqual, + [1, {'b': 2}, None, True], [{'b': 2}, True, None]) + def testAssertSetEqual(self): set1 = set() set2 = set() @@ -3338,8 +3379,8 @@ class TestLongMessage(TestCase): "^Missing: 'key'$", "^Missing: 'key' : oops$"]) - def testAssertSameElements(self): - self.assertMessages('assertSameElements', ([], [None]), + def testAssertItemsEqual(self): + self.assertMessages('assertItemsEqual', ([], [None]), [r"\[None\]$", "^oops$", r"\[None\]$", r"\[None\] : oops$"]) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 89009159799..d9f35fe39c3 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -838,6 +838,44 @@ class TestCase(object): standardMsg = '\n'.join(errors) 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:: + + 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. + + Asserts that each element has the same count in both sequences. + Example: + - [0, 1, 1] and [1, 0, 1] compare equal. + - [0, 0, 1] and [0, 1] compare unequal. + """ + try: + expected = sorted(expected_seq) + actual = sorted(actual_seq) + except TypeError: + # Unsortable items (example: set(), complex(), ...) + expected = list(expected_seq) + actual = list(actual_seq) + missing, unexpected = unorderable_list_difference(expected, actual) + else: + return self.assertSequenceEqual(expected, actual, msg=msg) + + errors = [] + if missing: + errors.append('Expected, but missing:\n %s' % + safe_repr(missing)) + if unexpected: + errors.append('Unexpected, but present:\n %s' % + safe_repr(unexpected)) + if errors: + standardMsg = '\n'.join(errors) + self.fail(self._formatMessage(msg, standardMsg)) + def assertMultiLineEqual(self, first, second, msg=None): """Assert that two multi-line strings are equal.""" self.assert_(isinstance(first, str), (