Skip to main content

Lib/unittest/case.py (part 2)

Source:

cpython 3.14 @ ab2d84fe1023/Lib/unittest/case.py

This annotation covers context-manager assertions, test lifecycle hooks, and skipping/expected-failure markers. See lib_unittest_detail for TestCase.run, assertEqual family, and the assertion infrastructure.

Map

LinesSymbolRole
1-80_AssertRaisesContextContext manager returned by assertRaises
81-200assertRaises / assertRaisesRegexVerify an exception is raised
201-350assertWarns / assertWarnsRegexVerify a warning is issued
351-500subTestMark a sub-case within a test; failures don't stop the test
501-650addCleanup / doCleanupsRegister teardown callbacks
651-800skipIf / skipUnlessConditional skip decorators
801-900expectedFailureMark a test expected to fail
901-1400Numeric/sequence assertionsassertAlmostEqual, assertSequenceEqual, assertDictEqual

Reading

assertRaises as context manager

# CPython: Lib/unittest/case.py:195 assertRaises
def assertRaises(self, expected_exception, *args, **kwargs):
context = _AssertRaisesContext(expected_exception, self)
try:
return context.handle('assertRaises', args, kwargs)
except Exception:
raise

class _AssertRaisesContext:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, tb):
if exc_type is None:
raise self.failureException(
f'{self.expected.__name__} not raised')
if not issubclass(exc_type, self.expected):
return False # re-raise unexpected exception
self.exception = exc_value.with_traceback(None)
return True # suppress the expected exception

subTest

# CPython: Lib/unittest/case.py:370 subTest
@contextmanager
def subTest(self, msg=_subtest_msg_sentinel, **params):
"""Context manager for a sub-case that can fail without stopping the test."""
parent = self._subtest
if parent is None:
params_map = _OrderedChainMap(params)
else:
params_map = parent.params.new_child(params)
self._subtest = _SubTest(self, msg, params_map)
try:
with self._outcome.testPartExecutor(self._subtest):
yield
finally:
self._subtest = parent

Failed subtests are collected; the parent test is marked as failed after all subtests run.

addCleanup

# CPython: Lib/unittest/case.py:520 addCleanup
def addCleanup(self, function, /, *args, **kwargs):
"""Register a function to be called after tearDown (LIFO order)."""
self._cleanups.append((function, args, kwargs))

def doCleanups(self):
"""Called by TestCase.run() after tearDown."""
outcome = self._outcome
while self._cleanups:
function, args, kwargs = self._cleanups.pop()
with outcome.testPartExecutor(self):
function(*args, **kwargs)
return outcome.success

skipIf / expectedFailure

# CPython: Lib/unittest/case.py:672 skipIf
def skipIf(condition, reason):
"""Skip the test if condition is true."""
if condition:
return skip(reason)
return lambda x: x

# CPython: Lib/unittest/case.py:820 expectedFailure
def expectedFailure(test_item):
"""Mark a test as expected to fail.
If it passes, it is counted as an unexpected success."""
test_item.__unittest_expecting_failure__ = True
return test_item

expectedFailure wraps the test in _ExpectedFailure; if the test passes, the runner reports it as u (unexpected success).

assertAlmostEqual

# CPython: Lib/unittest/case.py:920 assertAlmostEqual
def assertAlmostEqual(self, first, second, places=7,
msg=None, delta=None):
if first == second:
return
if delta is not None and places is not None:
raise TypeError("specify delta or places, not both")
diff = abs(second - first)
if delta is not None:
if diff <= delta: return
msg = self._formatMessage(msg,
f'{first!r} != {second!r} within {delta!r} delta ({diff!r})')
else:
if round(diff, places) == 0: return
msg = self._formatMessage(msg,
f'{first!r} != {second!r} within {places!r} places ({diff!r})')
raise self.failureException(msg)

gopy notes

unittest is pure Python. subTest uses @contextmanager (gopy's lib_contextlib_detail). assertRaises as a context manager uses __exit__ to inspect the exception. addCleanup is implemented in TestCase with a _cleanups list; gopy's list append/pop handles this correctly.