# Python subtests
Today I learned what Python subtests are. The Distinguishing test iterations using subtests (opens new window) section in the unittest
docs explain it very well.
It is similar to Pytest's @pytest.mark.parametrize
(opens new window) because it also allows you to test different sets of arguments using a single test function.
It is best illustarted with an example:
import unittest
class PowerTest(unittest.TestCase):
def test_power(self):
parameters = [
# (base, power, expected_result)
(1, 1, 1),
(1, 2, 1),
(2, 2, 4),
(3, 2, 9),
]
for p in parameters:
with self.subTest(base=p[0], power=p[1]):
self.assertEqual(p[0] ** p[1], p[2])
2
3
4
5
6
7
8
9
10
11
12
13
14
15
We can pass any arguments to self.subTest
that will give any failed tests more context. For example, if we add two more parameters (3, 1, 4), (4, 2, 4)
and run the test, the output will be:
======================================================================
FAIL: test_power (test.PowerTest) (base=3, power=1)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 21, in test_power
self.assertEqual(p[0] ** p[1], p[2])
AssertionError: 3 != 4
======================================================================
FAIL: test_power (test.PowerTest) (base=4, power=2)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 21, in test_power
self.assertEqual(p[0] ** p[1], p[2])
AssertionError: 16 != 4
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=2)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
We see above that instead of stopping further execution of the failing test method, Python continued to run other subtests in the function.
When we remove the self.subTest
context manager, the output will be:
F
======================================================================
FAIL: test_power (test.PowerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 20, in test_power
self.assertEqual(p[0] ** p[1], p[2])
AssertionError: 3 != 4
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
2
3
4
5
6
7
8
9
10
11
12
13
This gives us much less context about the test and Python didn't run the rest of the parameters after getting one failure.
Newsletter
If you'd like to subscribe to my blog, please enter your details below. You can unsubscribe at any time.