[Python-checkins] bpo-14265: Adds fully qualified test name to unittest output (GH-32138)

asvetlov webhook-mailer at python.org
Tue Mar 29 11:02:33 EDT 2022


https://github.com/python/cpython/commit/755be9b1505af591b9f2ee424a6525b6c2b65ce9
commit: 755be9b1505af591b9f2ee424a6525b6c2b65ce9
branch: main
author: Sam Ezeh <sam.z.ezeh at gmail.com>
committer: asvetlov <andrew.svetlov at gmail.com>
date: 2022-03-29T18:02:09+03:00
summary:

bpo-14265: Adds fully qualified test name to unittest output (GH-32138)

Co-authored-by: Andrew Svetlov <andrew.svetlov at gmail.com>

files:
A Misc/NEWS.d/next/Library/2022-03-27-10-41-24.bpo-14265.OBMlAi.rst
M Doc/library/unittest.rst
M Lib/unittest/case.py
M Lib/unittest/test/test_result.py
M Misc/ACKS

diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst
index 06df8ce3ad69b..9b8b75acce514 100644
--- a/Doc/library/unittest.rst
+++ b/Doc/library/unittest.rst
@@ -139,9 +139,9 @@ line, the above script produces an output that looks like this::
 Passing the ``-v`` option to your test script will instruct :func:`unittest.main`
 to enable a higher level of verbosity, and produce the following output::
 
-   test_isupper (__main__.TestStringMethods) ... ok
-   test_split (__main__.TestStringMethods) ... ok
-   test_upper (__main__.TestStringMethods) ... ok
+   test_isupper (__main__.TestStringMethods.test_isupper) ... ok
+   test_split (__main__.TestStringMethods.test_split) ... ok
+   test_upper (__main__.TestStringMethods.test_upper) ... ok
 
    ----------------------------------------------------------------------
    Ran 3 tests in 0.001s
@@ -565,10 +565,10 @@ Basic skipping looks like this::
 
 This is the output of running the example above in verbose mode::
 
-   test_format (__main__.MyTestCase) ... skipped 'not supported in this library version'
-   test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping'
-   test_maybe_skipped (__main__.MyTestCase) ... skipped 'external resource not available'
-   test_windows_support (__main__.MyTestCase) ... skipped 'requires Windows'
+   test_format (__main__.MyTestCase.test_format) ... skipped 'not supported in this library version'
+   test_nothing (__main__.MyTestCase.test_nothing) ... skipped 'demonstrating skipping'
+   test_maybe_skipped (__main__.MyTestCase.test_maybe_skipped) ... skipped 'external resource not available'
+   test_windows_support (__main__.MyTestCase.test_windows_support) ... skipped 'requires Windows'
 
    ----------------------------------------------------------------------
    Ran 4 tests in 0.005s
@@ -661,27 +661,33 @@ For example, the following test::
 will produce the following output::
 
    ======================================================================
-   FAIL: test_even (__main__.NumbersTest) (i=1)
+   FAIL: test_even (__main__.NumbersTest.test_even) (i=1)
+   Test that numbers between 0 and 5 are all even.
    ----------------------------------------------------------------------
    Traceback (most recent call last):
-     File "subtests.py", line 32, in test_even
+     File "subtests.py", line 11, in test_even
        self.assertEqual(i % 2, 0)
+       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    AssertionError: 1 != 0
 
    ======================================================================
-   FAIL: test_even (__main__.NumbersTest) (i=3)
+   FAIL: test_even (__main__.NumbersTest.test_even) (i=3)
+   Test that numbers between 0 and 5 are all even.
    ----------------------------------------------------------------------
    Traceback (most recent call last):
-     File "subtests.py", line 32, in test_even
+     File "subtests.py", line 11, in test_even
        self.assertEqual(i % 2, 0)
+       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    AssertionError: 1 != 0
 
    ======================================================================
-   FAIL: test_even (__main__.NumbersTest) (i=5)
+   FAIL: test_even (__main__.NumbersTest.test_even) (i=5)
+   Test that numbers between 0 and 5 are all even.
    ----------------------------------------------------------------------
    Traceback (most recent call last):
-     File "subtests.py", line 32, in test_even
+     File "subtests.py", line 11, in test_even
        self.assertEqual(i % 2, 0)
+       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    AssertionError: 1 != 0
 
 Without using a subtest, execution would stop after the first failure,
@@ -689,7 +695,7 @@ and the error would be less easy to diagnose because the value of ``i``
 wouldn't be displayed::
 
    ======================================================================
-   FAIL: test_even (__main__.NumbersTest)
+   FAIL: test_even (__main__.NumbersTest.test_even)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "subtests.py", line 32, in test_even
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
index 0d550204a7687..55770c06d7c5d 100644
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -478,7 +478,7 @@ def __hash__(self):
         return hash((type(self), self._testMethodName))
 
     def __str__(self):
-        return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
+        return "%s (%s.%s)" % (self._testMethodName, strclass(self.__class__), self._testMethodName)
 
     def __repr__(self):
         return "<%s testMethod=%s>" % \
diff --git a/Lib/unittest/test/test_result.py b/Lib/unittest/test/test_result.py
index c616f28dfee92..b0cc3d867d6e5 100644
--- a/Lib/unittest/test/test_result.py
+++ b/Lib/unittest/test/test_result.py
@@ -423,7 +423,7 @@ def testGetDescriptionWithoutDocstring(self):
         self.assertEqual(
                 result.getDescription(self),
                 'testGetDescriptionWithoutDocstring (' + __name__ +
-                '.Test_TextTestResult)')
+                '.Test_TextTestResult.testGetDescriptionWithoutDocstring)')
 
     def testGetSubTestDescriptionWithoutDocstring(self):
         with self.subTest(foo=1, bar=2):
@@ -431,13 +431,14 @@ def testGetSubTestDescriptionWithoutDocstring(self):
             self.assertEqual(
                     result.getDescription(self._subtest),
                     'testGetSubTestDescriptionWithoutDocstring (' + __name__ +
-                    '.Test_TextTestResult) (foo=1, bar=2)')
+                    '.Test_TextTestResult.testGetSubTestDescriptionWithoutDocstring) (foo=1, bar=2)')
+
         with self.subTest('some message'):
             result = unittest.TextTestResult(None, True, 1)
             self.assertEqual(
                     result.getDescription(self._subtest),
                     'testGetSubTestDescriptionWithoutDocstring (' + __name__ +
-                    '.Test_TextTestResult) [some message]')
+                    '.Test_TextTestResult.testGetSubTestDescriptionWithoutDocstring) [some message]')
 
     def testGetSubTestDescriptionWithoutDocstringAndParams(self):
         with self.subTest():
@@ -445,10 +446,11 @@ def testGetSubTestDescriptionWithoutDocstringAndParams(self):
             self.assertEqual(
                     result.getDescription(self._subtest),
                     'testGetSubTestDescriptionWithoutDocstringAndParams '
-                    '(' + __name__ + '.Test_TextTestResult) (<subtest>)')
+                    '(' + __name__ + '.Test_TextTestResult.testGetSubTestDescriptionWithoutDocstringAndParams) '
+                    '(<subtest>)')
 
     def testGetSubTestDescriptionForFalsyValues(self):
-        expected = 'testGetSubTestDescriptionForFalsyValues (%s.Test_TextTestResult) [%s]'
+        expected = 'testGetSubTestDescriptionForFalsyValues (%s.Test_TextTestResult.testGetSubTestDescriptionForFalsyValues) [%s]'
         result = unittest.TextTestResult(None, True, 1)
         for arg in [0, None, []]:
             with self.subTest(arg):
@@ -464,7 +466,8 @@ def testGetNestedSubTestDescriptionWithoutDocstring(self):
                 self.assertEqual(
                         result.getDescription(self._subtest),
                         'testGetNestedSubTestDescriptionWithoutDocstring '
-                        '(' + __name__ + '.Test_TextTestResult) (baz=2, bar=3, foo=1)')
+                        '(' + __name__ + '.Test_TextTestResult.testGetNestedSubTestDescriptionWithoutDocstring) '
+                        '(baz=2, bar=3, foo=1)')
 
     def testGetDuplicatedNestedSubTestDescriptionWithoutDocstring(self):
         with self.subTest(foo=1, bar=2):
@@ -473,7 +476,7 @@ def testGetDuplicatedNestedSubTestDescriptionWithoutDocstring(self):
                 self.assertEqual(
                         result.getDescription(self._subtest),
                         'testGetDuplicatedNestedSubTestDescriptionWithoutDocstring '
-                        '(' + __name__ + '.Test_TextTestResult) (baz=3, bar=4, foo=1)')
+                        '(' + __name__ + '.Test_TextTestResult.testGetDuplicatedNestedSubTestDescriptionWithoutDocstring) (baz=3, bar=4, foo=1)')
 
     @unittest.skipIf(sys.flags.optimize >= 2,
                      "Docstrings are omitted with -O2 and above")
@@ -483,7 +486,7 @@ def testGetDescriptionWithOneLineDocstring(self):
         self.assertEqual(
                 result.getDescription(self),
                ('testGetDescriptionWithOneLineDocstring '
-                '(' + __name__ + '.Test_TextTestResult)\n'
+                '(' + __name__ + '.Test_TextTestResult.testGetDescriptionWithOneLineDocstring)\n'
                 'Tests getDescription() for a method with a docstring.'))
 
     @unittest.skipIf(sys.flags.optimize >= 2,
@@ -495,7 +498,9 @@ def testGetSubTestDescriptionWithOneLineDocstring(self):
             self.assertEqual(
                 result.getDescription(self._subtest),
                ('testGetSubTestDescriptionWithOneLineDocstring '
-                '(' + __name__ + '.Test_TextTestResult) (foo=1, bar=2)\n'
+                '(' + __name__ + '.Test_TextTestResult.testGetSubTestDescriptionWithOneLineDocstring) '
+                '(foo=1, bar=2)\n'
+
                 'Tests getDescription() for a method with a docstring.'))
 
     @unittest.skipIf(sys.flags.optimize >= 2,
@@ -508,7 +513,7 @@ def testGetDescriptionWithMultiLineDocstring(self):
         self.assertEqual(
                 result.getDescription(self),
                ('testGetDescriptionWithMultiLineDocstring '
-                '(' + __name__ + '.Test_TextTestResult)\n'
+                '(' + __name__ + '.Test_TextTestResult.testGetDescriptionWithMultiLineDocstring)\n'
                 'Tests getDescription() for a method with a longer '
                 'docstring.'))
 
@@ -523,7 +528,8 @@ def testGetSubTestDescriptionWithMultiLineDocstring(self):
             self.assertEqual(
                 result.getDescription(self._subtest),
                ('testGetSubTestDescriptionWithMultiLineDocstring '
-                '(' + __name__ + '.Test_TextTestResult) (foo=1, bar=2)\n'
+                '(' + __name__ + '.Test_TextTestResult.testGetSubTestDescriptionWithMultiLineDocstring) '
+                '(foo=1, bar=2)\n'
                 'Tests getDescription() for a method with a longer '
                 'docstring.'))
 
@@ -582,17 +588,17 @@ def testDotsOutput(self):
     def testLongOutput(self):
         classname = f'{__name__}.{self.Test.__qualname__}'
         self.assertEqual(self._run_test('testSuccess', 2),
-                         f'testSuccess ({classname}) ... ok\n')
+                         f'testSuccess ({classname}.testSuccess) ... ok\n')
         self.assertEqual(self._run_test('testSkip', 2),
-                         f"testSkip ({classname}) ... skipped 'skip'\n")
+                         f"testSkip ({classname}.testSkip) ... skipped 'skip'\n")
         self.assertEqual(self._run_test('testFail', 2),
-                         f'testFail ({classname}) ... FAIL\n')
+                         f'testFail ({classname}.testFail) ... FAIL\n')
         self.assertEqual(self._run_test('testError', 2),
-                         f'testError ({classname}) ... ERROR\n')
+                         f'testError ({classname}.testError) ... ERROR\n')
         self.assertEqual(self._run_test('testExpectedFailure', 2),
-                         f'testExpectedFailure ({classname}) ... expected failure\n')
+                         f'testExpectedFailure ({classname}.testExpectedFailure) ... expected failure\n')
         self.assertEqual(self._run_test('testUnexpectedSuccess', 2),
-                         f'testUnexpectedSuccess ({classname}) ... unexpected success\n')
+                         f'testUnexpectedSuccess ({classname}.testUnexpectedSuccess) ... unexpected success\n')
 
     def testDotsOutputSubTestSuccess(self):
         self.assertEqual(self._run_test('testSubTestSuccess', 1), '.')
@@ -600,7 +606,7 @@ def testDotsOutputSubTestSuccess(self):
     def testLongOutputSubTestSuccess(self):
         classname = f'{__name__}.{self.Test.__qualname__}'
         self.assertEqual(self._run_test('testSubTestSuccess', 2),
-                         f'testSubTestSuccess ({classname}) ... ok\n')
+                         f'testSubTestSuccess ({classname}.testSubTestSuccess) ... ok\n')
 
     def testDotsOutputSubTestMixed(self):
         self.assertEqual(self._run_test('testSubTestMixed', 1), 'sFE')
@@ -608,10 +614,10 @@ def testDotsOutputSubTestMixed(self):
     def testLongOutputSubTestMixed(self):
         classname = f'{__name__}.{self.Test.__qualname__}'
         self.assertEqual(self._run_test('testSubTestMixed', 2),
-                f'testSubTestMixed ({classname}) ... \n'
-                f"  testSubTestMixed ({classname}) [skip] (b=2) ... skipped 'skip'\n"
-                f'  testSubTestMixed ({classname}) [fail] (c=3) ... FAIL\n'
-                f'  testSubTestMixed ({classname}) [error] (d=4) ... ERROR\n')
+                f'testSubTestMixed ({classname}.testSubTestMixed) ... \n'
+                f"  testSubTestMixed ({classname}.testSubTestMixed) [skip] (b=2) ... skipped 'skip'\n"
+                f'  testSubTestMixed ({classname}.testSubTestMixed) [fail] (c=3) ... FAIL\n'
+                f'  testSubTestMixed ({classname}.testSubTestMixed) [error] (d=4) ... ERROR\n')
 
     def testDotsOutputTearDownFail(self):
         out = self._run_test('testSuccess', 1, AssertionError('fail'))
@@ -627,19 +633,19 @@ def testLongOutputTearDownFail(self):
         classname = f'{__name__}.{self.Test.__qualname__}'
         out = self._run_test('testSuccess', 2, AssertionError('fail'))
         self.assertEqual(out,
-                         f'testSuccess ({classname}) ... FAIL\n')
+                         f'testSuccess ({classname}.testSuccess) ... FAIL\n')
         out = self._run_test('testError', 2, AssertionError('fail'))
         self.assertEqual(out,
-                         f'testError ({classname}) ... ERROR\n'
-                         f'testError ({classname}) ... FAIL\n')
+                         f'testError ({classname}.testError) ... ERROR\n'
+                         f'testError ({classname}.testError) ... FAIL\n')
         out = self._run_test('testFail', 2, Exception('error'))
         self.assertEqual(out,
-                         f'testFail ({classname}) ... FAIL\n'
-                         f'testFail ({classname}) ... ERROR\n')
+                         f'testFail ({classname}.testFail) ... FAIL\n'
+                         f'testFail ({classname}.testFail) ... ERROR\n')
         out = self._run_test('testSkip', 2, AssertionError('fail'))
         self.assertEqual(out,
-                         f"testSkip ({classname}) ... skipped 'skip'\n"
-                         f'testSkip ({classname}) ... FAIL\n')
+                         f"testSkip ({classname}.testSkip) ... skipped 'skip'\n"
+                         f'testSkip ({classname}.testSkip) ... FAIL\n')
 
 
 classDict = dict(unittest.TestResult.__dict__)
@@ -852,7 +858,7 @@ def test_foo(self):
         expected_out = '\nStdout:\nset up\n'
         self.assertEqual(stdout.getvalue(), expected_out)
         self.assertEqual(len(result.errors), 1)
-        description = f'test_foo ({strclass(Foo)})'
+        description = f'test_foo ({strclass(Foo)}.test_foo)'
         test_case, formatted_exc = result.errors[0]
         self.assertEqual(str(test_case), description)
         self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
@@ -874,7 +880,7 @@ def test_foo(self):
         expected_out = '\nStdout:\ntear down\n'
         self.assertEqual(stdout.getvalue(), expected_out)
         self.assertEqual(len(result.errors), 1)
-        description = f'test_foo ({strclass(Foo)})'
+        description = f'test_foo ({strclass(Foo)}.test_foo)'
         test_case, formatted_exc = result.errors[0]
         self.assertEqual(str(test_case), description)
         self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
@@ -897,7 +903,7 @@ def test_foo(self):
         expected_out = '\nStdout:\nset up\ndo cleanup2\ndo cleanup1\n'
         self.assertEqual(stdout.getvalue(), expected_out)
         self.assertEqual(len(result.errors), 2)
-        description = f'test_foo ({strclass(Foo)})'
+        description = f'test_foo ({strclass(Foo)}.test_foo)'
         test_case, formatted_exc = result.errors[0]
         self.assertEqual(str(test_case), description)
         self.assertIn('ValueError: bad cleanup2', formatted_exc)
@@ -928,7 +934,7 @@ def test_foo(self):
         expected_out = '\nStdout:\nset up\ndo cleanup2\ndo cleanup1\n'
         self.assertEqual(stdout.getvalue(), expected_out)
         self.assertEqual(len(result.errors), 3)
-        description = f'test_foo ({strclass(Foo)})'
+        description = f'test_foo ({strclass(Foo)}.test_foo)'
         test_case, formatted_exc = result.errors[0]
         self.assertEqual(str(test_case), description)
         self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
@@ -971,7 +977,7 @@ def test_foo(self):
         expected_out = '\nStdout:\nset up\ntear down\ndo cleanup2\ndo cleanup1\n'
         self.assertEqual(stdout.getvalue(), expected_out)
         self.assertEqual(len(result.errors), 3)
-        description = f'test_foo ({strclass(Foo)})'
+        description = f'test_foo ({strclass(Foo)}.test_foo)'
         test_case, formatted_exc = result.errors[0]
         self.assertEqual(str(test_case), description)
         self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
diff --git a/Misc/ACKS b/Misc/ACKS
index efa2474c3cfdb..72e2cfe13775a 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -516,6 +516,7 @@ Daniel Evers
 evilzero
 Winston Ewert
 Greg Ewing
+Sam Ezeh
 Martijn Faassen
 Clovis Fabricio
 Andreas Faerber
diff --git a/Misc/NEWS.d/next/Library/2022-03-27-10-41-24.bpo-14265.OBMlAi.rst b/Misc/NEWS.d/next/Library/2022-03-27-10-41-24.bpo-14265.OBMlAi.rst
new file mode 100644
index 0000000000000..308ce36c6ba50
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-03-27-10-41-24.bpo-14265.OBMlAi.rst
@@ -0,0 +1 @@
+Adds the fully qualified test name to unittest output



More information about the Python-checkins mailing list