Issue 10242: unittest.assertItemsEqual makes too many assumptions.

This commit is contained in:
Raymond Hettinger 2010-11-27 09:31:37 +00:00
parent db213a297d
commit 6e165b30de
5 changed files with 60 additions and 39 deletions

View file

@ -6,6 +6,7 @@ import difflib
import pprint
import re
import warnings
import collections
from . import result
from .util import (strclass, safe_repr, sorted_list_difference,
@ -990,15 +991,13 @@ 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::
def assertCountEqual(self, expected_seq, actual_seq, msg=None):
"""An unordered sequence specific comparison. It asserts that
expected_seq and actual_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(expected_seq)),
Counter(iter(actual_seq)))
Asserts that each element has the same count in both sequences.
Example:
@ -1006,15 +1005,18 @@ class TestCase(object):
- [0, 0, 1] and [0, 1] compare unequal.
"""
try:
expected = sorted(expected_seq)
actual = sorted(actual_seq)
expected = collections.Counter(iter(expected_seq))
actual = collections.Counter(iter(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)
if expected == actual:
return
missing = list(expected - actual)
unexpected = list(actual - expected)
errors = []
if missing:
@ -1027,6 +1029,9 @@ class TestCase(object):
standardMsg = '\n'.join(errors)
self.fail(self._formatMessage(msg, standardMsg))
# Old name for assertCountEqual()
assertItemsEqual = assertCountEqual
def assertMultiLineEqual(self, first, second, msg=None):
"""Assert that two multi-line strings are equal."""
self.assertIsInstance(first, str, 'First argument is not a string')

View file

@ -229,8 +229,8 @@ class TestLongMessage(unittest.TestCase):
"^Missing: 'key'$",
"^Missing: 'key' : oops$"])
def testAssertItemsEqual(self):
self.assertMessages('assertItemsEqual', ([], [None]),
def testassertCountEqual(self):
self.assertMessages('assertCountEqual', ([], [None]),
[r"\[None\]$", "^oops$",
r"\[None\]$",
r"\[None\] : oops$"])

View file

@ -672,46 +672,53 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
else:
self.fail('assertMultiLineEqual did not fail')
def testAssertItemsEqual(self):
def testassertCountEqual(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,
self.assertCountEqual([1, 2, 3], [3, 2, 1])
self.assertCountEqual(['foo', 'bar', 'baz'], ['bar', 'baz', 'foo'])
self.assertCountEqual([a, a, 2, 2, 3], (a, 2, 3, a, 2))
self.assertCountEqual([1, "2", "a", "a"], ["a", "2", True, "a"])
self.assertRaises(self.failureException, self.assertCountEqual,
[1, 2] + [3] * 100, [1] * 100 + [2, 3])
self.assertRaises(self.failureException, self.assertItemsEqual,
self.assertRaises(self.failureException, self.assertCountEqual,
[1, "2", "a", "a"], ["a", "2", True, 1])
self.assertRaises(self.failureException, self.assertItemsEqual,
self.assertRaises(self.failureException, self.assertCountEqual,
[10], [10, 11])
self.assertRaises(self.failureException, self.assertItemsEqual,
self.assertRaises(self.failureException, self.assertCountEqual,
[10, 11], [10])
self.assertRaises(self.failureException, self.assertItemsEqual,
self.assertRaises(self.failureException, self.assertCountEqual,
[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]])
self.assertCountEqual([[1, 2], [3, 4], 0], [False, [3, 4], [1, 2]])
# hashable types, but not orderable
self.assertRaises(self.failureException, self.assertItemsEqual,
self.assertRaises(self.failureException, self.assertCountEqual,
[], [divmod, 'x', 1, 5j, 2j, frozenset()])
# comparing dicts
self.assertItemsEqual([{'a': 1}, {'b': 2}], [{'b': 2}, {'a': 1}])
self.assertCountEqual([{'a': 1}, {'b': 2}], [{'b': 2}, {'a': 1}])
# comparing heterogenous non-hashable sequences
self.assertItemsEqual([1, 'x', divmod, []], [divmod, [], 'x', 1])
self.assertRaises(self.failureException, self.assertItemsEqual,
self.assertCountEqual([1, 'x', divmod, []], [divmod, [], 'x', 1])
self.assertRaises(self.failureException, self.assertCountEqual,
[], [divmod, [], 'x', 1, 5j, 2j, set()])
self.assertRaises(self.failureException, self.assertItemsEqual,
self.assertRaises(self.failureException, self.assertCountEqual,
[[1]], [[2]])
# Same elements, but not same sequence length
self.assertRaises(self.failureException, self.assertItemsEqual,
self.assertRaises(self.failureException, self.assertCountEqual,
[1, 1, 2], [2, 1])
self.assertRaises(self.failureException, self.assertItemsEqual,
self.assertRaises(self.failureException, self.assertCountEqual,
[1, 1, "2", "a", "a"], ["2", "2", True, "a"])
self.assertRaises(self.failureException, self.assertItemsEqual,
self.assertRaises(self.failureException, self.assertCountEqual,
[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.assertCountEqual(a, b)
def testAssertSetEqual(self):
set1 = set()
set2 = set()