testdesiderata
Lint Python test files against Kent Beck's 12 Test Desiderata. Static analysis only — no test execution required.
$ testdesiderata tests/
tests/test_payment.py
14:4 DET001 [Deterministic] random.choice() produces non-deterministic results
31:8 ISO003 [Isolated] open() in tests creates file system dependencies
52:4 FST001 [Fast] time.sleep() in tests slows down the suite
67:4 BHV001 [Behavioral] MagicMock() substitutes real behavior
4 violations in 1 file
Installation
pip install testdesiderata
pip install "testdesiderata[ai]" # AI review for Writable/Inspiring desiderata
Usage
testdesiderata tests/ # lint a directory
testdesiderata --select DET,FST tests/ # only deterministic + fast rules
testdesiderata --ignore BHV tests/ # skip behavioral rules
testdesiderata --ai tests/ # include AI review
Exit code 0 = clean, 1 = violations. Suitable for CI.
Configuration
[tool.testdesiderata]
select = ["DET", "FST", "ISO"]
ignore = ["BHV"]
CLI flags override config. Config is found by walking up from the working directory.
Suppress a single violation inline:
def test_something():
x = random.randint(1, 10) # noqa: DET001
# noqa (bare) suppresses everything on the line; # noqa: DET suppresses a whole prefix.
Rules
| Prefix | Desideratum | What it catches |
|---|---|---|
DET |
Deterministic | random, datetime.now, uuid4, os.urandom, numpy.random |
ISO |
Isolated | global, env mutation, file I/O, network, DB connections, tempfile, shutil, subprocess |
FST |
Fast | time.sleep, polling loops |
AUT |
Automated | input(), breakpoint(), pdb.set_trace() |
BHV |
Behavioral | Mock/MagicMock, @patch, mocker.spy, autospec=False |
STR |
Structure-insensitive | .assert_called_with() and related mock methods |
SPC |
Specific | bare/broad except, compound assert without message, raises(Exception) |
PRD |
Predictive | pytest.skip, @mark.skip, @mark.xfail without strict=True |
CMP |
Composable | >10 assertions or >50 lines per test |
RDL |
Readable | non-descriptive names, long tests without docstrings |
WRT |
Writable | boilerplate cost, maintenance burden (requires --ai) |
INS |
Inspiring | weak assertions, missing edge cases (requires --ai) |
Full rule reference: docs/rules.md
Python API
from testdesiderata.linter import Linter
linter = Linter()
violations = linter.lint_path(Path("tests/"))
for v in violations:
print(v) # tests/test_auth.py:14:4: DET001 [Deterministic] ...
Slow test detection
Pass --junit report.xml (or let the CLI auto-detect) to flag tests exceeding --slow seconds (default 1.0).
MCP server
pip install "testdesiderata[mcp]"
claude mcp add testdesiderata -- python -m testdesiderata.mcp_server
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file testdesiderata-0.1.2.tar.gz.
File metadata
- Download URL: testdesiderata-0.1.2.tar.gz
- Upload date:
- Size: 201.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9025e1c8deaed1a4953afbcee2417e30c3497aaa19421e991aec805b5f49aee
|
|
| MD5 |
64721d407e3bc6b1ab6801a43bab83bc
|
|
| BLAKE2b-256 |
9fb09d0bdb009f5807ab985462fd84aa9fe89cf65f5c59115fc85343c693985e
|
Provenance
The following attestation bundles were made for testdesiderata-0.1.2.tar.gz:
Publisher:
ci.yml on benomahony/testdesiderata
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
testdesiderata-0.1.2.tar.gz -
Subject digest:
c9025e1c8deaed1a4953afbcee2417e30c3497aaa19421e991aec805b5f49aee - Sigstore transparency entry: 2784450832
- Sigstore integration time:
-
Permalink:
benomahony/testdesiderata@fcd1b9cd83c23f2ba8c0f05555f7a532ac0ff707 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/benomahony
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@fcd1b9cd83c23f2ba8c0f05555f7a532ac0ff707 -
Trigger Event:
push
-
Statement type:
File details
Details for the file testdesiderata-0.1.2-py3-none-any.whl.
File metadata
- Download URL: testdesiderata-0.1.2-py3-none-any.whl
- Upload date:
- Size: 24.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b7e01cf54e96f513fb9fc5bf3b6cdf52ed2ff752864bc1ff3d22ac72f7c0205
|
|
| MD5 |
4a6bc227e50d65b6557df9b89fc34dd2
|
|
| BLAKE2b-256 |
eda637140b0b8e39ddd7fb76ea7873cc3c624a167339efcb217ba9688cc68cb0
|
Provenance
The following attestation bundles were made for testdesiderata-0.1.2-py3-none-any.whl:
Publisher:
ci.yml on benomahony/testdesiderata
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
testdesiderata-0.1.2-py3-none-any.whl -
Subject digest:
0b7e01cf54e96f513fb9fc5bf3b6cdf52ed2ff752864bc1ff3d22ac72f7c0205 - Sigstore transparency entry: 2784450857
- Sigstore integration time:
-
Permalink:
benomahony/testdesiderata@fcd1b9cd83c23f2ba8c0f05555f7a532ac0ff707 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/benomahony
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@fcd1b9cd83c23f2ba8c0f05555f7a532ac0ff707 -
Trigger Event:
push
-
Statement type: