Getting Started¶
This guide will help you get up and running with pytest-test-categories in just a few minutes.
Prerequisites¶
Python 3.11 or higher
pytest 8.0 or higher
Installation¶
Install pytest-test-categories using pip:
pip install pytest-test-categories
Or with uv:
uv add pytest-test-categories
Basic Usage¶
Step 1: Mark Your Tests¶
Add size markers to your tests to categorize them:
import pytest
@pytest.mark.small
def test_addition():
"""Small tests must complete in under 1 second."""
assert 1 + 1 == 2
@pytest.mark.medium
def test_database_query(db_connection):
"""Medium tests can take up to 5 minutes."""
result = db_connection.query("SELECT * FROM users")
assert len(result) > 0
@pytest.mark.large
def test_end_to_end_workflow(app):
"""Large tests can take up to 15 minutes."""
# Full workflow test
pass
Step 2: Run Your Tests¶
Run pytest as usual:
pytest
The plugin will automatically:
Count tests by size category
Append size labels to test IDs (e.g.,
test_addition[SMALL])Enforce time limits for each test
Report distribution statistics
Step 3: Review the Output¶
After tests complete, you’ll see a distribution summary:
======================== Test Size Distribution ========================
Small: 45 tests (81.8%) - Target: 80% +/- 5% [OK]
Medium: 8 tests (14.5%) - Target: 15% +/- 5% [OK]
Large: 2 tests ( 3.6%) - Target: 5% +/- 3% [OK]
========================================================================
Test Size Guidelines¶
Small Tests (< 1 second)¶
Small tests are the foundation of a healthy test suite. They should be:
Fast: Complete in under 1 second
Hermetic: No external dependencies (network, filesystem, databases)
Deterministic: Same input always produces same output
Parallelizable: Safe to run concurrently
@pytest.mark.small
def test_email_validation():
from myapp.validators import validate_email
assert validate_email("user@example.com") is True
assert validate_email("invalid") is False
Medium Tests (< 5 minutes)¶
Medium tests may access local services:
Local databases (PostgreSQL, MySQL, SQLite)
Local caches (Redis, Memcached)
Local mock servers
@pytest.mark.medium
def test_user_repository(postgres_connection):
from myapp.repositories import UserRepository
repo = UserRepository(postgres_connection)
user = repo.find_by_email("alice@example.com")
assert user is not None
Large Tests (< 15 minutes)¶
Large tests may access external services:
External APIs
Staging environments
Third-party services
@pytest.mark.large
def test_payment_integration(staging_api):
from myapp.payments import process_payment
result = process_payment(amount=100, currency="USD")
assert result.success is True
XLarge Tests (< 15 minutes)¶
XLarge tests are for extended test scenarios that need the full time allocation but aren’t necessarily accessing external services.
Using Base Test Classes¶
As an alternative to markers, you can inherit from base test classes:
from pytest_test_categories import SmallTest, MediumTest
class TestEmailValidator(SmallTest):
def test_valid_email(self):
assert validate_email("user@example.com") is True
class TestUserRepository(MediumTest):
def test_find_user(self, db):
user = UserRepository(db).find_by_email("test@example.com")
assert user is not None
Next Steps¶
Learn about timing enforcement
Configure distribution validation
Set up test reporting
Understand resource isolation for hermetic tests
Explore network isolation enforcement
See common patterns for mocking strategies