summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/unittest/case.py14
-rw-r--r--Lib/unittest/test/test_result.py19
-rw-r--r--Misc/NEWS3
3 files changed, 29 insertions, 7 deletions
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
index 993aaec..f19afef 100644
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -338,6 +338,16 @@ class _AssertLogsContext(_BaseTestCaseContext):
.format(logging.getLevelName(self.level), self.logger.name))
+class _OrderedChainMap(collections.ChainMap):
+ def __iter__(self):
+ seen = set()
+ for mapping in self.maps:
+ for k in mapping:
+ if k not in seen:
+ seen.add(k)
+ yield k
+
+
class TestCase(object):
"""A class whose instances are single test cases.
@@ -514,7 +524,7 @@ class TestCase(object):
return
parent = self._subtest
if parent is None:
- params_map = collections.ChainMap(params)
+ params_map = _OrderedChainMap(params)
else:
params_map = parent.params.new_child(params)
self._subtest = _SubTest(self, msg, params_map)
@@ -1418,7 +1428,7 @@ class _SubTest(TestCase):
if self.params:
params_desc = ', '.join(
"{}={!r}".format(k, v)
- for (k, v) in sorted(self.params.items()))
+ for (k, v) in self.params.items())
parts.append("({})".format(params_desc))
return " ".join(parts) or '(<subtest>)'
diff --git a/Lib/unittest/test/test_result.py b/Lib/unittest/test/test_result.py
index 0a61553..0ffb87b 100644
--- a/Lib/unittest/test/test_result.py
+++ b/Lib/unittest/test/test_result.py
@@ -307,7 +307,7 @@ class Test_TestResult(unittest.TestCase):
self.assertEqual(
result.getDescription(self._subtest),
'testGetSubTestDescriptionWithoutDocstring (' + __name__ +
- '.Test_TestResult) (bar=2, foo=1)')
+ '.Test_TestResult) (foo=1, bar=2)')
with self.subTest('some message'):
result = unittest.TextTestResult(None, True, 1)
self.assertEqual(
@@ -335,12 +335,21 @@ class Test_TestResult(unittest.TestCase):
def testGetNestedSubTestDescriptionWithoutDocstring(self):
with self.subTest(foo=1):
- with self.subTest(bar=2):
+ with self.subTest(baz=2, bar=3):
result = unittest.TextTestResult(None, True, 1)
self.assertEqual(
result.getDescription(self._subtest),
'testGetNestedSubTestDescriptionWithoutDocstring '
- '(' + __name__ + '.Test_TestResult) (bar=2, foo=1)')
+ '(' + __name__ + '.Test_TestResult) (baz=2, bar=3, foo=1)')
+
+ def testGetDuplicatedNestedSubTestDescriptionWithoutDocstring(self):
+ with self.subTest(foo=1, bar=2):
+ with self.subTest(baz=3, bar=4):
+ result = unittest.TextTestResult(None, True, 1)
+ self.assertEqual(
+ result.getDescription(self._subtest),
+ 'testGetDuplicatedNestedSubTestDescriptionWithoutDocstring '
+ '(' + __name__ + '.Test_TestResult) (baz=3, bar=4, foo=1)')
@unittest.skipIf(sys.flags.optimize >= 2,
"Docstrings are omitted with -O2 and above")
@@ -362,7 +371,7 @@ class Test_TestResult(unittest.TestCase):
self.assertEqual(
result.getDescription(self._subtest),
('testGetSubTestDescriptionWithOneLineDocstring '
- '(' + __name__ + '.Test_TestResult) (bar=2, foo=1)\n'
+ '(' + __name__ + '.Test_TestResult) (foo=1, bar=2)\n'
'Tests getDescription() for a method with a docstring.'))
@unittest.skipIf(sys.flags.optimize >= 2,
@@ -390,7 +399,7 @@ class Test_TestResult(unittest.TestCase):
self.assertEqual(
result.getDescription(self._subtest),
('testGetSubTestDescriptionWithMultiLineDocstring '
- '(' + __name__ + '.Test_TestResult) (bar=2, foo=1)\n'
+ '(' + __name__ + '.Test_TestResult) (foo=1, bar=2)\n'
'Tests getDescription() for a method with a longer '
'docstring.'))
diff --git a/Misc/NEWS b/Misc/NEWS
index fc9e1de..f33589d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -374,6 +374,9 @@ Extension Modules
Library
-------
+- bpo-30664: The description of a unittest subtest now preserves the order of
+ keyword arguments of TestCase.subTest().
+
- [Security] bpo-30730: Prevent environment variables injection in subprocess on
Windows. Prevent passing other environment variables and command arguments.