testing-pytest
Skill5 starsChanged 16 days agoMITView on GitHub
Pytest testing skill with modern patterns - use for writing Python tests with fixtures, parametrization, and modular design
1 other project uses a version of this.
Adopted by
Most recently taken up by
- mhihasan/agentic-sdlctheir own version, first seen Oct 15, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- mhihasan/agentic-sdlc★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository50 other files it gives its agents.
- analyze-pr-commentsSkill
- architecture-analyzeSkill
- architecture-tradeoffSkill
- askSkill
- code-smellsSkill
- debugging-rocprof-sysSkill
- exploration-explore-codeSkill
- git-commitSkill
- git-gh-clientSkill
- git-prepare-pull-requestSkill
- git-pull-request-statusSkill
- gitSkill
- grill-meSkill
- library-amd-smiSkill
- notify-meSkill
- planning-architectureSkill
- planning-baseSkill
- planning-bugfixSkill
- planning-docsSkill
- planning-featureSkill
- planning-refactorSkill
- programming-cmake-best-practicesSkill
- programming-cpp-constexprSkill
- programming-cpp-design-patternsSkill
- programming-cpp-naming-rulesSkill
- programming-cpp-policy-based-diSkill
- programming-cppSkill
- programming-cpp-stl-algorithmsSkill
- programming-pythonSkill
- pr-review-interactiveSkill
- pr-reviewSkill
- radisha-create-skillSkill
- radisha-helpSkill
- radisha-improve-skillSkill
- radisha-skillsSkill
- radisha-updateSkill
- refactoring-techniquesSkill
- review-architectureSkill
- rocprofsys-buildSkill
- rocprofsys-configureSkill
- rocprofsysSkill
- static-analysisSkill
- testing-gtest-gmockSkill
- testing-testplanSkill
- therock-build-to-commitSkill
- therock-commit-in-buildSkill
- therock-first-build-with-commitSkill
- update-pr-descriptionSkill
- verify-pmc-metricsSkill
- watchSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 4 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Use this skill when writing Python tests with pytest framework.
- Distinctive: line 11
Follow pytest best practices for modern, modular, and reusable test design.
- Distinctive: line 13
Pytest is the standard: Use pytest for all Python testing.
- Distinctive: line 17
Fixtures over setup/teardown: Use pytest fixtures for test dependencies and resource management, not setUp/tearDown methods.
- Very specific: line 19
Parametrize for data-driven tests: Use @pytest.mark.parametrize instead of writing multiple similar test functions.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Pytest Testing Skill
Use this skill when writing Python tests with pytest framework.
<IMPORTANT>
Follow pytest best practices for modern, modular, and reusable test design.Pytest is the standard. Use pytest for all Python testing.
Tests MUST be isolated. Each test should be independent and not rely on execution order or state from other tests.
Fixtures over setup/teardown. Use pytest fixtures for test dependencies and resource management, not setUp/tearDown methods.
Parametrize for data-driven tests. Use @pytest.mark.parametrize instead of writing multiple similar test functions.
Organize tests logically. Mirror the source code structure in your test directory. Group related tests in classes when appropriate.
Test behavior, not implementation. Focus on testing what the code does, not how it does it. This makes tests resilient to refactoring.
</IMPORTANT>
Pytest Basics
Test Discovery and Naming
Pytest automatically discovers tests following these conventions:
# File naming: test_*.py or *_test.py
test_user.py # ✓ Discovered
user_test.py # ✓ Discovered
test_models.py # ✓ Discovered
models.py # ✗ Not discovered
# Function naming: test_*
def test_user_creation(): # ✓ Discovered
pass
def test_invalid_email(): # ✓ Discovered
pass
def helper_function(): # ✗ Not a test (no test_ prefix)
pass
# Class naming: Test* (no __init__)
class TestUser: # ✓ Discovered
def test_creation(self):
pass
class TestUserValidation: # ✓ Discovered
def test_email(self):
pass
class UserHelper: # ✗ Not a test class
passBasic Test Structure
from myapp.models import User
def test_user_creation():
"""Test that a user can be created with valid data."""
# Arrange
username = "alice"
email = "alice@example.com"
# Act
user = User(username=username, email=email)
# Assert
assert user.username == "alice"
assert user.email == "alice@example.com"
assert user.is_active is True # Default value
def test_user_invalid_email():
"""Test that invalid email raises ValueError."""
with pytest.raises(ValueError, match="Invalid email"):
User(username="bob", email="not-an-email")Running Tests
# Run all tests
pytest
# Run specific file
pytest tests/test_user.py
# Run specific test
pytest tests/test_user.py::test_user_creation
# Run tests matching pattern
pytest -k "user and not invalid"
# Run with verbose output
pytest -v
# Run with coverage
pytest --cov=myapp --cov-report=html
# Run and stop at first failure
pytest -x
# Run last failed tests
pytest --lf
# Run in parallel (requires pytest-xdist)
pytest -n autoAssertions
Basic Assertions
import pytest
def test_assertions():
"""Demonstrate pytest assertion introspection."""
# Equality
assert result == expected
assert user.name == "Alice"
# Identity
assert value is None
assert obj is not None
# Membership
assert "admin" in user.roles
assert item not in processed_items
# Comparison
assert age >= 18
assert count < MAX_COUNT
# Boolean
assert user.is_active
assert not user.is_deleted
# Type checking
assert isinstance(result, dict)
assert isinstance(user, User)
def test_approximate_equality():
"""Test floating point with tolerance."""
import math
result = math.sqrt(2) ** 2
assert result == pytest.approx(2.0, rel=1e-9)
def test_assertion_messages():
"""Add custom messages to assertions."""
assert user.age >= 18, f"User {user.name} is underage: {user.age}"Exception Testing
import pytest
def test_exception_raised():
"""Test that exception is raised."""
with pytest.raises(ValueError):
process_invalid_data()
def test_exception_with_message():
"""Test exception message matches pattern."""
with pytest.raises(ValueError, match="Invalid email format"):
User(email="not-an-email")
def test_exception_details():
"""Test exception attributes."""
with pytest.raises(APIError) as exc_info:
call_api_with_invalid_token()
assert exc_info.value.status_code == 401
assert "authentication" in str(exc_info.value).lower()
def test_no_exception():
"""Test that no exception is raised."""
# Just call the function - if it raises, test fails
result = process_valid_data()
assert result is not NoneWarnings Testing
import pytest
import warnings
def test_deprecated_function():
"""Test that deprecated function shows warning."""
with pytest.warns(DeprecationWarning, match="deprecated"):
old_function()
def test_warning_details():
"""Test warning details."""
with pytest.warns(UserWarning) as warning_list:
trigger_warning()
assert len(warning_list) == 1
assert "careful" in str(warning_list[0].message)Fixtures
Basic Fixtures
import pytest
from myapp.database import Database
from myapp.models import User
@pytest.fixture
def database():
"""Provide a database connection for tests."""
db = Database(":memory:")
db.create_tables()
yield db # Provide to test
db.close() # Cleanup after test
@pytest.fixture
def sample_user():
"""Provide a sample user for tests."""
return User(username="alice", email="alice@example.com")
def test_user_save(database, sample_user):
"""Test saving user to database."""
# Fixtures are automatically injected by name
database.save(sample_user)
retrieved = database.get_user(sample_user.id)
assert retrieved.username == "alice"Fixture Scopes
import pytest
# Function scope (default): Run once per test function
@pytest.fixture
def temp_file():
"""Create temp file for each test."""
file = create_temp_file()
yield file
file.delete()
# Class scope: Run once per test class
@pytest.fixture(scope="class")
def database_connection():
"""Create database connection for test class."""
conn = Database.connect()
yield conn
conn.close()
# Module scope: Run once per test module
@pytest.fixture(scope="module")
def api_client():
"""Create API client for entire module."""
client = APIClient()
client.authenticate()
yield client
client.logout()
# Session scope: Run once per test session
@pytest.fixture(scope="session")
def docker_container():
"""Start Docker container for entire test session."""
container = start_docker_postgres()
yield container
container.stop()Fixture Dependencies
import pytest
@pytest.fixture
def database():
"""Provide database connection."""
db = Database(":memory:")
db.create_tables()
yield db
db.close()
@pytest.fixture
def user_repository(database):
"""Provide user repository (depends on database fixture)."""
return UserRepository(database)
@pytest.fixture
def sample_users(user_repository):
"""Create sample users (depends on user_repository)."""
users = [
User(username="alice", email="alice@example.com"),
User(username="bob", email="bob@example.com"),
]
for user in users:
user_repository.save(user)
return users
def test_find_user(user_repository, sample_users):
"""Test finding user by username."""
# Both fixtures are injected automatically
user = user_repository.find_by_username("alice")
assert user is not None
assert user.email == "alice@example.com"Autouse Fixtures
import pytest
@pytest.fixture(autouse=True)
def reset_state():
"""Reset global state before each test (runs automatically)."""
clear_cache()
reset_counters()
yield
# Cleanup after test
@pytest.fixture(autouse=True, scope="module")
def setup_logging():
"""Configure logging for all tests in module."""
configure_test_logging()Factory Fixtures
import pytest
@pytest.fixture
def user_factory(database):
"""Fixture that returns a factory function for creating users."""
def _create_user(username: str, **kwargs):
user = User(username=username, **kwargs)
database.save(user)
return user
return _create_user
def test_multiple_users(user_factory):
"""Test with multiple users created by factory."""
alice = user_factory("alice", email="alice@example.com")
bob = user_factory("bob", email="bob@example.com", admin=True)
assert alice.username == "alice"
assert bob.is_admin is TrueParametrization
Basic Parametrization
import pytest
@pytest.mark.parametrize("input,expected", [
(2, 4),
(3, 9),
(4, 16),
(5, 25),
])
def test_square(input, expected):
"""Test square function with multiple inputs."""
assert square(input) == expected
@pytest.mark.parametrize("email", [
"user@example.com",
"test+tag@domain.org",
"name.surname@company.co.uk",
])
def test_valid_emails(email):
"""Test that valid emails are accepted."""
assert is_valid_email(email) is True
@pytest.mark.parametrize("invalid_email", [
"not-an-email",
"@example.com",
"user@",
"user name@example.com",
])
def test_invalid_emails(invalid_email):
"""Test that invalid emails are rejected."""
assert is_valid_email(invalid_email) is FalseMultiple Parameters
import pytest
@pytest.mark.parametrize("username,email,expected_valid", [
("alice", "alice@example.com", True),
("bob", "bob@example.com", True),
("", "test@example.com", False), # Empty username
("alice", "not-an-email", False), # Invalid email
("a" * 100, "test@example.com", False), # Username too long
])
def test_user_validation(username, email, expected_valid):
"""Test user validation with various inputs."""
user = User(username=username, email=email)
assert user.is_valid() == expected_validParametrize with IDs
import pytest
@pytest.mark.parametrize("input,expected", [
pytest.param(2, 4, id="two"),
pytest.param(3, 9, id="three"),
pytest.param(10, 100, id="ten"),
])
def test_square_with_ids(input, expected):
"""Test square with readable test IDs."""
assert square(input) == expected
# Alternative: ids as list
@pytest.mark.parametrize("value,result", [
(0, "zero"),
(1, "one"),
(5, "many"),
], ids=["zero", "one", "many"])
def test_number_name(value, result):
assert get_name(value) == resultCombining Parametrize
import pytest
@pytest.mark.parametrize("x", [1, 2])
@pytest.mark.parametrize("y", [3, 4])
def test_add(x, y):
"""Test all combinations: (1,3), (1,4), (2,3), (2,4)."""
result = x + y
assert result > 0Parametrizing Fixtures
import pytest
@pytest.fixture(params=["sqlite", "postgres", "mysql"])
def database(request):
"""Parametrized fixture - runs tests with each database."""
db_type = request.param
db = Database.create(db_type)
db.connect()
yield db
db.close()
def test_user_operations(database):
"""This test runs 3 times (once per database type)."""
user = User(username="test")
database.save(user)
retrieved = database.get_user(user.id)
assert retrieved.username == "test"Test Organization with conftest.py
Project Structure
myproject/
├── src/
│ └── myapp/
│ ├── __init__.py
│ ├── models.py
│ └── services.py
└── tests/
├── conftest.py # Shared fixtures for all tests
├── test_models.py
├── test_services.py
└── integration/
├── conftest.py # Fixtures specific to integration tests
└── test_api.pyRoot conftest.py
# tests/conftest.py
"""Shared fixtures for all tests."""
import pytest
from myapp.database import Database
from myapp.models import User
@pytest.fixture(scope="session")
def database_engine():
"""Create database engine for entire test session."""
engine = Database.create_engine("sqlite:///:memory:")
Database.create_all_tables(engine)
yield engine
engine.dispose()
@pytest.fixture
def database(database_engine):
"""Provide clean database for each test."""
connection = database_engine.connect()
transaction = connection.begin()
session = Database.create_session(bind=connection)
yield session
session.close()
transaction.rollback()
connection.close()
@pytest.fixture
def user_factory(database):
"""Factory for creating test users."""
def _create_user(**kwargs):
defaults = {
"username": "testuser",
"email": "test@example.com",
"active": True,
}
user = User(**{**defaults, **kwargs})
database.add(user)
database.commit()
return user
return _create_userSubdirectory conftest.py
# tests/integration/conftest.py
"""Fixtures specific to integration tests."""
import pytest
from myapp.api import create_app
@pytest.fixture(scope="module")
def app():
"""Create Flask/FastAPI app for integration testing."""
app = create_app(testing=True)
yield app
@pytest.fixture
def client(app):
"""Provide test client for API testing."""
return app.test_client()
@pytest.fixture
def authenticated_client(client, user_factory):
"""Provide authenticated test client."""
user = user_factory(username="testuser")
token = generate_token(user)
client.headers["Authorization"] = f"Bearer {token}"
return clientMocking and Patching
Using unittest.mock
import pytest
from unittest.mock import Mock, MagicMock, patch, call
def test_mock_basic():
"""Basic mock usage."""
mock = Mock()
mock.method.return_value = 42
result = mock.method()
assert result == 42
mock.method.assert_called_once()
def test_mock_with_side_effect():
"""Mock with side effects."""
mock = Mock()
mock.method.side_effect = [1, 2, 3]
assert mock.method() == 1
assert mock.method() == 2
assert mock.method() == 3
def test_mock_exception():
"""Mock that raises exception."""
mock = Mock()
mock.method.side_effect = ValueError("Invalid input")
with pytest.raises(ValueError):
mock.method()Patching
import pytest
from unittest.mock import patch
@patch("myapp.services.EmailService")
def test_order_processor_with_patch(mock_email_service):
"""Test using @patch decorator."""
mock_instance = mock_email_service.return_value
mock_instance.send.return_value = True
processor = OrderProcessor()
processor.process(order)
mock_instance.send.assert_called_once()
def test_with_patch_context():
"""Test using patch as context manager."""
with patch("myapp.services.requests.get") as mock_get:
mock_get.return_value.json.return_value = {"data": "value"}
result = fetch_api_data()
assert result["data"] == "value"
mock_get.assert_called_once()
@patch("myapp.services.datetime")
def test_with_mocked_datetime(mock_datetime):
"""Mock datetime.now() for deterministic tests."""
fixed_time = datetime(2024, 1, 1, 12, 0, 0)
mock_datetime.now.return_value = fixed_time
result = create_timestamp()
assert result == fixed_timepytest-mock Plugin
import pytest
def test_with_mocker(mocker):
"""Test using pytest-mock plugin (cleaner than unittest.mock)."""
mock_service = mocker.patch("myapp.services.EmailService")
mock_service.return_value.send.return_value = True
processor = OrderProcessor()
processor.process(order)
mock_service.return_value.send.assert_called_once()
def test_spy(mocker):
"""Spy on real method calls."""
spy = mocker.spy(UserRepository, "find_by_id")
service = UserService()
user = service.get_user(123)
spy.assert_called_once_with(123)Markers
Built-in Markers
import pytest
@pytest.mark.skip(reason="Not implemented yet")
def test_future_feature():
"""Skip this test."""
pass
@pytest.mark.skipif(sys.platform == "win32", reason="Unix only")
def test_unix_specific():
"""Skip on Windows."""
pass
@pytest.mark.xfail(reason="Known bug #123")
def test_with_known_bug():
"""Expected to fail until bug is fixed."""
assert buggy_function() == expected
@pytest.mark.xfail(strict=True)
def test_strict_xfail():
"""Must fail, otherwise test fails."""
passCustom Markers
# pytest.ini or pyproject.toml
# [tool.pytest.ini_options]
# markers =
# slow: marks tests as slow
# integration: marks tests as integration tests
# unit: marks tests as unit tests
import pytest
@pytest.mark.slow
def test_large_dataset():
"""Slow test that processes large dataset."""
process_million_records()
@pytest.mark.integration
def test_api_endpoint():
"""Integration test for API."""
response = client.get("/users")
assert response.status_code == 200
@pytest.mark.unit
@pytest.mark.parametrize("input,expected", [(1, 2), (2, 4)])
def test_double(input, expected):
"""Unit test with multiple markers."""
assert double(input) == expected
# Run only marked tests
# pytest -m slow
# pytest -m "not slow"
# pytest -m "integration and not slow"Modular Test Patterns
Test Classes for Grouping
import pytest
class TestUserCreation:
"""Group tests related to user creation."""
def test_valid_user(self, database):
"""Test creating valid user."""
user = User(username="alice", email="alice@example.com")
database.save(user)
assert user.id is not None
def test_duplicate_username(self, database, user_factory):
"""Test that duplicate username raises error."""
user_factory(username="alice")
with pytest.raises(ValueError):
user_factory(username="alice")
def test_invalid_email(self):
"""Test that invalid email raises error."""
with pytest.raises(ValueError):
User(username="bob", email="not-an-email")
class TestUserAuthentication:
"""Group tests related to authentication."""
def test_valid_credentials(self, user_factory):
"""Test authentication with valid credentials."""
user = user_factory(username="alice")
user.set_password("secret123")
assert user.check_password("secret123") is True
def test_invalid_password(self, user_factory):
"""Test authentication with invalid password."""
user = user_factory(username="alice")
user.set_password("secret123")
assert user.check_password("wrong") is FalseShared Setup with Class Fixtures
import pytest
class TestDatabaseOperations:
"""Tests that share setup via class-scoped fixture."""
@pytest.fixture(scope="class")
def populated_database(self, database):
"""Populate database once for all tests in class."""
users = [
User(username=f"user{i}", email=f"user{i}@example.com")
for i in range(100)
]
for user in users:
database.save(user)
return database
def test_count_users(self, populated_database):
"""Test counting users."""
count = populated_database.count_users()
assert count == 100
def test_find_user(self, populated_database):
"""Test finding specific user."""
user = populated_database.find_by_username("user42")
assert user.email == "user42@example.com"Helper Functions
# tests/helpers.py
"""Test helper functions."""
from typing import Any
from myapp.models import User
def assert_user_equal(actual: User, expected: User) -> None:
"""Assert that two users are equal."""
assert actual.username == expected.username
assert actual.email == expected.email
assert actual.is_active == expected.is_active
def create_test_user(**kwargs: Any) -> User:
"""Create a test user with default values."""
defaults = {
"username": "testuser",
"email": "test@example.com",
"active": True,
}
return User(**{**defaults, **kwargs})
# Use in tests
from tests.helpers import assert_user_equal, create_test_user
def test_user_copy(database):
"""Test user copying."""
original = create_test_user(username="alice")
copy = original.copy()
assert_user_equal(copy, original)
assert copy is not originalBest Practices
Test Isolation
# GOOD: Tests are independent
def test_create_user(database):
"""Each test gets fresh database."""
user = User(username="alice")
database.save(user)
assert database.count() == 1
def test_delete_user(database, user_factory):
"""Independent - doesn't rely on previous test."""
user = user_factory(username="bob")
database.delete(user)
assert database.count() == 0
# BAD: Tests depend on each other
class TestUserFlow:
user_id = None
def test_1_create(self, database):
user = User(username="alice")
database.save(user)
TestUserFlow.user_id = user.id # Shared state!
def test_2_update(self, database):
user = database.get(TestUserFlow.user_id) # Depends on test_1!
user.email = "new@example.com"Arrange-Act-Assert Pattern
def test_user_creation():
"""Test following AAA pattern."""
# Arrange: Set up test data and dependencies
username = "alice"
email = "alice@example.com"
# Act: Execute the code under test
user = User(username=username, email=email)
# Assert: Verify the results
assert user.username == "alice"
assert user.email == "alice@example.com"
assert user.is_active is TrueTest Naming
# GOOD: Descriptive test names
def test_user_creation_with_valid_data_succeeds():
pass
def test_user_creation_with_invalid_email_raises_value_error():
pass
def test_order_total_includes_tax_and_shipping():
pass
# Pattern: test_[unit]_[scenario]_[expected_behavior]
def test_calculate_discount_when_vip_user_returns_20_percent():
passFixture Reusability
# conftest.py - Reusable fixtures
@pytest.fixture
def api_client():
"""Reusable API client fixture."""
return APIClient(base_url="http://localhost:8000")
@pytest.fixture
def admin_token(user_factory):
"""Reusable admin authentication fixture."""
admin = user_factory(username="admin", is_admin=True)
return generate_token(admin)
# Multiple tests can use these fixtures
def test_get_users(api_client, admin_token):
response = api_client.get("/users", headers={"Authorization": admin_token})
assert response.status_code == 200
def test_create_user(api_client, admin_token):
response = api_client.post(
"/users",
json={"username": "newuser"},
headers={"Authorization": admin_token}
)
assert response.status_code == 201Testing Anti-Patterns to Avoid
Don't Test Implementation Details
# BAD: Testing private methods
def test_internal_validation():
"""Don't test private methods directly."""
user = User(username="alice")
assert user._validate_username() is True # Testing internals
# GOOD: Test public interface
def test_user_creation_validates_username():
"""Test behavior through public interface."""
with pytest.raises(ValueError):
User(username="") # Validation happens implicitlyDon't Use Too Many Mocks
# BAD: Too many mocks - test is brittle and tests nothing
def test_process_order_too_many_mocks(mocker):
mock_db = mocker.Mock()
mock_email = mocker.Mock()
mock_payment = mocker.Mock()
mock_inventory = mocker.Mock()
mock_shipping = mocker.Mock()
# ... testing implementation, not behavior
# GOOD: Mock only external dependencies
def test_process_order_integration(database, mocker):
mock_email = mocker.patch("myapp.services.EmailService")
processor = OrderProcessor(database=database)
processor.process(order)
# Real database interaction, mocked email
assert database.get_order(order.id).status == "processed"
mock_email.send_confirmation.assert_called_once()Don't Test Third-Party Code
# BAD: Testing Django/Flask/FastAPI internals
def test_django_orm():
"""Don't test that Django ORM works."""
user = User.objects.create(username="alice")
retrieved = User.objects.get(id=user.id)
assert retrieved.username == "alice" # Testing Django, not your code
# GOOD: Test your business logic
def test_user_service_creates_with_default_role():
"""Test your logic using Django."""
service = UserService()
user = service.create_user(username="alice")
assert user.role == "member" # Testing YOUR default logicTest Checklist
Before submitting tests:
Structure & Organization
- Tests mirror source code structure
- Related tests grouped in classes
- Fixtures in conftest.py for reusability
- Test names clearly describe scenario and expected behavior
Fixtures
- Appropriate fixture scope (function/class/module/session)
- Fixtures are isolated and don't share state
- Use factory fixtures for creating multiple instances
- Autouse fixtures only when necessary
Parametrization
- Data-driven tests use
@pytest.mark.parametrize - Parametrize includes readable IDs
- Edge cases covered in parameters
Assertions
- Each test has clear assertions
- Assertions include helpful messages where needed
- Exceptions tested with
pytest.raises - Floating point comparisons use
pytest.approx
Isolation & Independence
- Tests don't depend on execution order
- Each test can run independently
- No shared state between tests
- Database/files cleaned up after each test
Mocking
- Only external dependencies are mocked
- Internal logic uses real implementations
- Mocks verify correct interactions
- Not over-mocking
Coverage
- Happy path tested
- Edge cases tested
- Error conditions tested
- Test behavior, not implementation
References
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

