skills/bossjones/pytest/SKILL.md
Python testing framework for writing simple, scalable, and powerful tests
npx skillsauth add aiskillstore/marketplace pytestInstall 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.
Pytest is a mature Python testing framework that makes it easy to write small tests while scaling to support complex functional testing.
# test_example.py
def test_addition():
assert 2 + 2 == 4
def test_string_operations():
assert "hello".upper() == "HELLO"
assert "world" in "hello world"
# Run all tests
uv run pytest
# Run with verbose output
uv run pytest -v
# Run specific test file
uv run pytest test_example.py
# Run specific test function
uv run pytest test_example.py::test_addition
Basic fixture definition:
import pytest
@pytest.fixture
def sample_data():
return {"name": "Alice", "age": 30}
def test_user_data(sample_data):
assert sample_data["name"] == "Alice"
assert sample_data["age"] == 30
Fixture with setup and teardown:
@pytest.fixture
def database_connection():
# Setup
conn = create_database_connection()
yield conn
# Teardown
conn.close()
def test_database_query(database_connection):
result = database_connection.query("SELECT * FROM users")
assert len(result) > 0
Fixture scopes:
@pytest.fixture(scope="function") # Default - created per test
def temp_file():
pass
@pytest.fixture(scope="module") # Created once per module
def module_resource():
pass
@pytest.fixture(scope="session") # Created once per test session
def session_resource():
pass
Basic parametrization:
@pytest.mark.parametrize("input,expected", [
("3+5", 8),
("2+4", 6),
("6*9", 54),
])
def test_eval(input, expected):
assert eval(input) == expected
Parametrized fixtures:
@pytest.fixture(params=["mysql", "postgresql", "sqlite"])
def database(request):
if request.param == "mysql":
return MySQLConnection()
elif request.param == "postgresql":
return PostgreSQLConnection()
else:
return SQLiteConnection()
def test_database_operations(database):
# Test runs 3 times, once for each database type
result = database.execute("SELECT 1")
assert result == 1
Stacking parametrization for combinatorial testing:
@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_combinations(x, y):
# Runs 4 times: (0,2), (0,3), (1,2), (1,3)
assert x + y > 1
Basic async test:
import pytest
@pytest.mark.asyncio
async def test_async_function():
result = await async_operation()
assert result is not None
Async fixtures:
@pytest.fixture
async def async_client():
client = AsyncClient()
await client.connect()
yield client
await client.disconnect()
@pytest.mark.asyncio
async def test_async_api(async_client):
response = await async_client.get("/api/data")
assert response.status_code == 200
Using conftest.py for shared fixtures:
# conftest.py
@pytest.fixture
def authenticated_client():
client = create_test_client()
client.login("testuser", "password")
return client
@pytest.fixture(scope="session")
def test_database():
db = create_test_database()
yield db
db.cleanup()
Test classes:
class TestUserAPI:
def test_create_user(self, authenticated_client):
response = authenticated_client.post("/users", json={"name": "John"})
assert response.status_code == 201
def test_get_user(self, authenticated_client):
user_id = create_test_user()
response = authenticated_client.get(f"/users/{user_id}")
assert response.status_code == 200
Using monkeypatch fixture:
def test_environment_variable(monkeypatch):
monkeypatch.setenv("API_KEY", "test-key")
assert get_api_key() == "test-key"
def test_file_operations(monkeypatch, tmp_path):
test_file = tmp_path / "test.txt"
test_file.write_text("test content")
monkeypatch.setattr("module.FILE_PATH", str(test_file))
assert read_file_content() == "test content"
Custom markers:
# pytest.ini
[tool:pytest]
markers =
slow: marks tests as slow
integration: marks tests as integration tests
unit: marks tests as unit tests
# test_file.py
@pytest.mark.slow
def test_expensive_operation():
pass
@pytest.mark.integration
def test_database_integration():
pass
Running tests by marker:
# Run only unit tests
uv run pytest -m unit
# Skip slow tests
uv run pytest -m "not slow"
# Run integration or unit tests
uv run pytest -m "integration or unit"
import pytest
from fastapi.testclient import TestClient
from myapp import app
@pytest.fixture
def client():
return TestClient(app)
@pytest.fixture
def test_user():
return {"username": "testuser", "email": "[email protected]"}
def test_create_user(client, test_user):
response = client.post("/users/", json=test_user)
assert response.status_code == 201
assert response.json()["username"] == test_user["username"]
def test_get_user(client, test_user):
# Create user first
create_response = client.post("/users/", json=test_user)
user_id = create_response.json()["id"]
# Get user
response = client.get(f"/users/{user_id}")
assert response.status_code == 200
assert response.json()["email"] == test_user["email"]
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
@pytest.fixture(scope="function")
def test_db():
engine = create_engine("sqlite:///:memory:")
Session = sessionmaker(bind=engine)
Base.metadata.create_all(engine)
session = Session()
yield session
session.close()
def test_user_creation(test_db):
user = User(name="John", email="[email protected]")
test_db.add(user)
test_db.commit()
retrieved_user = test_db.query(User).filter_by(name="John").first()
assert retrieved_user.email == "[email protected]"
def test_invalid_input_raises_error():
with pytest.raises(ValueError, match="Invalid input"):
process_input("invalid")
def test_file_not_found():
with pytest.raises(FileNotFoundError):
read_nonexistent_file()
def test_custom_exception():
with pytest.raises(CustomAPIError) as exc_info:
call_api_endpoint()
assert exc_info.value.status_code == 404
assert "not found" in str(exc_info.value)
uv add --dev pytest)uv add --dev pytest-asyncio)uv add --dev httpx for async HTTP tests)development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.