Skip to main content

pytest-doctor

pytest-doctor is a CLI tool that diagnoses weak or broken pytest suites and provides a 0–100 health score with actionable recommendations.

It combines linting, dead code detection, and test quality analysis to pinpoint gaps in test coverage, isolation issues, and performance problems—then integrates with coding agents for automated fixes.

Core Capabilities

  • Gap analysis: highlights what your tests miss (logic paths, edge cases, and risk areas)
  • Test quality checks: detects fixture usage issues, isolation problems, missing parametrization
  • Dead code detection: finds unused test utilities, fixtures, and helper functions
  • Scoring system: 0–100 health metric (Critical <50, Needs work 50–74, Good 75+)
  • Agent-friendly output: structured recommendations that coding agents can apply directly

Installation

Install pytest-doctor with uv:

uv pip install pytest-doctor

Or with pip:

pip install pytest-doctor

Quick Start

# Scan your project
pytest-doctor .

# Verbose mode with detailed paths and recommendations
pytest-doctor . --verbose

# Scan only changed files (requires git)
pytest-doctor . --diff main

# Output results as JSON
pytest-doctor . --json

# Save JSON results to a file
pytest-doctor . --output results.json

# Request automated fixes via agent
pytest-doctor . --fix

CLI Flags

  • PATH: Directory to scan (default: current directory)
  • --verbose, -v: Enable verbose output with detailed recommendations
  • --fix: Generate agent-friendly output with structured recommendations and deeplinks. Creates .pytest-doctor/diagnostics.json with complete analysis, context, and navigation links
  • --diff REF: Scan only files changed compared to a git reference (e.g., main, HEAD~1)
  • --json: Output complete diagnostics in JSON format to stdout
  • --output FILE: Write JSON diagnostics to the specified file
  • --version: Show version and exit
  • -h, --help: Show help message

Configuration

Configure via pytest-doctor.config.json, pyproject.toml, or CLI flags:

pytest-doctor.config.json

{
  "ignore": {
    "rules": ["E501", "custom/slow-test"],
    "files": ["tests/legacy/**", "tests/generated/**"]
  },
  "lint": true,
  "deadCode": true,
  "testAnalysis": true,
  "verbose": false
}

pyproject.toml

[tool.pytest-doctor]
lint = true
deadCode = true
testAnalysis = true
verbose = false

[tool.pytest-doctor.ignore]
rules = ["E501", "custom/slow-test"]
files = ["tests/legacy/**", "tests/generated/**"]

Configuration Options

  • lint (bool): Enable ruff linting for test files (default: true)
  • deadCode (bool): Enable vulture dead code detection (default: true)
  • testAnalysis (bool): Enable test quality analysis (default: true)
  • verbose (bool): Enable verbose output (default: false)
  • ignore.rules (list): Rule IDs to ignore (e.g., "E501", "RUF001")
  • ignore.files (list): File glob patterns to ignore

Configuration Precedence

CLI flags override pyproject.toml settings, which override pytest-doctor.config.json, which override defaults.

Architecture

The tool runs three parallel analysis passes:

  1. Linting (ruff) – detects correctness, performance, security, and async issues
  2. Dead code detection (vulture) – finds unused test utilities and fixtures
  3. Test quality – flags isolation issues, missing parametrization, slow tests

Results are aggregated, scored, and rendered with actionable recommendations.

Output Formats

Human-Readable Output (default)

============================================================
pytest-doctor Diagnostic Report
============================================================

Health Score: 75/100 [⚠ NEEDS WORK]

Summary:
  Critical: 0
  Warning:  3
  Info:     12
  Total:    15

Findings:
------------------------------------------------------------

tests/test_example.py
  ⚠ Line 45: Line too long (120 > 100 characters) [E501]
  ℹ Line 67: Test test_example has 30 lines (>20 is a code smell) [large-test]
    → Break test into smaller, focused tests
...

Health score meanings:

  • 75-100: Good - Few issues found
  • 50-74: Needs Work - Multiple issues should be addressed
  • <50: Critical - Suite requires significant improvements

JSON Output

Use --json flag to output complete diagnostics:

pytest-doctor . --json

JSON Schema:

{
  "version": "0.1.0",
  "path": ".",
  "score": 75,
  "summary": {
    "critical": 0,
    "warning": 3,
    "info": 12
  },
  "total_issues": 15,
  "results": [
    {
      "engine": "ruff",
      "issues": [
        {
          "file_path": "tests/test_example.py",
          "line_number": 45,
          "column_number": 100,
          "rule_id": "E501",
          "rule_name": "Line too long",
          "message": "Line too long (120 > 100 characters)",
          "severity": "warning",
          "source": "linting",
          "recommendation": "Break line into multiple lines"
        }
      ],
      "duration_ms": 125.45
    }
  ],
  "all_issues": [...],
  "issues": {
    "tests/test_example.py": [...]
  }
}

Filtering by Changed Files

Scan only files changed relative to a git reference:

# Compare to main branch
pytest-doctor . --diff main

# Compare to a specific commit
pytest-doctor . --diff abc123

# Compare to previous version
pytest-doctor . --diff HEAD~1

This is useful for CI/CD pipelines to report only issues in changed code.

Agent Integration

Using the --fix Flag (Recommended)

The --fix flag generates agent-friendly output with structured recommendations and deeplinks:

# Generate agent-friendly output with deeplinks
pytest-doctor . --fix

This creates a .pytest-doctor/diagnostics.json file with:

  • Context: project path, health score, issue counts
  • Suggestions: structured fix recommendations for each issue
  • Deeplinks: file:// and https:// links for easy navigation to:
    • Diagnostics summary JSON
    • Critical issues (if any)
    • Documentation and fix guides

The output includes all information needed by coding agents to understand and fix issues automatically.

JSON-Based Integration

For local or remote coding agents, you can also use JSON output:

# Pipe diagnostics to your agent
pytest-doctor . --json | your-agent --fix

# Or save to file
pytest-doctor . --output diagnostics.json
your-agent diagnostics.json --fix

The JSON output includes:

  • All issues with file paths, line numbers, and severity
  • Actionable recommendations for each issue
  • Health score and summary statistics
  • Source information (which analyzer found the issue)

Agent Output Format (--fix)

When using --fix, the output follows this structure:

{
  "context": {
    "project_path": ".",
    "health_score": 57,
    "total_issues": 125,
    "critical_count": 0,
    "warning_count": 31,
    "info_count": 94
  },
  "suggestions": [
    {
      "file_path": "src/pytest_doctor/cli.py",
      "line_number": 81,
      "rule_id": "untested-function",
      "rule_name": "Function appears untested",
      "message": "Function 'main' with 29 code paths may not be tested",
      "severity": "warning",
      "recommendation": "Add test case(s) for main covering all branches",
      "context_lines": []
    }
  ],
  "deeplinks": {
    "diagnostics_summary": "file://./.pytest-doctor/diagnostics.json",
    "documentation": "https://github.com/pytest-doctor/pytest-doctor#agent-integration",
    "fix_guide": "https://github.com/pytest-doctor/pytest-doctor#fixing-issues"
  },
  "version": "0.1.0"
}

Integration Examples

Python-based agent:

import json
import subprocess

# Get diagnostics via --fix flag
result = subprocess.run(['pytest-doctor', '.', '--fix'], 
                       capture_output=True, text=True)
agent_output = json.loads(result.stdout)

# Access context and suggestions
context = agent_output['context']
print(f"Health Score: {context['health_score']}/100")

for suggestion in agent_output['suggestions']:
    print(f"Fix {suggestion['rule_id']} in {suggestion['file_path']}:{suggestion['line_number']}")
    print(f"Recommendation: {suggestion['recommendation']}")

# Open diagnostics file via deeplink
diagnostics_url = agent_output['deeplinks']['diagnostics_summary']
print(f"See full diagnostics: {diagnostics_url}")

Shell-based agent:

#!/bin/bash
pytest-doctor . --fix | jq '.suggestions[] | 
  {file: .file_path, line: .line_number, recommendation: .recommendation}'

Goal: let agents not only make tests pass, but make tests trustworthy.

Development

Running Tests

uv run pytest tests/

Code Coverage

uv run pytest tests/ --cov=src/pytest_doctor --cov-report=html

Code Quality

# Format code
uv run black src/ tests/

# Lint code
uv run ruff check src/ tests/

# Type check
uv run mypy src/

License

MIT

Release files for pytest-doctor 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-doctor 1.0.0
File Size Uploaded
pytest_doctor-1.0.0.tar.gz 5.5 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-doctor 1.0.0
File Interpreter ABI Platform
pytest_doctor-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 5.5 MB

Release files / pytest_doctor-1.0.0.tar.gz

Download URL pytest_doctor-1.0.0.tar.gz
Size 5.5 MB
Tags Source
SHA-256 checksum
How to use checksums
a5e99e1c049cbcc540e2b9be5675b371d3d3afc3714168a516f369091cf7fb6b
BLAKE2b-256 checksum
How to use checksums
6a5472d1bc84c23a5d1200f77ab4c96054839399660e43dd8d8ba5079e94b317
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / pytest_doctor-1.0.0-py3-none-any.whl

Download URL pytest_doctor-1.0.0-py3-none-any.whl
Size 27.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
41d07960ff5b8a2a014e59befa01462fa6f05f895ee835848912a648d6aab2e4
BLAKE2b-256 checksum
How to use checksums
aa3f13c61b18a20f2d826695383cf5ddedee685431f4662a119be2ede23960f8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page