When a single positional argument is passed to subTest(), if the argument is false, its value won't be displayed in the output -- () will appear instead: >>> import unittest >>> class NumbersTest(unittest.TestCase): ... def test_odd(self): ... for i in range(4): ... with self.subTest(i): # single positional arg ... self.assertNotEqual(i%2, 0) ... >>> unittest.main(exit=False) ====================================================================== FAIL: test_odd (__main__.NumbersTest) () ---------------------------------------------------------------------- Traceback (most recent call last): File "", line 5, in test_odd AssertionError: 0 == 0 ====================================================================== FAIL: test_odd (__main__.NumbersTest) [2] ---------------------------------------------------------------------- Traceback (most recent call last): File "", line 5, in test_odd AssertionError: 0 == 0 ---------------------------------------------------------------------- Ran 1 test in 0.001s FAILED (failures=2) This is because subTest() accepts a positional "msg" arg, passes it to _SubTest (Lib/unittest/case.py:515), and then _SubTest checks using "if self._message:" (Lib/unittest/case.py:1400). I think it would be better to check the message against a sentinel value instead.
I think Ezio's suggestion of a sentinel value would be better, allowing None to be using as a legitimate 'message' [1]. That is, somewhere at global scope, define '_subtest_msg_sentinel = object()', change the msg default at Lib/unittest/case.py:500 to be 'msg=_subtest_msg_sentinel', and change the check at Lib/unittest/case.py:1400 to check 'if message is not _subtest_msg_sentinel'. [1] For example: class TruthTest(unittest.TestCase): def test_truth(self): for o in None, 1, 0, [], (4,): with self.subTest(o): self.assertTrue(o) Should print failure results including '[None]', '[0]', and '[[]]'.