Python Testing Patterns
jh941213/my-cc-harness
Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development.
Python testing best practices using pytest including fixtures, parametrization, mocking, coverage analysis, async testing, and test organization.
$ npx skills add affaan-m/ECC --skill python-testing -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install affaan-m/ECC python-testing --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.kiro/skills/python-testing .claude/skills/python-testing && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "python-testing" agent skill from https://github.com/affaan-m/ECC/tree/main/.kiro/skills/python-testing into .claude/skills/python-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "python-testing", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/affaan-m/ECC/tree/main/.kiro/skills/python-testingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add affaan-m/ECC --skill python-testing -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install affaan-m/ECC python-testing --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.kiro/skills/python-testing .agents/skills/python-testing && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "python-testing" agent skill from https://github.com/affaan-m/ECC/tree/main/.kiro/skills/python-testing into .agents/skills/python-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "python-testing", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add affaan-m/ECC --skill python-testing -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install affaan-m/ECC python-testing --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.kiro/skills/python-testing .cursor/skills/python-testing && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "python-testing" agent skill from https://github.com/affaan-m/ECC/tree/main/.kiro/skills/python-testing into .cursor/skills/python-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "python-testing", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/affaan-m/ECC.git --path .kiro/skills/python-testing--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add affaan-m/ECC --skill python-testing -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install affaan-m/ECC python-testing --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.kiro/skills/python-testing .gemini/skills/python-testing && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "python-testing" agent skill from https://github.com/affaan-m/ECC/tree/main/.kiro/skills/python-testing into .gemini/skills/python-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "python-testing", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install affaan-m/ECC python-testingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add affaan-m/ECC --skill python-testing -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .github/skills && cp -r skills-src/.kiro/skills/python-testing .github/skills/python-testing && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "python-testing" agent skill from https://github.com/affaan-m/ECC/tree/main/.kiro/skills/python-testing into .github/skills/python-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "python-testing", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add affaan-m/ECC --skill python-testing -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install affaan-m/ECC python-testing --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.kiro/skills/python-testing .opencode/skills/python-testing && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "python-testing" agent skill from https://github.com/affaan-m/ECC/tree/main/.kiro/skills/python-testing into .opencode/skills/python-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "python-testing", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
python-testingPython testing best practices using pytest including fixtures, parametrization, mocking, coverage analysis, async testing, and test organization.
Python Testing is an agent skill from affaan-m/ECC. Python testing best practices using pytest including fixtures, parametrization, mocking, coverage analysis, async testing, and test organization. Use when writing or improving Python tests.
Its SKILL.md is about 2.7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering Unit testing and Test strategy. It works with Python and pytest. The repository describes itself as: The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond. The licence is MIT.
8 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit ef648e0. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
pytestFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Python Testing loads about 2.7k tokens when it runs. Until then it costs about 51 tokens; SKILL.md has 234 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from affaan-m/ECC at commit ef648e0, republished under its MIT licence (© affaan-m). 234 words, ~2,685 tokens.
.claude/skills/python-testing/SKILL.md (or your agent's skills folder).This skill provides comprehensive Python testing patterns using pytest as the primary testing framework.
Use pytest as the testing framework for its powerful features and clean syntax.
def test_user_creation():
"""Test that a user can be created with valid data"""
user = User(name="Alice", email="alice@example.com")
assert user.name == "Alice"
assert user.email == "alice@example.com"
assert user.is_active is Truepytest automatically discovers tests following these conventions:
test_*.py or *_test.pytest_*Test* (without __init__)test_*Fixtures provide reusable test setup and teardown:
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
@pytest.fixture
def db_session():
"""Provide a database session for tests"""
engine = create_engine("sqlite:///:memory:")
Session = sessionmaker(bind=engine)
session = Session()
# Setup
Base.metadata.create_all(engine)
yield session
# Teardown
session.close()
def test_user_repository(db_session):
"""Test using the db_session fixture"""
repo = UserRepository(db_session)
user = repo.create(name="Alice", email="alice@example.com")
assert user.id is not None@pytest.fixture(scope="function") # Default: per test
def user():
return User(name="Alice")
@pytest.fixture(scope="class") # Per test class
def database():
db = Database()
db.connect()
yield db
db.disconnect()
@pytest.fixture(scope="module") # Per module
def app():
return create_app()
@pytest.fixture(scope="session") # Once per test session
def config():
return load_config()@pytest.fixture
def database():
db = Database()
db.connect()
yield db
db.disconnect()
@pytest.fixture
def user_repository(database):
"""Fixture that depends on database fixture"""
return UserRepository(database)
def test_create_user(user_repository):
user = user_repository.create(name="Alice")
assert user.id is not NoneTest multiple inputs with @pytest.mark.parametrize:
import pytest
@pytest.mark.parametrize("email,expected", [
("user@example.com", True),
("invalid-email", False),
("", False),
("user@", False),
("@example.com", False),
])
def test_email_validation(email, expected):
result = validate_email(email)
assert result == expected@pytest.mark.parametrize("name,age,valid", [
("Alice", 25, True),
("Bob", 17, False),
("", 25, False),
("Charlie", -1, False),
])
def test_user_validation(name, age, valid):
result = validate_user(name, age)
assert result == valid@pytest.mark.parametrize("input,expected", [
("hello", "HELLO"),
("world", "WORLD"),
], ids=["lowercase", "another_lowercase"])
def test_uppercase(input, expected):
assert input.upper() == expectedUse markers for test categorization and selective execution:
import pytest
@pytest.mark.unit
def test_calculate_total():
"""Fast unit test"""
assert calculate_total([1, 2, 3]) == 6
@pytest.mark.integration
def test_database_connection():
"""Slower integration test"""
db = Database()
assert db.connect() is True
@pytest.mark.slow
def test_large_dataset():
"""Very slow test"""
process_million_records()
@pytest.mark.skip(reason="Not implemented yet")
def test_future_feature():
pass
@pytest.mark.skipif(sys.version_info < (3, 10), reason="Requires Python 3.10+")
def test_new_syntax():
passRun specific markers:
pytest -m unit # Run only unit tests
pytest -m "not slow" # Skip slow tests
pytest -m "unit or integration" # Run unit OR integrationfrom unittest.mock import Mock, patch, MagicMock
def test_user_service_with_mock():
"""Test with mock repository"""
mock_repo = Mock()
mock_repo.find_by_id.return_value = User(id="1", name="Alice")
service = UserService(mock_repo)
user = service.get_user("1")
assert user.name == "Alice"
mock_repo.find_by_id.assert_called_once_with("1")
@patch('myapp.services.EmailService')
def test_send_notification(mock_email_service):
"""Test with patched dependency"""
service = NotificationService()
service.send("user@example.com", "Hello")
mock_email_service.send.assert_called_once()def test_with_mocker(mocker):
"""Using pytest-mock plugin"""
mock_repo = mocker.Mock()
mock_repo.find_by_id.return_value = User(id="1", name="Alice")
service = UserService(mock_repo)
user = service.get_user("1")
assert user.name == "Alice"pytest --cov=src --cov-report=term-missingpytest --cov=src --cov-report=html
open htmlcov/index.html# pytest.ini or pyproject.toml
[tool.pytest.ini_options]
addopts = """
--cov=src
--cov-report=term-missing
--cov-report=html
--cov-fail-under=80
"""pytest --cov=src --cov-branchimport pytest
@pytest.mark.asyncio
async def test_async_fetch_user():
"""Test async function"""
user = await fetch_user("1")
assert user.name == "Alice"
@pytest.fixture
async def async_client():
"""Async fixture"""
client = AsyncClient()
await client.connect()
yield client
await client.disconnect()
@pytest.mark.asyncio
async def test_with_async_fixture(async_client):
result = await async_client.get("/users/1")
assert result.status == 200tests/
├── unit/
│ ├── test_models.py
│ ├── test_services.py
│ └── test_utils.py
├── integration/
│ ├── test_database.py
│ └── test_api.py
├── conftest.py # Shared fixtures
└── pytest.ini # Configuration# tests/conftest.py
import pytest
@pytest.fixture(scope="session")
def app():
"""Application fixture available to all tests"""
return create_app()
@pytest.fixture
def client(app):
"""Test client fixture"""
return app.test_client()
def pytest_configure(config):
"""Register custom markers"""
config.addinivalue_line("markers", "unit: Unit tests")
config.addinivalue_line("markers", "integration: Integration tests")
config.addinivalue_line("markers", "slow: Slow tests")def test_assertions():
assert value == expected
assert value != other
assert value > 0
assert value in collection
assert isinstance(value, str)def test_with_context():
"""pytest provides detailed assertion introspection"""
result = calculate_total([1, 2, 3])
expected = 6
# pytest shows: assert 5 == 6
assert result == expecteddef test_with_message():
result = process_data(input_data)
assert result.is_valid, f"Expected valid result, got errors: {result.errors}"import pytest
def test_float_comparison():
result = 0.1 + 0.2
assert result == pytest.approx(0.3)
# With tolerance
assert result == pytest.approx(0.3, abs=1e-9)import pytest
def test_raises_exception():
"""Test that function raises expected exception"""
with pytest.raises(ValueError):
validate_age(-1)
def test_exception_message():
"""Test exception message"""
with pytest.raises(ValueError, match="Age must be positive"):
validate_age(-1)
def test_exception_details():
"""Capture and inspect exception"""
with pytest.raises(ValidationError) as exc_info:
validate_user(name="", age=-1)
assert "name" in exc_info.value.errors
assert "age" in exc_info.value.errors# tests/helpers.py
def assert_user_equal(actual, expected):
"""Custom assertion helper"""
assert actual.id == expected.id
assert actual.name == expected.name
assert actual.email == expected.email
def create_test_user(**kwargs):
"""Test data factory"""
defaults = {
"name": "Test User",
"email": "test@example.com",
"age": 25,
}
defaults.update(kwargs)
return User(**defaults)Using hypothesis for property-based testing:
from hypothesis import given, strategies as st
@given(st.integers(), st.integers())
def test_addition_commutative(a, b):
"""Test that addition is commutative"""
assert a + b == b + a
@given(st.lists(st.integers()))
def test_sort_idempotent(lst):
"""Test that sorting twice gives same result"""
sorted_once = sorted(lst)
sorted_twice = sorted(sorted_once)
assert sorted_once == sorted_twice# Run all tests
pytest
# Run specific file
pytest tests/test_user.py
# Run specific test
pytest tests/test_user.py::test_create_user
# Run with verbose output
pytest -v
# Run with output capture disabled
pytest -s
# Run in parallel (requires pytest-xdist)
pytest -n auto
# Run only failed tests from last run
pytest --lf
# Run failed tests first
pytest --ff© affaan-m, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .kiro/skills/python-testing of affaan-m/ECC.
Open the folder on GitHubat commit ef648e0
Python Testing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Python Testing this skillaffaan-m/ECC | 274k | — | ~2.7k | Automated safety check: Pass | MIT | |
| Python Testing Patternsjh941213/my-cc-harness | 126 | 16 repos | ~5.4k | Automated safety check: Pass | None | |
| Python Testing Strategiesc0x12c/ai-toolkit | 106 | — | ~747 | Automated safety check: Pass | None | |
| PytestGentleman-Programming/Gentleman-Skills | 657 | — | ~1.1k | Automated safety check: Pass | Apache-2.0 | |
| Testing Patternssoftspark/ai-toolkit | 179 | — | ~1.6k | Automated safety check: Pass | Apache-2.0 | |
| Testing Test Strategydzhalaevd/Donatello | 135 | — | ~1.7k | Automated safety check: Pass | Apache-2.0 |
jh941213/my-cc-harness
Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development.
c0x12c/ai-toolkit
Testing patterns for FastAPI with pytest-asyncio, httpx AsyncClient, fixtures, and test data factories.
Gentleman-Programming/Gentleman-Skills
Pytest testing patterns for Python. An agent skill from Gentleman-Programming/Gentleman-Skills.
softspark/ai-toolkit
Testing strategy: pyramid, AAA, mocks/fakes/stubs, flaky tests, coverage.
dzhalaevd/Donatello
Use as the lead skill when choosing what backend tests to write, reviewing test plans, or balancing unit, integration, API, concurrency, and E2E coverage
athola/claude-night-market
Python testing patterns with pytest, fixtures, TDD, mocking, async and integration tests.
affaan-m/ECC
Audits your installed Claude skills and commands for quality, with a quick mode for recently changed skills and a full mode that evaluates all of them through subagents.
affaan-m/ECC
Ingest, index, search, edit, and monitor video and audio with the VideoDB Python SDK — upload from files, URLs, or RTSP feeds, build spoken and scene indexes with timestamped search and playable…
affaan-m/ECC
Scans installed skills for principles that recur across them and proposes rule-file changes: append, revise, add a section, create a file or leave as covered.
affaan-m/ECC
Builds DRAFT counterparty agreements from one markdown template and a small JSON spec per party, with clauses picked by the party's role.
affaan-m/ECC
Measures whether agents actually follow a skill, rule or agent definition by generating scenarios at three strictness levels and scoring tool-call traces.
affaan-m/ECC
Instinct-based learning system that observes sessions via hooks, creates atomic instincts with confidence scoring, and evolves them into skills/commands/agents.
Categories
Python testing best practices using pytest including fixtures, parametrization, mocking, coverage analysis, async testing, and test organization. Python Testing is an agent skill from affaan-m/ECC. Python testing best practices using pytest including fixtures, parametrization, mocking, coverage analysis, async testing, and test organization.
Python Testing fits situations like: improving Python tests; tasks that involve Unit testing; tasks that involve Test strategy.
Run `npx skills add affaan-m/ECC --skill python-testing -a claude-code`. Or copy the skill folder (.kiro/skills/python-testing in affaan-m/ECC) into .claude/skills/python-testing in your project. Claude Code loads it when a task matches its description.
Run `npx skills add affaan-m/ECC --skill python-testing -a codex`. Or copy the skill folder (.kiro/skills/python-testing in affaan-m/ECC) into .agents/skills/python-testing in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add affaan-m/ECC --skill python-testing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/python-testing, .gemini/skills/python-testing, .github/skills/python-testing and .opencode/skills/python-testing in your project.
Going by SKILL.md and its folder, Python Testing needs the command-line tools its instructions call (pytest). Our summary lists: Python 3.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Python Testing is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.7k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Python Testing: Python Testing Patterns (jh941213/my-cc-harness, 126 stars), Python Testing Strategies (c0x12c/ai-toolkit, 106 stars), Pytest (Gentleman-Programming/Gentleman-Skills, 657 stars) and Testing Patterns (softspark/ai-toolkit, 179 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
affaan-m (a GitHub user) maintains it in affaan-m/ECC, which has 274,360 GitHub stars. The repository holds 657 skills in this directory. The repository was last updated on October 5, 2026.
Source: affaan-m/ECC on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.