mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
Issue 10242: unittest.assertItemsEqual makes too many assumptions.
This commit is contained in:
parent
db213a297d
commit
6e165b30de
5 changed files with 60 additions and 39 deletions
|
@ -1068,8 +1068,8 @@ Test cases
|
||||||
| :meth:`assertDictContainsSubset(a, b) | all the key/value pairs | 3.1 |
|
| :meth:`assertDictContainsSubset(a, b) | all the key/value pairs | 3.1 |
|
||||||
| <TestCase.assertDictContainsSubset>` | in `a` exist in `b` | |
|
| <TestCase.assertDictContainsSubset>` | in `a` exist in `b` | |
|
||||||
+---------------------------------------+--------------------------------+--------------+
|
+---------------------------------------+--------------------------------+--------------+
|
||||||
| :meth:`assertItemsEqual(a, b) | `a` and `b` have the same | 3.2 |
|
| :meth:`assertCountEqual(a, b) | `a` and `b` have the same | 3.2 |
|
||||||
| <TestCase.assertItemsEqual>` | elements in the same number, | |
|
| <TestCase.assertCountEqual>` | elements in the same number, | |
|
||||||
| | regardless of their order | |
|
| | regardless of their order | |
|
||||||
+---------------------------------------+--------------------------------+--------------+
|
+---------------------------------------+--------------------------------+--------------+
|
||||||
|
|
||||||
|
@ -1130,7 +1130,7 @@ Test cases
|
||||||
.. versionadded:: 3.1
|
.. 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*,
|
Test that sequence *expected* contains the same elements as *actual*,
|
||||||
regardless of their order. When they don't, an error message listing the
|
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
|
Duplicate elements are *not* ignored when comparing *actual* and
|
||||||
*expected*. It verifies if each element has the same count in both
|
*expected*. It verifies if each element has the same count in both
|
||||||
sequences. It is the equivalent of ``assertEqual(sorted(expected),
|
sequences. Equivalent to:
|
||||||
sorted(actual))`` but it works with sequences of unhashable objects as
|
``assertEqual(Counter(iter(expected)), Counter(iter(actual)))``
|
||||||
well.
|
but works with sequences of unhashable objects as well.
|
||||||
|
|
||||||
.. versionadded:: 3.2
|
.. 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)
|
.. method:: assertSameElements(actual, expected, msg=None)
|
||||||
|
|
||||||
|
@ -1155,7 +1161,7 @@ Test cases
|
||||||
It is the equivalent of ``assertEqual(set(expected), set(actual))``
|
It is the equivalent of ``assertEqual(set(expected), set(actual))``
|
||||||
but it works with sequences of unhashable objects as well. Because
|
but it works with sequences of unhashable objects as well. Because
|
||||||
duplicates are ignored, this method has been deprecated in favour of
|
duplicates are ignored, this method has been deprecated in favour of
|
||||||
:meth:`assertItemsEqual`.
|
:meth:`assertCountEqual`.
|
||||||
|
|
||||||
.. versionadded:: 3.1
|
.. versionadded:: 3.1
|
||||||
.. deprecated:: 3.2
|
.. deprecated:: 3.2
|
||||||
|
|
|
@ -6,6 +6,7 @@ import difflib
|
||||||
import pprint
|
import pprint
|
||||||
import re
|
import re
|
||||||
import warnings
|
import warnings
|
||||||
|
import collections
|
||||||
|
|
||||||
from . import result
|
from . import result
|
||||||
from .util import (strclass, safe_repr, sorted_list_difference,
|
from .util import (strclass, safe_repr, sorted_list_difference,
|
||||||
|
@ -990,15 +991,13 @@ class TestCase(object):
|
||||||
self.fail(self._formatMessage(msg, standardMsg))
|
self.fail(self._formatMessage(msg, standardMsg))
|
||||||
|
|
||||||
|
|
||||||
def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
|
def assertCountEqual(self, expected_seq, actual_seq, msg=None):
|
||||||
"""An unordered sequence / set specific comparison. It asserts that
|
"""An unordered sequence specific comparison. It asserts that
|
||||||
expected_seq and actual_seq contain the same elements. It is
|
expected_seq and actual_seq have the same element counts.
|
||||||
the equivalent of::
|
Equivalent to::
|
||||||
|
|
||||||
self.assertEqual(sorted(expected_seq), sorted(actual_seq))
|
self.assertEqual(Counter(iter(expected_seq)),
|
||||||
|
Counter(iter(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.
|
Asserts that each element has the same count in both sequences.
|
||||||
Example:
|
Example:
|
||||||
|
@ -1006,15 +1005,18 @@ class TestCase(object):
|
||||||
- [0, 0, 1] and [0, 1] compare unequal.
|
- [0, 0, 1] and [0, 1] compare unequal.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
expected = sorted(expected_seq)
|
expected = collections.Counter(iter(expected_seq))
|
||||||
actual = sorted(actual_seq)
|
actual = collections.Counter(iter(actual_seq))
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Unsortable items (example: set(), complex(), ...)
|
# Unsortable items (example: set(), complex(), ...)
|
||||||
expected = list(expected_seq)
|
expected = list(expected_seq)
|
||||||
actual = list(actual_seq)
|
actual = list(actual_seq)
|
||||||
missing, unexpected = unorderable_list_difference(expected, actual)
|
missing, unexpected = unorderable_list_difference(expected, actual)
|
||||||
else:
|
else:
|
||||||
return self.assertSequenceEqual(expected, actual, msg=msg)
|
if expected == actual:
|
||||||
|
return
|
||||||
|
missing = list(expected - actual)
|
||||||
|
unexpected = list(actual - expected)
|
||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
if missing:
|
if missing:
|
||||||
|
@ -1027,6 +1029,9 @@ class TestCase(object):
|
||||||
standardMsg = '\n'.join(errors)
|
standardMsg = '\n'.join(errors)
|
||||||
self.fail(self._formatMessage(msg, standardMsg))
|
self.fail(self._formatMessage(msg, standardMsg))
|
||||||
|
|
||||||
|
# Old name for assertCountEqual()
|
||||||
|
assertItemsEqual = assertCountEqual
|
||||||
|
|
||||||
def assertMultiLineEqual(self, first, second, msg=None):
|
def assertMultiLineEqual(self, first, second, msg=None):
|
||||||
"""Assert that two multi-line strings are equal."""
|
"""Assert that two multi-line strings are equal."""
|
||||||
self.assertIsInstance(first, str, 'First argument is not a string')
|
self.assertIsInstance(first, str, 'First argument is not a string')
|
||||||
|
|
|
@ -229,8 +229,8 @@ class TestLongMessage(unittest.TestCase):
|
||||||
"^Missing: 'key'$",
|
"^Missing: 'key'$",
|
||||||
"^Missing: 'key' : oops$"])
|
"^Missing: 'key' : oops$"])
|
||||||
|
|
||||||
def testAssertItemsEqual(self):
|
def testassertCountEqual(self):
|
||||||
self.assertMessages('assertItemsEqual', ([], [None]),
|
self.assertMessages('assertCountEqual', ([], [None]),
|
||||||
[r"\[None\]$", "^oops$",
|
[r"\[None\]$", "^oops$",
|
||||||
r"\[None\]$",
|
r"\[None\]$",
|
||||||
r"\[None\] : oops$"])
|
r"\[None\] : oops$"])
|
||||||
|
|
|
@ -672,46 +672,53 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||||
else:
|
else:
|
||||||
self.fail('assertMultiLineEqual did not fail')
|
self.fail('assertMultiLineEqual did not fail')
|
||||||
|
|
||||||
def testAssertItemsEqual(self):
|
def testassertCountEqual(self):
|
||||||
a = object()
|
a = object()
|
||||||
self.assertItemsEqual([1, 2, 3], [3, 2, 1])
|
self.assertCountEqual([1, 2, 3], [3, 2, 1])
|
||||||
self.assertItemsEqual(['foo', 'bar', 'baz'], ['bar', 'baz', 'foo'])
|
self.assertCountEqual(['foo', 'bar', 'baz'], ['bar', 'baz', 'foo'])
|
||||||
self.assertItemsEqual([a, a, 2, 2, 3], (a, 2, 3, a, 2))
|
self.assertCountEqual([a, a, 2, 2, 3], (a, 2, 3, a, 2))
|
||||||
self.assertItemsEqual([1, "2", "a", "a"], ["a", "2", True, "a"])
|
self.assertCountEqual([1, "2", "a", "a"], ["a", "2", True, "a"])
|
||||||
self.assertRaises(self.failureException, self.assertItemsEqual,
|
self.assertRaises(self.failureException, self.assertCountEqual,
|
||||||
[1, 2] + [3] * 100, [1] * 100 + [2, 3])
|
[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])
|
[1, "2", "a", "a"], ["a", "2", True, 1])
|
||||||
self.assertRaises(self.failureException, self.assertItemsEqual,
|
self.assertRaises(self.failureException, self.assertCountEqual,
|
||||||
[10], [10, 11])
|
[10], [10, 11])
|
||||||
self.assertRaises(self.failureException, self.assertItemsEqual,
|
self.assertRaises(self.failureException, self.assertCountEqual,
|
||||||
[10, 11], [10])
|
[10, 11], [10])
|
||||||
self.assertRaises(self.failureException, self.assertItemsEqual,
|
self.assertRaises(self.failureException, self.assertCountEqual,
|
||||||
[10, 11, 10], [10, 11])
|
[10, 11, 10], [10, 11])
|
||||||
|
|
||||||
# Test that sequences of unhashable objects can be tested for sameness:
|
# 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
|
# hashable types, but not orderable
|
||||||
self.assertRaises(self.failureException, self.assertItemsEqual,
|
self.assertRaises(self.failureException, self.assertCountEqual,
|
||||||
[], [divmod, 'x', 1, 5j, 2j, frozenset()])
|
[], [divmod, 'x', 1, 5j, 2j, frozenset()])
|
||||||
# comparing dicts
|
# 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
|
# comparing heterogenous non-hashable sequences
|
||||||
self.assertItemsEqual([1, 'x', divmod, []], [divmod, [], 'x', 1])
|
self.assertCountEqual([1, 'x', divmod, []], [divmod, [], 'x', 1])
|
||||||
self.assertRaises(self.failureException, self.assertItemsEqual,
|
self.assertRaises(self.failureException, self.assertCountEqual,
|
||||||
[], [divmod, [], 'x', 1, 5j, 2j, set()])
|
[], [divmod, [], 'x', 1, 5j, 2j, set()])
|
||||||
self.assertRaises(self.failureException, self.assertItemsEqual,
|
self.assertRaises(self.failureException, self.assertCountEqual,
|
||||||
[[1]], [[2]])
|
[[1]], [[2]])
|
||||||
|
|
||||||
# Same elements, but not same sequence length
|
# Same elements, but not same sequence length
|
||||||
self.assertRaises(self.failureException, self.assertItemsEqual,
|
self.assertRaises(self.failureException, self.assertCountEqual,
|
||||||
[1, 1, 2], [2, 1])
|
[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"])
|
[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])
|
[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):
|
def testAssertSetEqual(self):
|
||||||
set1 = set()
|
set1 = set()
|
||||||
set2 = set()
|
set2 = set()
|
||||||
|
|
|
@ -41,6 +41,9 @@ Core and Builtins
|
||||||
Library
|
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
|
- Issue #2986: difflib.SequenceMatcher gets a new parameter, autojunk, which
|
||||||
can be set to False to turn off the previously undocumented 'popularity'
|
can be set to False to turn off the previously undocumented 'popularity'
|
||||||
heuristic. Patch by Terry Reedy and Eli Bendersky.
|
heuristic. Patch by Terry Reedy and Eli Bendersky.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue