Skip to content

Commit c9b3ef2

Browse files
committed
Issue #16997: unittest.TestCase now provides a subTest() context manager to procedurally generate, in an easy way, small test instances.
1 parent a612176 commit c9b3ef2

File tree

10 files changed

+539
-105
lines changed

10 files changed

+539
-105
lines changed

Doc/library/unittest.rst

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,68 @@ Skipped tests will not have :meth:`setUp` or :meth:`tearDown` run around them.
556556
Skipped classes will not have :meth:`setUpClass` or :meth:`tearDownClass` run.
557557

558558

559+
.. _subtests:
560+
561+
Distinguishing test iterations using subtests
562+
---------------------------------------------
563+
564+
.. versionadded:: 3.4
565+
566+
When some of your tests differ only by a some very small differences, for
567+
instance some parameters, unittest allows you to distinguish them inside
568+
the body of a test method using the :meth:`~TestCase.subTest` context manager.
569+
570+
For example, the following test::
571+
572+
class NumbersTest(unittest.TestCase):
573+
574+
def test_even(self):
575+
"""
576+
Test that numbers between 0 and 5 are all even.
577+
"""
578+
for i in range(0, 6):
579+
with self.subTest(i=i):
580+
self.assertEqual(i % 2, 0)
581+
582+
will produce the following output::
583+
584+
======================================================================
585+
FAIL: test_even (__main__.NumbersTest) (i=1)
586+
----------------------------------------------------------------------
587+
Traceback (most recent call last):
588+
File "subtests.py", line 32, in test_even
589+
self.assertEqual(i % 2, 0)
590+
AssertionError: 1 != 0
591+
592+
======================================================================
593+
FAIL: test_even (__main__.NumbersTest) (i=3)
594+
----------------------------------------------------------------------
595+
Traceback (most recent call last):
596+
File "subtests.py", line 32, in test_even
597+
self.assertEqual(i % 2, 0)
598+
AssertionError: 1 != 0
599+
600+
======================================================================
601+
FAIL: test_even (__main__.NumbersTest) (i=5)
602+
----------------------------------------------------------------------
603+
Traceback (most recent call last):
604+
File "subtests.py", line 32, in test_even
605+
self.assertEqual(i % 2, 0)
606+
AssertionError: 1 != 0
607+
608+
Without using a subtest, execution would stop after the first failure,
609+
and the error would be less easy to diagnose because the value of ``i``
610+
wouldn't be displayed::
611+
612+
======================================================================
613+
FAIL: test_even (__main__.NumbersTest)
614+
----------------------------------------------------------------------
615+
Traceback (most recent call last):
616+
File "subtests.py", line 32, in test_even
617+
self.assertEqual(i % 2, 0)
618+
AssertionError: 1 != 0
619+
620+
559621
.. _unittest-contents:
560622

561623
Classes and functions
@@ -669,6 +731,21 @@ Test cases
669731
.. versionadded:: 3.1
670732

671733

734+
.. method:: subTest(msg=None, **params)
735+
736+
Return a context manager which executes the enclosed code block as a
737+
subtest. *msg* and *params* are optional, arbitrary values which are
738+
displayed whenever a subtest fails, allowing you to identify them
739+
clearly.
740+
741+
A test case can contain any number of subtest declarations, and
742+
they can be arbitrarily nested.
743+
744+
See :ref:`subtests` for more information.
745+
746+
.. versionadded:: 3.4
747+
748+
672749
.. method:: debug()
673750

674751
Run the test without collecting the result. This allows exceptions raised
@@ -1733,6 +1810,22 @@ Loading and running tests
17331810
:attr:`unexpectedSuccesses` attribute.
17341811

17351812

1813+
.. method:: addSubTest(test, subtest, outcome)
1814+
1815+
Called when a subtest finishes. *test* is the test case
1816+
corresponding to the test method. *subtest* is a custom
1817+
:class:`TestCase` instance describing the subtest.
1818+
1819+
If *outcome* is :const:`None`, the subtest succeeded. Otherwise,
1820+
it failed with an exception where *outcome* is a tuple of the form
1821+
returned by :func:`sys.exc_info`: ``(type, value, traceback)``.
1822+
1823+
The default implementation does nothing when the outcome is a
1824+
success, and records subtest failures as normal failures.
1825+
1826+
.. versionadded:: 3.4
1827+
1828+
17361829
.. class:: TextTestResult(stream, descriptions, verbosity)
17371830

17381831
A concrete implementation of :class:`TestResult` used by the

Lib/test/test_socket.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import unittest
44
from test import support
5-
from unittest.case import _ExpectedFailure
65

76
import errno
87
import io
@@ -272,9 +271,6 @@ def clientRun(self, test_func):
272271
raise TypeError("test_func must be a callable function")
273272
try:
274273
test_func()
275-
except _ExpectedFailure:
276-
# We deliberately ignore expected failures
277-
pass
278274
except BaseException as e:
279275
self.queue.put(e)
280276
finally:

0 commit comments

Comments
 (0)