Skill: Test Framework Setup (pytest)
When to Use This Skill
This skill activates when you need to:
- Set up pytest from scratch in a Python project
- Add coverage reporting to existing tests
- Configure watch mode for test-driven development
- Fix broken pytest configurations
Prerequisites
Check if testing is already configured:
- Look for {{test_dirs}} (e.g.,
tests/,test/, or__tests__/) - Check for
pytestinrequirements.txt,pyproject.toml, orPipfile - Verify {{test_command}} exists in project configuration
If already configured: This skill provides configuration improvements and troubleshooting.
Step-by-Step Workflow
Step 1: Install pytest and Extensions
If using pip (requirements.txt):
pip install pytest pytest-cov pytest-watch
Add to requirements.txt or requirements-dev.txt:
pytest>=7.4.0
pytest-cov>=4.1.0
pytest-watch>=4.2.0
If using Poetry:
poetry add --group dev pytest pytest-cov pytest-watch
If using Pipenv:
pipenv install --dev pytest pytest-cov pytest-watch
If using conda:
conda install pytest pytest-cov
pip install pytest-watch
Step 2: Create Test Directory Structure
# Create main test directory
mkdir -p tests
# Create __init__.py to make it a package
touch tests/__init__.py
# Create conftest.py for shared fixtures
touch tests/conftest.py
# Create your first test file
touch tests/test_example.py
Add a sample test to tests/test_example.py:
def test_basic_example():
"""Basic example test to verify pytest is working."""
assert 1 + 1 == 2
def test_string_operations():
"""Test string operations."""
assert "hello".upper() == "HELLO"
Step 3: Add pytest Configuration
Option A: pytest.ini (Recommended)
Create pytest.ini in project root:
[pytest]
testpaths = tests
python_files = test_*.py *_test.py
python_classes = Test*
python_functions = test_*
addopts =
-v
--strict-markers
--cov=src
--cov-report=html
--cov-report=term-missing
--cov-report=xml
markers =
slow: marks tests as slow (deselect with '-m "not slow"')
integration: marks tests as integration tests
Option B: pyproject.toml
If using pyproject.toml, add:
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"-v",
"--strict-markers",
"--cov=src",
"--cov-report=html",
"--cov-report=term-missing",
]
markers = [
"slow: marks tests as slow",
"integration: marks tests as integration tests",
]
Note: Update --cov=src to match your source directory:
--cov=srcif source is insrc/--cov=appif source is inapp/--cov=.for current directory--cov=mypackagefor package name
Step 4: Create conftest.py with Shared Fixtures
Add to tests/conftest.py:
"""
Shared pytest fixtures and configuration.
"""
import pytest
@pytest.fixture
def sample_data():
"""Provide sample data for tests."""
return {
"name": "Test User",
"email": "test@example.com",
"age": 25
}
@pytest.fixture
def temp_directory(tmp_path):
"""Provide a temporary directory for tests."""
test_dir = tmp_path / "test_workspace"
test_dir.mkdir()
return test_dir
Step 5: Run Tests
Basic test run:
pytest
Verbose output:
pytest -v
With coverage:
pytest --cov=src --cov-report=html
Run specific test file:
pytest tests/test_example.py
Run specific test:
pytest tests/test_example.py::test_basic_example
Run tests matching pattern:
pytest -k "test_string"
Skip slow tests:
pytest -m "not slow"
Step 6: Set Up Watch Mode (Optional)
Run pytest-watch for continuous testing:
# Watch for changes and re-run tests
ptw
# Watch with verbose output
ptw -- -v
# Watch specific directory
ptw tests/
Alternative: pytest-xdist for parallel execution:
pip install pytest-xdist
pytest -n auto # Auto-detect CPU count
pytest -n 4 # Use 4 workers
Common Issues and Solutions
Issue: Tests not discovered
Symptoms: pytest finds 0 tests or can't find test files
Solutions:
- Verify test file naming:
test_*.pyor*_test.py - Check test function naming: must start with
test_ - Ensure
tests/directory has__init__.py - Check
testpathsin pytest configuration - Run with verbose discovery:
pytest --collect-only -v
Issue: Coverage not showing or incorrect
Symptoms: Coverage report shows 0% or doesn't include your code
Solutions:
- Verify
--cov=points to correct source directory - Check that source code is in the specified directory
- Ensure
__init__.pyexists in source directories - Run:
pytest --cov=. --cov-report=termto see detailed report - Check
.coveragercorpyproject.tomlcoverage config
Issue: Import errors in tests
Symptoms: ModuleNotFoundError when running tests
Solutions:
- Install package in development mode:
pip install -e . - Add project root to PYTHONPATH:
export PYTHONPATH="${PYTHONPATH}:${PWD}" - Create
conftest.pywith path modifications:
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
- Ensure
setup.pyorpyproject.tomlis configured correctly
Issue: Fixtures not found
Symptoms: fixture 'name' not found
Solutions:
- Ensure
conftest.pyexists intests/directory - Check fixture name spelling matches exactly
- Verify fixture is defined with
@pytest.fixturedecorator - Check fixture scope if using scoped fixtures
Issue: Slow test execution
Solutions:
- Use pytest-xdist for parallel execution:
pytest -n auto - Mark slow tests:
@pytest.mark.slowand skip:pytest -m "not slow" - Use fixtures to share expensive setup
- Cache database/API responses in tests
- Profile tests:
pytest --durations=10to see slowest tests
Success Criteria
- ✅ pytest runs successfully with
pytest -v - ✅ Coverage report generated in
htmlcov/directory - ✅ Tests are discovered automatically
- ✅ Sample test passes
- ✅ Coverage percentage displayed in terminal
- ✅ Watch mode works (if installed)
Additional Configuration
Integration with VS Code
Add to .vscode/settings.json:
{
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"python.testing.pytestArgs": [
"tests",
"-v"
]
}
Integration with CI/CD
GitHub Actions example:
- name: Run tests with pytest
run: |
pip install pytest pytest-cov
pytest --cov=src --cov-report=xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
Pre-commit Hook
Add to .pre-commit-config.yaml:
- repo: local
hooks:
- id: pytest-check
name: pytest
entry: pytest
language: system
pass_filenames: false
always_run: true
Related Skills
- run-tests - Commands to execute tests in configured projects
- debug-test-failures - Debugging failing tests
- code-formatting - Code formatting with black/ruff
