pytest by aiskillstore
Python testing framework for writing simple, scalable, and powerful tests
Testing
85 Stars
2 Forks
Updated Jan 19, 2026, 04:39 AM
Why Use This
This skill provides specialized capabilities for aiskillstore's codebase.
Use Cases
- Developing new features in the aiskillstore repository
- Refactoring existing code to follow aiskillstore standards
- Understanding and working with aiskillstore's codebase structure
Install Guide
2 steps- 1
Skip this step if Ananke is already installed.
- 2
Skill Snapshot
Auto scan of skill assets. Informational only.
Valid SKILL.md
Checks against SKILL.md specification
Source & Community
Skill Stats
SKILL.md 329 Lines
Total Files 1
Total Size 0 B
License NOASSERTION
---
name: pytest
description: Python testing framework for writing simple, scalable, and powerful tests
when_to_use: When you need to write, run, or organize Python tests with fixtures, parametrization, or async testing
---
# Pytest Testing Framework
Pytest is a mature Python testing framework that makes it easy to write small tests while scaling to support complex functional testing.
## Quick Start
### Basic Test Structure
```python
# test_example.py
def test_addition():
assert 2 + 2 == 4
def test_string_operations():
assert "hello".upper() == "HELLO"
assert "world" in "hello world"
```
### Running Tests
```bash
# 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
```
## Common Patterns
### Fixtures
**Basic fixture definition:**
```python
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:**
```python
@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:**
```python
@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
```
### Parametrization
**Basic parametrization:**
```python
@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:**
```python
@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:**
```python
@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
```
### Async Testing
**Basic async test:**
```python
import pytest
@pytest.mark.asyncio
async def test_async_function():
result = await async_operation()
assert result is not None
```
**Async fixtures:**
```python
@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
```
### Test Organization
**Using conftest.py for shared fixtures:**
```python
# 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:**
```python
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
```
### Mocking and Patching
**Using monkeypatch fixture:**
```python
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"
```
### Markers and Selection
**Custom markers:**
```python
# 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:**
```bash
# 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"
```
## Practical Code Snippets
### API Testing
```python
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"]
```
### Database Testing
```python
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]"
```
### Error Handling Testing
```python
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)
```
## Requirements
- Python 3.7+
- pytest (`uv add --dev pytest`)
- For async testing: pytest-asyncio (`uv add --dev pytest-asyncio`)
- For API testing: web framework test client (e.g., `uv add --dev httpx` for async HTTP tests)
Name Size