skip to content

Testing Idioms

Testing Python with what ships in the box — unittest cases and fixtures, unittest.mock patching, doctest. Interviewers check whether you can write trustworthy tests without a third-party runner.

part ofPythonoverview, primer and where to startread it →
on this pageshow

explore

questions

73 · 4 sections

How do you assert in unittest that a block of code emitted a WARNING log record?

level: juniorimportance: must knowfreq 45%
basics
~10 s

Wrap the call in with self.assertLogs("my.logger", level="WARNING") as captured:. The block fails unless at least one record is emitted, and afterwards captured.records holds the LogRecord objects and captured.output the formatted strings.

open as a page

How do you run a single unittest test method from the command line with `python -m unittest`?

level: juniorimportance: must knowfreq 55%
basics
~10 s

Pass its dotted path as an argument: python -m unittest package.module.ClassName.test_method. Shorten the path to run a whole module or one TestCase, and a file path such as tests/test_csv_import.py works too.

open as a page

What do setUp and tearDown do in a unittest.TestCase, and when does each run?

level: juniorimportance: must knowfreq 72%
basics
~10 s

unittest calls setUp before every test_ method and tearDown after it, on a brand-new TestCase instance built per method. setUp prepares that test's state; tearDown releases it. If setUp raises, tearDown is skipped.

open as a page

What does @unittest.skip do to a test, and why prefer it to commenting the test out?

level: juniorimportance: must knowfreq 40%
basics
~20 s

The @unittest.skip decorator stops the decorated test body from running and makes the runner report it as skipped, with the reason you supplied. The test is still collected and still counted, so the gap stays visible in the summary; a commented-out test disappears entirely.

open as a page

What does unittest's TestCase.subTest do inside a loop of test cases?

level: juniorimportance: must knowfreq 50%
basics
~20 s

unittest.TestCase.subTest is a context manager that wraps one iteration of a loop, so a failure inside it is recorded and the loop keeps going instead of the first failed assertion ending the whole test method.

open as a page

What does calling a unittest.mock.AsyncMock return, and how does that differ from Mock?

level: juniorimportance: must knowfreq 60%
basics
~10 s

Calling an AsyncMock runs nothing and hands back a coroutine object; awaiting that coroutine produces the mock's return_value. A plain Mock returns its return_value immediately, and awaiting a Mock raises TypeError.

open as a page

What does Mock.assert_called_once_with check that Mock.assert_called_with does not?

level: juniorimportance: must knowfreq 68%
basics
~10 s

assert_called_with only inspects the mock's most recent call. assert_called_once_with additionally requires that the mock was called exactly once, so a second, accidental call fails the test.

open as a page

What does unittest.mock.MagicMock configure that a plain Mock does not?

level: juniorimportance: must knowfreq 62%
basics
~10 s

MagicMock preconfigures the magic dunder methods, such as len, iter, bool and the context-manager pair, with working defaults. A plain Mock invents ordinary attributes only, so calling len() on one raises TypeError.

open as a page

How does unittest.mock.mock_open let you test a function that reads a file?

level: juniorimportance: must knowfreq 60%
basics
~20 s

unittest.mock.mock_open(read_data="...") builds a MagicMock that stands in for the builtin open. Patch open with it, and the handle the code receives serves that text from read, readline, readlines and iteration, without touching a real file.

open as a page

What are the three ways to apply unittest.mock.patch, and when is each right?

level: juniorimportance: must knowfreq 60%
basics
~20 s

unittest.mock.patch can be used as a decorator on a test function or class, as a with-statement context manager, or started and stopped by hand through a patcher object. Every form puts the original attribute back when its scope ends.

open as a page

What does Python's doctest module treat as a test inside a docstring?

level: juniorimportance: must knowfreq 40%
basics
~20 s

Any docstring line that starts with the >>> prompt. doctest runs that statement and compares whatever it prints to standard output against the lines beneath it, character for character, up to the first blank line.

open as a page

Why is a doctest brittle when its example prints a float, a set or a default repr?

level: middleimportance: should knowfreq 34%
basics
~20 s

Because doctest matches printed text exactly. 0.10 + 0.20 prints 0.30000000000000004, set order depends on the hash seed, and a default repr embeds a memory address, so the example fails for reasons unrelated to the code being correct.

open as a page

How do you run a module's doctests with doctest.testmod, python -m doctest or unittest?

level: middleimportance: should knowfreq 32%
basics
~20 s

Call doctest.testmod() inside the module to run its own docstring examples, run python -m doctest on a .py or text file from the shell, or add doctest.DocTestSuite() in a load_tests function so a normal unittest run reports them.

open as a page

When do doctests earn their place, and when should a dedicated unit test replace them?

level: seniorimportance: should knowfreq 26%
basics
~20 s

Doctests earn their place when the example is documentation first: a short, pure, deterministic call whose printed form is stable. Anything needing tolerance, fixtures, patching or many input cases belongs in a dedicated test instead.

open as a page

Why does a test that calls an async def function without awaiting it still pass?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Calling an async def function only builds a coroutine object; the body never runs. Assertions then inspect that object rather than a result, so the test passes vacuously. CPython only warns, at garbage-collection time, that the coroutine was never awaited.

open as a page

Why is a collaborator constructed inside a Python class harder to test than one passed in?

level: juniorimportance: must knowfreq 60%
basics
~20 s

A collaborator built inside the class gives a test no way in, so the only override left is patching the name the module imported. Take the collaborator as a constructor parameter and the test simply passes a small fake object.

open as a page

Why does assigning over a module attribute in a test leak into later tests?

level: juniorimportance: must knowfreq 62%
basics
~20 s

An imported module exists once per process, cached in sys.modules, so rebinding one of its attributes changes it for every user until something restores it. A plain assignment has no rollback, and a failing assertion skips the restore line.

open as a page

Why does asyncio.sleep as a synchronisation device make an async test flaky?

level: middleimportance: must knowfreq 58%
basics
~10 s

A sleep guesses how long another coroutine needs, and a loaded machine breaks the guess. Await an asyncio.Event the code under test sets instead: the handshake resumes as soon as the state is real.

open as a page

How do tempfile.TemporaryDirectory and unittest's addCleanup keep a test's scratch files isolated?

level: middleimportance: must knowfreq 60%
basics
~10 s

tempfile.TemporaryDirectory creates a fresh, uniquely named directory per test, so no two tests share a path. Registering its cleanup with TestCase.addCleanup deletes the tree even when setUp or the test itself raises.

open as a page