test-coverage-review
An automated testing companion for Python that audits coverage and writes robust pytest-based test suites.
Install
mkdir -p .claude/skills/test-coverage-review && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/14994" && unzip -o skill.zip -d .claude/skills/test-coverage-review && rm skill.zipInstalls to .claude/skills/test-coverage-review
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Audit, plan, write, and verify unit tests for Python projects using pytest. Use this skill whenever someone asks to review test coverage, write tests, add missing tests, check if code is properly tested, improve test quality, or ensure new features have tests. Trigger on phrases like "write tests for this", "add unit tests", "check my test coverage", "review my tests", "are my tests good enough", "this needs tests", "test this module", or any request involving pytest, unittest, test files, mocking, fixtures, or code coverage in a Python project. Also trigger when someone finishes writing a feature and needs tests before the work is considered complete, or when they ask about testing best practices.Key capabilities
- →Discover project structure and test directories
- →Map source modules to test files and identify missing tests
- →Audit test quality against best practices
- →Run coverage reports and identify uncovered lines
- →Write new unit tests for new code
- →Fill test coverage gaps by prioritizing error handlers and public API methods
How it works
The skill audits existing Python test coverage, identifies gaps, and writes new unit tests following pytest best practices, ensuring code quality and coverage.
Inputs & outputs
When to use test-coverage-review
- →Reviewing test suite quality
- →Filling test coverage gaps
- →Writing unit tests for new features
- →Checking test suite efficiency
- →Implementing mock objects and fixtures
About this skill
Test Coverage Review
This skill audits test coverage in Python projects, identifies gaps, writes new tests, and verifies that the test suite passes — all following pytest best practices.
Before you start
Read the best-practices reference file to ground your work:
cat references/best-practices.md
Use the practices and source citations in that file as your authoritative checklist.
Modes of operation
Determine the mode from the user's request.
Mode 1 — Audit existing test coverage
Use when the user says "review my tests", "check my coverage", or "are my tests good enough".
Step 1: Discover the project structure
Identify:
- The package name and layout (flat or
src/layout) - The test directory (
tests/,test/, or co-located) - The test framework in use (pytest, unittest, or both)
- Any
conftest.pyfiles and shared fixtures - Coverage configuration in
pyproject.toml,setup.cfg, or.coveragerc
Step 2: Map source modules to test files
For every public module in the package, check whether a corresponding test file exists. Flag modules with no test file at all.
| Source module | Test file | Status |
|---|---|---|
mypackage/api.py | tests/test_api.py | ✅ exists |
mypackage/parser.py | — | ❌ missing |
Step 3: Audit test quality
For each existing test file, check against the reference checklist:
- Naming — File named
test_<module>.py, classes prefixedTest, methods prefixedtest_. - Docstrings — Module-level docstring, class docstring, method docstrings.
- Structure — Tests grouped in classes by the unit under test, with section dividers between classes.
- Isolation — No test depends on another test's state or execution order.
- Mock boundaries — External I/O (HTTP, filesystem, database) is mocked. Internal methods are tested directly, not mocked.
- Fixtures — Shared setup uses
@pytest.fixture, notsetUp()or duplicated code. - Sample data — Test data defined as module-level constants (not buried inside fixtures or test methods).
- Edge cases — Empty inputs, invalid inputs, boundary conditions, and error paths are tested.
- Assertions — Each test has clear, specific assertions. No tests that only check "does not raise".
- Coverage — Every public method/function has at least one test. Every branch (if/else, try/except) has coverage.
Step 4: Run coverage (if possible)
pytest tests/ --cov=<package> --cov-report=term-missing --tb=short -q
Report:
- Overall coverage percentage
- Specific lines/branches not covered
- Which modules are below the project's coverage threshold
Step 5: Produce the audit report
Output a markdown table of findings:
| File | Issue | Severity | Source |
|---|---|---|---|
tests/test_api.py | No tests for error paths in fetch() | critical | [PYTEST-GOOD] |
tests/test_parser.py | _parse() mocked instead of tested directly | warning | [MOCK-BOUND] |
| — | No test file for mypackage/utils.py | critical | [COVERAGE] |
Severity levels:
- critical — Public code with no tests, untested error paths, missing test files, live API calls in tests.
- warning — Missing docstrings, over-mocking, duplicated setup code, missing edge cases.
- info — Style suggestions, parametrize opportunities, fixture improvements.
Mode 2 — Write tests for new code
Use when the user says "write tests for this", "add tests for this module", or has just finished a feature.
Step 1: Analyze the code under test
Read the module and identify:
- Every public class and its public methods
- Every public function
- Constructor parameters and their types
- Return types and possible exceptions
- External dependencies (HTTP calls, file I/O, database, etc.)
- Edge cases (empty inputs, None values, invalid types, boundary conditions)
Step 2: Plan test categories
For each public class or function, plan tests in these categories:
| Category | What to test |
|---|---|
| Happy path | Normal inputs produce expected outputs |
| Edge cases | Empty inputs, None, zero, boundary values |
| Error handling | Invalid inputs raise expected exceptions |
| Return types | Return values have correct types and structure |
| Side effects | External calls are made with correct arguments |
| State changes | Object state changes correctly after method calls |
Present the plan to the user before writing.
Step 3: Write the test file
Follow this structure:
"""Tests for <module description>."""
from unittest.mock import patch, MagicMock
import pytest
from <package>.<module> import <Class>, <function>
# ---------------------------------------------------------------------------
# Sample data
# ---------------------------------------------------------------------------
SAMPLE_DATA = ... # Module-level test data constants
# ---------------------------------------------------------------------------
# <ClassName> tests
# ---------------------------------------------------------------------------
class Test<ClassName>:
"""Tests for the <ClassName> <type>."""
def test_<behavior>(self):
"""Verify <what is being tested>."""
# Arrange
...
# Act
...
# Assert
...
Rules:
- One test file per source module:
test_<module>.py - Group related tests in
class Test<Name>:with class docstrings - Docstring on every test method:
"""Verify <what>.""" - Section dividers (
# ---) between test classes - Follow Arrange-Act-Assert pattern within each test
- Sample data as module-level constants, not inside tests
- Shared setup in
@pytest.fixture, notsetUp()
Step 4: Mock at the boundary
Mock external dependencies only:
requests.get/requests.postfor HTTP callsopen/pathlib.Pathfor file I/O- Database connections and cursors
- Third-party API clients
time.sleep,datetime.nowwhen testing time-dependent logic
Do NOT mock:
- Internal methods of the class under test
- Private helper functions
- Data transformation logic
- Anything that can be tested directly with sample data
# CORRECT — mock the HTTP boundary
@patch("mypackage.api.requests.get")
def test_fetch_sends_timeout(self, mock_get):
mock_get.return_value = MagicMock(status_code=200, json=lambda: {})
client = APIClient()
client.fetch("https://example.com")
_, kwargs = mock_get.call_args
assert kwargs["timeout"] == 10
# WRONG — don't mock internal methods
@patch.object(Parser, "_transform") # ← test this directly instead
def test_parse(self, mock_transform):
...
Step 5: Run and verify
After writing tests:
# Run the new tests
pytest tests/test_<module>.py -v --tb=short
# Run the full suite to check for regressions
pytest tests/ --tb=short -q
# Check coverage of the new module
pytest tests/ --cov=<package>.<module> --cov-report=term-missing
Report the test count and pass/fail status. Note the count for the changelog entry:
- **tests/test_<module>.py**: N unit tests for <description>.
Mode 3 — Fill coverage gaps
Use when the user says "improve my coverage", "fill the gaps", or coverage reports show low percentages.
Step 1: Identify uncovered code
Run coverage and parse the Missing column to identify:
- Untested functions/methods
- Untested branches (if/else paths, try/except handlers)
- Untested error paths
- Dead code (code that can never be reached — flag for removal)
Step 2: Prioritize by risk
Write tests for gaps in this order:
- Error handlers — untested
exceptblocks, validation failures - Public API methods — any public method with zero tests
- Branch coverage — untested
if/elsepaths - Edge cases — boundary conditions in already-tested functions
- Private methods — only if they contain complex logic
Step 3: Write gap-filling tests
Add tests to existing test files (don't create new files if a test file already exists for that module). Follow the same structure and conventions as the existing tests.
Step 4: Re-run coverage and report
Show before/after coverage numbers for the affected modules.
Constraints
- Always use pytest unless the project explicitly uses a different framework.
Do not introduce unittest-style classes (
TestCase,self.assertEqual) into a pytest-native project. - Never make live API/network calls — all tests must run offline with mocks.
- Never modify source code to make it testable — if something is hard to test, note it as a finding but don't refactor the source.
- One behavior per test — each test method should verify one specific behavior. If a test has many unrelated assertions, split it.
- Tests must be deterministic — no random data, no time-dependent assertions, no ordering dependencies between tests.
- Preserve existing tests — when filling gaps, add to existing test files. Do not restructure or rename existing tests unless the user requests it.
When not to use it
- →The project does not use Python or pytest
- →The task requires modifying source code to make it testable
- →The task involves making live API/network calls in tests
Limitations
- →Always use pytest unless the project explicitly uses a different framework.
- →Never make live API/network calls; all tests must run offline with mocks.
- →Never modify source code to make it testable.
How it compares
This skill provides a structured, multi-mode approach to test coverage review and creation, including specific audit steps and gap-filling strategies, unlike a general test writing utility.
Compared to similar skills
test-coverage-review side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| test-coverage-review (this skill) | 0 | 3mo | Review | Intermediate |
| python-testing-patterns | 77 | 2mo | Review | Intermediate |
| backtesting-frameworks | 17 | 2mo | No flags | Advanced |
| temporal-python-testing | 8 | 4mo | No flags | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
python-testing-patterns
wshobson
Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development. Use when writing Python tests, setting up test suites, or implementing testing best practices.
backtesting-frameworks
wshobson
Build robust backtesting systems for trading strategies with proper handling of look-ahead bias, survivorship bias, and transaction costs. Use when developing trading algorithms, validating strategies, or building backtesting infrastructure.
temporal-python-testing
wshobson
Test Temporal workflows with pytest, time-skipping, and mocking strategies. Covers unit testing, integration testing, replay testing, and local development setup. Use when implementing Temporal workflow tests or debugging test failures.
home-assistant-integration-knowledge
home-assistant
Everything you need to know to build, test and review Home Assistant Integrations. If you're looking at an integration, you must use this as your primary reference.
testing-python
jlowin
Write and evaluate effective Python tests using pytest. Use when writing tests, reviewing test code, debugging test failures, or improving test coverage. Covers test design, fixtures, parameterization, mocking, and async testing.
pr-review
pytorch
Review PyTorch pull requests for code quality, test coverage, security, and backward compatibility. Use when reviewing PRs, when asked to review code changes, or when the user mentions "review PR", "code review", or "check this PR".