Python unit testing with pytest as the primary framework - fixtures (`@pytest.fixture` scopes, `conftest.py`), `@pytest.mark.parametrize` table-driven tests, markers (`skip` / `xfail` / custom with `--strict-markers`), `pyproject.toml` config, mocking via pytest-mock, coverage gating with pytest-cov (`--cov-fail-under`), parallel runs with pytest-xdist, and CI wiring - plus stdlib `unittest` (TestCase, unittest.mock, discovery) and `doctest` (docstring examples, directives) as references. Includes framework choice (pytest for new code; match an existing unittest convention; doctest only for documented examples) and test-authoring conventions (framework detection from pyproject.toml/setup.cfg/tox.ini, layout matching, no fabricated attributes). Use for any Python unit-test task: setting up pytest, writing fixtures or parametrized tests, mocking, gating coverage, wiring CI, or maintaining unittest/doctest suites. For async tests, see pytest-asyncio-patterns.
72
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Companion reference for python-unit-tests. Consult for
documentation-as-tests: library code where API docs include usage examples
that must not drift from the implementation. Not a replacement for pytest -
use it as a complement (smoke + docs).
Per docs.python.org/3/library/doctest.html:
doctest embeds executable examples in docstrings: the interactive-prompt
convention (>>> ... input, expected output on the next line) becomes a
test case automatically. Examples render in help() and Sphinx HTML.
def sum(a, b):
"""Add two numbers.
>>> sum(1, 2)
3
>>> sum(-1, 1)
0
"""
return a + bpython -m doctest module.py # silent on pass
python -m doctest module.py -v # verbose; show all examplesPer dt-docs:
| Directive | Use |
|---|---|
# doctest: +ELLIPSIS | ... matches arbitrary substrings |
# doctest: +NORMALIZE_WHITESPACE | Collapse whitespace before compare |
# doctest: +SKIP | Skip this example |
# doctest: +IGNORE_EXCEPTION_DETAIL | Match exception type only |
# doctest: +DONT_ACCEPT_TRUE_FOR_1 | Strict bool != int comparison |
>>> list_users() # doctest: +ELLIPSIS
[{'id': 1, 'name': 'Alice', 'created_at': ...}, ...]>>> divide(10, 0)
Traceback (most recent call last):
...
ZeroDivisionError: division by zeroThe Traceback (most recent call last): + ... + exception line pattern
is doctest's expected-error format - it must match exactly.
pytest --doctest-modules src/ # collects doctests from all modulesor in pyproject.toml: addopts = "--doctest-modules"
(docs.pytest.org/en/stable/how-to/doctest.html).
sphinx.ext.doctest runs doctests during the Sphinx build
(sphinx-doc.org/en/master/usage/extensions/doctest.html):
sphinx-build -b doctest docs/ build/doctest/+ELLIPSIS at best.For those, use pytest (SKILL.md).
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| doctest for complex logic | Docstrings become unreadable | pytest for non-trivial tests |
| Non-deterministic output without ELLIPSIS | Fails on every run | +ELLIPSIS directive |
Wrong Traceback pattern | Exception expectation doesn't match | Follow the exact format above |