python-testing/SKILL.md
Python testing strategies using pytest, TDD methodology, fixtures, mocking, parametrization, and coverage requirements.
npx skillsauth add lidge-jun/cli-jaw-skills python-testingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Comprehensive testing strategies for Python applications using pytest, TDD methodology, and best practices.
Full code examples: references/code-examples.md
Follow the TDD cycle:
# Step 1: Write failing test (Red)
def test_add_numbers():
result = add(2, 3)
assert result == 5
# Step 2: Write minimal implementation (Green)
def add(a, b):
return a + b
# Step 3: Refactor if needed
pytest --cov=mypackage --cov-report=term-missing --cov-report=html
import pytest
def test_addition():
assert 2 + 2 == 4
def test_string_uppercase():
assert "hello".upper() == "HELLO"
| Assertion | Usage |
|-----------|-------|
| assert result == expected | Equality |
| assert result / assert not result | Truthiness |
| assert result is None | Identity |
| assert item in collection | Membership |
| assert isinstance(result, str) | Type check |
| pytest.raises(ValueError) | Exception |
| pytest.raises(ValueError, match="msg") | Exception with message |
# Exception testing
with pytest.raises(ValueError, match="invalid input"):
raise ValueError("invalid input provided")
# Check exception attributes
with pytest.raises(ValueError) as exc_info:
raise ValueError("error message")
assert str(exc_info.value) == "error message"
Fixtures provide reusable test setup. See references/code-examples.md for full examples.
@pytest.fixtureyield to split setup and cleanupfunction (default), module, session@pytest.fixture(params=[...]) for multi-run fixturesautouse=True runs automatically for every testconftest.py@pytest.fixture
def database():
db = Database(":memory:")
db.create_tables()
yield db
db.close()
def test_query(database):
result = database.query("SELECT * FROM users")
assert len(result) > 0
Run the same test with different inputs:
@pytest.mark.parametrize("a,b,expected", [
(2, 3, 5),
(0, 0, 0),
(-1, 1, 0),
(100, 200, 300),
])
def test_add(a, b, expected):
assert add(a, b) == expected
Use ids= for readable test names:
@pytest.mark.parametrize("input,expected", [
("[email protected]", True),
("invalid", False),
], ids=["valid-email", "missing-at"])
def test_email_validation(input, expected):
assert is_valid_email(input) is expected
@pytest.mark.slow
def test_slow_operation():
time.sleep(5)
@pytest.mark.integration
def test_api_integration():
response = requests.get("https://api.example.com")
assert response.status_code == 200
pytest -m "not slow" # Skip slow tests
pytest -m integration # Only integration tests
pytest -m "unit and not slow" # Combine markers
[pytest]
markers =
slow: marks tests as slow
integration: marks tests as integration tests
unit: marks tests as unit tests
Mock external dependencies to keep tests fast and isolated. See references/code-examples.md for all patterns.
from unittest.mock import patch, Mock
@patch("mypackage.external_api_call")
def test_with_mock(api_call_mock):
api_call_mock.return_value = {"status": "success"}
result = my_function()
api_call_mock.assert_called_once()
assert result["status"] == "success"
Key mocking techniques:
return_value — set what the mock returnsside_effect = Exception(...) — make the mock raiseautospec=True — catch API misusemock_open — mock file operationsPropertyMock — mock properties@pytest.mark.asyncio
async def test_async_function():
result = await async_add(2, 3)
assert result == 5
Use assert_awaited_once() instead of assert_called_once() for async mocks.
tests/
├── conftest.py # Shared fixtures
├── unit/ # Unit tests
│ ├── test_models.py
│ └── test_services.py
├── integration/ # Integration tests
│ └── test_api.py
└── e2e/ # End-to-end tests
└── test_user_flow.py
Group related tests in classes:
class TestUserService:
@pytest.fixture(autouse=True)
def setup(self):
self.service = UserService()
def test_create_user(self):
user = self.service.create_user("Alice")
assert user.name == "Alice"
test_user_login_with_invalid_credentials_failspytest.raises instead)[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"--strict-markers",
"--cov=mypackage",
"--cov-report=term-missing",
]
markers = [
"slow: marks tests as slow",
"integration: marks tests as integration tests",
"unit: marks tests as unit tests",
]
pytest # Run all tests
pytest tests/test_utils.py # Run specific file
pytest tests/test_utils.py::test_fn # Run specific test
pytest -v # Verbose output
pytest --cov=mypackage # With coverage
pytest -m "not slow" # Skip slow tests
pytest -x # Stop on first failure
pytest --maxfail=3 # Stop after N failures
pytest --lf # Run last failed
pytest -k "test_user" # Run by pattern
pytest --pdb # Debugger on failure
| Pattern | Usage |
|---------|-------|
| pytest.raises() | Test expected exceptions |
| @pytest.fixture() | Create reusable test fixtures |
| @pytest.mark.parametrize() | Run tests with multiple inputs |
| @pytest.mark.slow | Mark slow tests |
| pytest -m "not slow" | Skip slow tests |
| @patch() | Mock functions and classes |
| tmp_path fixture | Automatic temp directory |
| pytest --cov | Generate coverage report |
| assert | Simple and readable assertions |
Tests are code too — keep them clean, readable, and maintainable.
development
Goal execution guidelines with PABCD integration, verification tiers, documentation workflow, and AI-driven planning
tools
A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
development
Use this skill any time a spreadsheet file is the primary input or output (.xlsx, .xlsm, .csv, .tsv). This includes: creating, reading, editing, analyzing, or formatting spreadsheets; cleaning messy tabular data; converting between formats; and data visualization with charts. Also use for pandas-based data analysis when the deliverable is a spreadsheet. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration.
tools
Use this skill when the user wants to build a financial model, 3-statement model, DCF valuation, cap table, scenario analysis, or financial projections in Excel. Trigger on: 'financial model', '3-statement model', 'DCF', 'cap table', 'pro forma', 'projections', 'sensitivity analysis', 'waterfall', 'debt schedule', 'break-even', 'discounted cash flow', 'capitalization table', 'fundraising model', 'WACC calculation', 'scenario analysis model'. Input is a text prompt with assumptions. Output is a single .xlsx file with formula-driven, interconnected statement sheets.