summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/unittest.rst20
-rw-r--r--Lib/unittest/case.py27
-rw-r--r--Lib/unittest/test/test_assertions.py4
-rw-r--r--Lib/unittest/test/test_case.py45
-rw-r--r--Misc/NEWS3
5 files changed, 60 insertions, 39 deletions
diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst
index f2c6dee..2236f72 100644
--- a/Doc/library/unittest.rst
+++ b/Doc/library/unittest.rst
@@ -1068,8 +1068,8 @@ Test cases
| :meth:`assertDictContainsSubset(a, b) | all the key/value pairs | 3.1 |
| <TestCase.assertDictContainsSubset>` | in `a` exist in `b` | |
+---------------------------------------+--------------------------------+--------------+
- | :meth:`assertItemsEqual(a, b) | `a` and `b` have the same | 3.2 |
- | <TestCase.assertItemsEqual>` | elements in the same number, | |
+ | :meth:`assertCountEqual(a, b) | `a` and `b` have the same | 3.2 |
+ | <TestCase.assertCountEqual>` | elements in the same number, | |
| | regardless of their order | |
+---------------------------------------+--------------------------------+--------------+
@@ -1130,7 +1130,7 @@ Test cases
.. versionadded:: 3.1
- .. method:: assertItemsEqual(actual, expected, msg=None)
+ .. method:: assertCountEqual(expected, actual, msg=None)
Test that sequence *expected* contains the same elements as *actual*,
regardless of their order. When they don't, an error message listing the
@@ -1138,12 +1138,18 @@ Test cases
Duplicate elements are *not* ignored when comparing *actual* and
*expected*. It verifies if each element has the same count in both
- sequences. It is the equivalent of ``assertEqual(sorted(expected),
- sorted(actual))`` but it works with sequences of unhashable objects as
- well.
+ sequences. Equivalent to:
+ ``assertEqual(Counter(iter(expected)), Counter(iter(actual)))``
+ but works with sequences of unhashable objects as well.
.. versionadded:: 3.2
+ .. method:: assertItemsEqual(actual, expected, msg=None)
+
+ Outdated name for :meth:`assertCountEqual`, kept for compatibility
+ with Python 2.7.
+
+ .. versionadded:: 3.2
.. method:: assertSameElements(actual, expected, msg=None)
@@ -1155,7 +1161,7 @@ Test cases
It is the equivalent of ``assertEqual(set(expected), set(actual))``
but it works with sequences of unhashable objects as well. Because
duplicates are ignored, this method has been deprecated in favour of
- :meth:`assertItemsEqual`.
+ :meth:`assertCountEqual`.
.. versionadded:: 3.1
.. deprecated:: 3.2
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
index dbf7aa2..f59c068 100644
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -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')
diff --git a/Lib/unittest/test/test_assertions.py b/Lib/unittest/test/test_assertions.py
index 91eb8bf..6a30db6 100644
--- a/Lib/unittest/test/test_assertions.py
+++ b/Lib/unittest/test/test_assertions.py
@@ -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$"])
diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py
index 07904d4..aa8cc37 100644
--- a/Lib/unittest/test/test_case.py
+++ b/Lib/unittest/test/test_case.py
@@ -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()
diff --git a/Misc/NEWS b/Misc/NEWS
index f90deb9..07f0570 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -41,6 +41,9 @@ Core and Builtins
Library
-------
+- Issue #10242: Fixed implementation of unittest.ItemsEqual and gave it
+ a new more informative name, unittest.CountEqual.
+
- Issue #2986: difflib.SequenceMatcher gets a new parameter, autojunk, which
can be set to False to turn off the previously undocumented 'popularity'
heuristic. Patch by Terry Reedy and Eli Bendersky.