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