metacoding
Version:
Guided Development Workflow for GitHub Copilot - Transform your coding experience with AI-guided standards, structured workflows, and quality practices
1,075 lines (882 loc) • 33.6 kB
Markdown
---
description: 'Python-specific testing patterns and frameworks (pytest, Django, FastAPI)'
applyTo: 'test/**/*.py,tests/**/*.py,**/test_*.py'
language: 'python'
---
# Python Testing Standards
## Test Case Naming Conventions
### Test Case ID Format: `[AREA]-[TYPE]-[NUMBER]`
**Python/Django/FastAPI Area Prefixes:**
- `VIEW` - Django views/FastAPI endpoints tests
- `MODEL` - Django models/SQLAlchemy tests
- `FORM` - Django forms/Pydantic validators tests
- `API` - REST API endpoint tests
- `SRV` - Service layer tests
- `DB` - Database/ORM tests
- `AUTH` - Authentication/Authorization tests
- `UTIL` - Backend utility function tests
- `SERIALIZER` - DRF serializers/Pydantic schemas tests
- `MIDDLEWARE` - Django middleware tests
**Type Suffixes:**
- `UNIT` - Unit tests (isolated component testing)
- `INT` - Integration tests (component interaction testing)
- `E2E` - End-to-end tests (full API workflow testing)
**Examples:**
- `VIEW-UNIT-001` - First unit test for Django view
- `MODEL-UNIT-001` - First unit test for Django model
- `FORM-INT-001` - First integration test for Django form
- `API-E2E-001` - First end-to-end API test
## Testing Framework and Setup
### Primary Testing Framework: pytest
```python
# pytest.ini
[tool:pytest]
testpaths = tests
python_files = test_*.py *_test.py
python_classes = Test*
python_functions = test_*
addopts =
--strict-markers
--strict-config
--cov=src
--cov-report=term-missing
--cov-report=html
--cov-fail-under=80
markers =
unit: Unit tests
integration: Integration tests
slow: Slow running tests
api: API endpoint tests
```
```python
# conftest.py
import pytest
from unittest.mock import Mock
from src.database import Database
from src.services.user_service import UserService
def mock_database():
"""Mock database connection for testing."""
return Mock(spec=Database)
def user_service(mock_database):
"""User service with mocked dependencies."""
return UserService(database=mock_database)
def sample_user_data():
"""Sample user data for testing."""
return {
'name': 'John Doe',
'email': 'john@example.com',
'age': 30
}
def test_database():
"""Session-scoped test database."""
db = Database(DATABASE_TEST_URL)
db.create_tables()
yield db
db.drop_tables()
db.close()
```
### Test Case Naming Conventions
**Area Prefixes for Python/Django:**
- `VIEW` - View/Controller tests
- `MODEL` - Model/ORM tests
- `FORM` - Form validation tests
- `CMD` - Management command tests
- `API` - API endpoint tests
- `SRV` - Service layer tests
- `UTIL` - Utility function tests
- `DB` - Database operation tests
- `AUTH` - Authentication/Authorization tests
- `INT` - Integration tests
- `E2E` - End-to-end tests
**Examples:**
- `VIEW-UNIT-001` - First unit test for View layer
- `MODEL-UNIT-001` - First unit test for Model layer
- `API-INT-001` - First integration test for API
- `E2E-FLOW-001` - First end-to-end workflow test
## Unit Testing Patterns
### Service Layer Testing
```python
# tests/unit/test_user_service.py
import pytest
from unittest.mock import Mock, patch, call
from src.services.user_service import UserService, UserNotFoundError
from src.models.user import User
class TestUserService:
"""Test suite for UserService class."""
def mock_repository(self):
"""Mock user repository."""
return Mock()
def user_service(self, mock_repository):
"""UserService instance with mocked dependencies."""
return UserService(repository=mock_repository)
def test_get_user_by_id_success(self, user_service, mock_repository):
"""Test successful user retrieval by ID."""
# Arrange
user_id = "123"
expected_user = User(id=user_id, name="John Doe", email="john@example.com")
mock_repository.find_by_id.return_value = expected_user
# Act
result = user_service.get_user_by_id(user_id)
# Assert
assert result == expected_user
mock_repository.find_by_id.assert_called_once_with(user_id)
def test_get_user_by_id_not_found(self, user_service, mock_repository):
"""Test user retrieval when user doesn't exist."""
# Arrange
user_id = "999"
mock_repository.find_by_id.return_value = None
# Act & Assert
with pytest.raises(UserNotFoundError, match=f"User {user_id} not found"):
user_service.get_user_by_id(user_id)
mock_repository.find_by_id.assert_called_once_with(user_id)
def test_get_user_by_id_repository_calls(
self, user_service, mock_repository, user_id, expected_calls
):
"""Test repository is called correct number of times."""
# Arrange
mock_repository.find_by_id.return_value = Mock()
# Act
user_service.get_user_by_id(user_id)
# Assert
assert mock_repository.find_by_id.call_count == expected_calls
def test_create_user_success(self, user_service, mock_repository):
"""Test successful user creation."""
# Arrange
user_data = {
'name': 'Jane Doe',
'email': 'jane@example.com'
}
created_user = User(id="456", **user_data)
mock_repository.create.return_value = created_user
# Act
result = user_service.create_user(user_data)
# Assert
assert result == created_user
mock_repository.create.assert_called_once_with(user_data)
def test_create_user_validation_error(self, user_service):
"""Test user creation with invalid data."""
# Arrange
invalid_data = {'name': ''} # Missing email
# Act & Assert
with pytest.raises(ValueError, match="Invalid user data"):
user_service.create_user(invalid_data)
```
### Model Testing (Django)
```python
# tests/unit/test_user_model.py
import pytest
from django.test import TestCase
from django.core.exceptions import ValidationError
from django.db import IntegrityError
from src.models.user import User
class TestUserModel(TestCase):
"""Test suite for User model."""
def setUp(self):
"""Set up test data."""
self.valid_user_data = {
'name': 'John Doe',
'email': 'john@example.com',
'age': 30
}
def test_create_user_success(self):
"""Test successful user creation."""
# Act
user = User.objects.create(**self.valid_user_data)
# Assert
assert user.pk is not None
assert user.name == self.valid_user_data['name']
assert user.email == self.valid_user_data['email']
assert user.age == self.valid_user_data['age']
assert user.is_active is True # Default value
def test_user_str_representation(self):
"""Test string representation of user."""
# Arrange
user = User(**self.valid_user_data)
# Act
result = str(user)
# Assert
expected = f"{self.valid_user_data['name']} ({self.valid_user_data['email']})"
assert result == expected
def test_email_uniqueness_constraint(self):
"""Test email uniqueness is enforced."""
# Arrange
User.objects.create(**self.valid_user_data)
# Act & Assert
with pytest.raises(IntegrityError):
User.objects.create(**self.valid_user_data)
def test_email_validation(self):
"""Test email format validation."""
# Arrange
invalid_data = self.valid_user_data.copy()
invalid_data['email'] = 'invalid-email'
# Act & Assert
user = User(**invalid_data)
with pytest.raises(ValidationError):
user.full_clean()
def test_age_validation(self, age, is_valid):
"""Test age validation with various values."""
# Arrange
user_data = self.valid_user_data.copy()
user_data['age'] = age
user = User(**user_data)
# Act & Assert
if is_valid:
user.full_clean() # Should not raise
else:
with pytest.raises(ValidationError):
user.full_clean()
def test_get_full_name_method(self):
"""Test custom method for getting full name."""
# Arrange
user = User(name="John Doe", email="john@example.com")
# Act
result = user.get_full_name()
# Assert
assert result == "John Doe"
def test_is_adult_property(self):
"""Test custom property for checking if user is adult."""
# Arrange
adult_user = User(age=25, name="Adult", email="adult@example.com")
minor_user = User(age=16, name="Minor", email="minor@example.com")
# Act & Assert
assert adult_user.is_adult is True
assert minor_user.is_adult is False
```
### View Testing (Django)
```python
# tests/unit/test_user_views.py
import json
import pytest
from django.test import TestCase, Client
from django.contrib.auth.models import User as AuthUser
from django.urls import reverse
from src.models.user import User
class TestUserViews(TestCase):
"""Test suite for user-related views."""
def setUp(self):
"""Set up test data and client."""
self.client = Client()
self.auth_user = AuthUser.objects.create_user(
username='testuser',
password='testpass123'
)
self.user = User.objects.create(
name='John Doe',
email='john@example.com',
age=30
)
def test_user_list_view_success(self):
"""Test user list view returns users."""
# Act
response = self.client.get(reverse('user:list'))
# Assert
assert response.status_code == 200
assert 'users' in response.context
assert self.user in response.context['users']
def test_user_detail_view_success(self):
"""Test user detail view returns specific user."""
# Act
response = self.client.get(
reverse('user:detail', kwargs={'pk': self.user.pk})
)
# Assert
assert response.status_code == 200
assert response.context['user'] == self.user
def test_user_detail_view_not_found(self):
"""Test user detail view with non-existent user."""
# Act
response = self.client.get(
reverse('user:detail', kwargs={'pk': 999})
)
# Assert
assert response.status_code == 404
def test_user_create_view_get(self):
"""Test GET request to user create view."""
# Arrange
self.client.login(username='testuser', password='testpass123')
# Act
response = self.client.get(reverse('user:create'))
# Assert
assert response.status_code == 200
assert 'form' in response.context
def test_user_create_view_post_success(self):
"""Test successful POST to user create view."""
# Arrange
self.client.login(username='testuser', password='testpass123')
user_data = {
'name': 'Jane Doe',
'email': 'jane@example.com',
'age': 25
}
# Act
response = self.client.post(reverse('user:create'), data=user_data)
# Assert
assert response.status_code == 302 # Redirect after success
assert User.objects.filter(email='jane@example.com').exists()
def test_user_create_view_post_invalid_data(self):
"""Test POST to user create view with invalid data."""
# Arrange
self.client.login(username='testuser', password='testpass123')
invalid_data = {
'name': '', # Invalid: empty name
'email': 'invalid-email', # Invalid: bad email format
'age': -5 # Invalid: negative age
}
# Act
response = self.client.post(reverse('user:create'), data=invalid_data)
# Assert
assert response.status_code == 200 # Returns form with errors
assert 'form' in response.context
assert response.context['form'].errors
def test_user_create_view_requires_authentication(self):
"""Test user create view requires authentication."""
# Act
response = self.client.get(reverse('user:create'))
# Assert
assert response.status_code == 302 # Redirect to login
assert '/login/' in response.url
```
### API Testing (FastAPI)
```python
# tests/unit/test_user_api.py
import pytest
from fastapi.testclient import TestClient
from unittest.mock import Mock, patch
from src.main import app
from src.services.user_service import UserService
from src.models.user import User
client = TestClient(app)
class TestUserAPI:
"""Test suite for User API endpoints."""
def test_get_user_success(self, mock_get_service):
"""Test successful user retrieval via API."""
# Arrange
user_id = "123"
expected_user = User(id=user_id, name="John Doe", email="john@example.com")
mock_service = Mock(spec=UserService)
mock_service.get_user_by_id.return_value = expected_user
mock_get_service.return_value = mock_service
# Act
response = client.get(f"/users/{user_id}")
# Assert
assert response.status_code == 200
assert response.json()["id"] == user_id
assert response.json()["name"] == "John Doe"
mock_service.get_user_by_id.assert_called_once_with(user_id)
def test_get_user_not_found(self, mock_get_service):
"""Test user not found via API."""
# Arrange
user_id = "999"
mock_service = Mock(spec=UserService)
mock_service.get_user_by_id.side_effect = UserNotFoundError("User not found")
mock_get_service.return_value = mock_service
# Act
response = client.get(f"/users/{user_id}")
# Assert
assert response.status_code == 404
assert "not found" in response.json()["detail"].lower()
def test_create_user_success(self, mock_get_service):
"""Test successful user creation via API."""
# Arrange
user_data = {
"name": "Jane Doe",
"email": "jane@example.com",
"age": 25
}
created_user = User(id="456", **user_data)
mock_service = Mock(spec=UserService)
mock_service.create_user.return_value = created_user
mock_get_service.return_value = mock_service
# Act
response = client.post("/users/", json=user_data)
# Assert
assert response.status_code == 201
assert response.json()["id"] == "456"
assert response.json()["name"] == user_data["name"]
mock_service.create_user.assert_called_once_with(user_data)
def test_create_user_validation_error(self):
"""Test user creation with invalid data."""
# Arrange
invalid_data = {
"name": "", # Invalid: empty name
"email": "invalid-email", # Invalid: bad format
"age": -5 # Invalid: negative age
}
# Act
response = client.post("/users/", json=invalid_data)
# Assert
assert response.status_code == 422
assert "detail" in response.json()
def test_create_user_various_data(
self, mock_get_service, user_data, expected_status
):
"""Test user creation with various data combinations."""
# Arrange
if expected_status == 201:
created_user = User(id="123", **user_data)
mock_service = Mock(spec=UserService)
mock_service.create_user.return_value = created_user
mock_get_service.return_value = mock_service
# Act
response = client.post("/users/", json=user_data)
# Assert
assert response.status_code == expected_status
```
## Integration Testing
### Database Integration Testing
```python
# tests/integration/test_user_repository.py
import pytest
import asyncio
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from src.database.base import Base
from src.repositories.user_repository import UserRepository
from src.models.user import User
class TestUserRepositoryIntegration:
"""Integration tests for UserRepository with real database."""
def db_engine(self):
"""Create test database engine."""
engine = create_engine("sqlite:///:memory:", echo=False)
Base.metadata.create_all(engine)
yield engine
Base.metadata.drop_all(engine)
def db_session(self, db_engine):
"""Create database session for each test."""
Session = sessionmaker(bind=db_engine)
session = Session()
yield session
session.rollback()
session.close()
def user_repository(self, db_session):
"""Create UserRepository with real database session."""
return UserRepository(session=db_session)
def test_create_and_find_user(self, user_repository):
"""Test creating and finding a user in database."""
# Arrange
user_data = {
'name': 'John Doe',
'email': 'john@example.com',
'age': 30
}
# Act
created_user = user_repository.create(user_data)
found_user = user_repository.find_by_id(created_user.id)
# Assert
assert found_user is not None
assert found_user.id == created_user.id
assert found_user.name == user_data['name']
assert found_user.email == user_data['email']
def test_find_by_email(self, user_repository):
"""Test finding user by email."""
# Arrange
user_data = {
'name': 'Jane Doe',
'email': 'jane@example.com',
'age': 25
}
created_user = user_repository.create(user_data)
# Act
found_user = user_repository.find_by_email('jane@example.com')
# Assert
assert found_user is not None
assert found_user.id == created_user.id
assert found_user.email == 'jane@example.com'
def test_update_user(self, user_repository):
"""Test updating user information."""
# Arrange
user_data = {
'name': 'Original Name',
'email': 'original@example.com',
'age': 30
}
created_user = user_repository.create(user_data)
# Act
update_data = {'name': 'Updated Name', 'age': 31}
updated_user = user_repository.update(created_user.id, update_data)
# Assert
assert updated_user.name == 'Updated Name'
assert updated_user.age == 31
assert updated_user.email == 'original@example.com' # Unchanged
def test_delete_user(self, user_repository):
"""Test deleting a user."""
# Arrange
user_data = {
'name': 'To Be Deleted',
'email': 'delete@example.com',
'age': 25
}
created_user = user_repository.create(user_data)
# Act
result = user_repository.delete(created_user.id)
found_user = user_repository.find_by_id(created_user.id)
# Assert
assert result is True
assert found_user is None
def test_list_users_with_pagination(self, user_repository):
"""Test listing users with pagination."""
# Arrange
users_data = [
{'name': f'User {i}', 'email': f'user{i}@example.com', 'age': 20 + i}
for i in range(5)
]
created_users = [user_repository.create(data) for data in users_data]
# Act
page_1 = user_repository.list_users(page=1, per_page=2)
page_2 = user_repository.list_users(page=2, per_page=2)
# Assert
assert len(page_1) == 2
assert len(page_2) == 2
assert page_1[0].id != page_2[0].id # Different users
```
### API Integration Testing
```python
# tests/integration/test_api_integration.py
import pytest
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from src.main import app
from src.database.base import Base
from src.dependencies import get_database_session
class TestAPIIntegration:
"""Integration tests for API with real database."""
def test_engine(self):
"""Create test database engine."""
engine = create_engine("sqlite:///:memory:", echo=False)
Base.metadata.create_all(engine)
yield engine
Base.metadata.drop_all(engine)
def test_session(self, test_engine):
"""Create test database session."""
Session = sessionmaker(bind=test_engine)
session = Session()
yield session
session.close()
def client(self, test_session):
"""Create test client with test database."""
def override_get_db():
yield test_session
app.dependency_overrides[get_database_session] = override_get_db
client = TestClient(app)
yield client
app.dependency_overrides.clear()
def test_full_user_crud_workflow(self, client):
"""Test complete CRUD workflow for users."""
# Create user
user_data = {
"name": "Test User",
"email": "test@example.com",
"age": 30
}
create_response = client.post("/users/", json=user_data)
assert create_response.status_code == 201
created_user = create_response.json()
user_id = created_user["id"]
# Read user
get_response = client.get(f"/users/{user_id}")
assert get_response.status_code == 200
assert get_response.json()["name"] == user_data["name"]
# Update user
update_data = {"name": "Updated User", "age": 31}
update_response = client.patch(f"/users/{user_id}", json=update_data)
assert update_response.status_code == 200
assert update_response.json()["name"] == "Updated User"
# List users
list_response = client.get("/users/")
assert list_response.status_code == 200
users = list_response.json()
assert len(users) >= 1
assert any(user["id"] == user_id for user in users)
# Delete user
delete_response = client.delete(f"/users/{user_id}")
assert delete_response.status_code == 204
# Verify deletion
get_deleted_response = client.get(f"/users/{user_id}")
assert get_deleted_response.status_code == 404
def test_user_email_uniqueness_constraint(self, client):
"""Test email uniqueness is enforced at API level."""
# Arrange
user_data = {
"name": "First User",
"email": "duplicate@example.com",
"age": 25
}
# Act - Create first user
first_response = client.post("/users/", json=user_data)
assert first_response.status_code == 201
# Act - Try to create second user with same email
user_data["name"] = "Second User"
second_response = client.post("/users/", json=user_data)
# Assert
assert second_response.status_code == 400
assert "email" in second_response.json()["detail"].lower()
```
## Async Testing
### Async Function Testing
```python
# tests/unit/test_async_service.py
import pytest
import asyncio
from unittest.mock import AsyncMock, Mock
from src.services.async_user_service import AsyncUserService
class TestAsyncUserService:
"""Test suite for async user service."""
def mock_async_repository(self):
"""Mock async repository."""
mock = AsyncMock()
return mock
def async_user_service(self, mock_async_repository):
"""Async user service with mocked dependencies."""
return AsyncUserService(repository=mock_async_repository)
async def test_get_user_by_id_async(self, async_user_service, mock_async_repository):
"""Test async user retrieval."""
# Arrange
user_id = "123"
expected_user = {"id": user_id, "name": "John Doe"}
mock_async_repository.find_by_id.return_value = expected_user
# Act
result = await async_user_service.get_user_by_id(user_id)
# Assert
assert result == expected_user
mock_async_repository.find_by_id.assert_called_once_with(user_id)
async def test_create_multiple_users_concurrently(
self, async_user_service, mock_async_repository
):
"""Test creating multiple users concurrently."""
# Arrange
users_data = [
{"name": f"User {i}", "email": f"user{i}@example.com"}
for i in range(3)
]
mock_async_repository.create.side_effect = [
{"id": f"id_{i}", **data} for i, data in enumerate(users_data)
]
# Act
tasks = [
async_user_service.create_user(data) for data in users_data
]
results = await asyncio.gather(*tasks)
# Assert
assert len(results) == 3
assert all("id" in result for result in results)
assert mock_async_repository.create.call_count == 3
async def test_timeout_handling(self, async_user_service, mock_async_repository):
"""Test handling of timeout in async operations."""
# Arrange
async def slow_operation(*args, **kwargs):
await asyncio.sleep(2) # Simulate slow operation
return {"id": "123", "name": "Slow User"}
mock_async_repository.find_by_id.side_effect = slow_operation
# Act & Assert
with pytest.raises(asyncio.TimeoutError):
await asyncio.wait_for(
async_user_service.get_user_by_id("123"),
timeout=1.0
)
```
## Mocking and Fixtures
### Complex Fixture Patterns
```python
# tests/conftest.py
import pytest
from unittest.mock import Mock, patch
from datetime import datetime, timedelta
from src.models.user import User
from src.services.email_service import EmailService
def freeze_time():
"""Fixture to freeze time for consistent testing."""
frozen_time = datetime(2023, 1, 1, 12, 0, 0)
with patch('src.utils.datetime.datetime') as mock_datetime:
mock_datetime.now.return_value = frozen_time
mock_datetime.utcnow.return_value = frozen_time
yield frozen_time
def mock_email_service():
"""Mock email service for testing."""
mock = Mock(spec=EmailService)
mock.send_email.return_value = True
mock.send_bulk_email.return_value = {"sent": 5, "failed": 0}
return mock
def user_data_variations(request):
"""Parametrized fixture for different user data."""
return request.param
def users_factory():
"""Factory fixture for creating multiple users."""
def _create_users(count=3, **overrides):
users = []
for i in range(count):
user_data = {
"name": f"User {i}",
"email": f"user{i}@example.com",
"age": 20 + i,
**overrides
}
users.append(User(**user_data))
return users
return _create_users
def test_config():
"""Session-scoped configuration for tests."""
return {
"database_url": "sqlite:///:memory:",
"debug": True,
"testing": True,
"email_backend": "mock"
}
```
### Advanced Mocking Patterns
```python
# tests/unit/test_advanced_mocking.py
import pytest
from unittest.mock import Mock, patch, MagicMock, call
from datetime import datetime
from src.services.notification_service import NotificationService
class TestAdvancedMocking:
"""Test suite demonstrating advanced mocking patterns."""
def test_property_mocking(self):
"""Test mocking object properties."""
# Arrange
mock_user = Mock()
type(mock_user).is_active = PropertyMock(return_value=True)
# Act & Assert
assert mock_user.is_active is True
def test_context_manager_mocking(self):
"""Test mocking context managers."""
# Arrange
with patch('builtins.open', mock_open(read_data='file content')) as mock_file:
# Act
with open('test.txt', 'r') as f:
content = f.read()
# Assert
assert content == 'file content'
mock_file.assert_called_once_with('test.txt', 'r')
def test_side_effect_with_exception(self):
"""Test using side_effect to raise exceptions."""
# Arrange
mock_service = Mock()
mock_service.get_user.side_effect = [
{"id": "1", "name": "User 1"}, # First call succeeds
Exception("Service unavailable"), # Second call fails
{"id": "3", "name": "User 3"}, # Third call succeeds
]
# Act & Assert
result1 = mock_service.get_user("1")
assert result1["name"] == "User 1"
with pytest.raises(Exception, match="Service unavailable"):
mock_service.get_user("2")
result3 = mock_service.get_user("3")
assert result3["name"] == "User 3"
def test_mock_chain_calls(self):
"""Test mocking chained method calls."""
# Arrange
mock_database = Mock()
mock_database.users.filter.return_value.order_by.return_value.limit.return_value = [
{"id": "1", "name": "User 1"}
]
# Act
result = mock_database.users.filter(active=True).order_by('name').limit(10)
# Assert
assert len(result) == 1
assert result[0]["name"] == "User 1"
def test_multiple_patches(self, mock_sms_service, mock_email_service):
"""Test using multiple patches."""
# Arrange
notification_service = NotificationService()
mock_email_service.return_value.send.return_value = True
mock_sms_service.return_value.send.return_value = True
# Act
result = notification_service.send_notification(
"user@example.com",
"Test message",
channels=["email", "sms"]
)
# Assert
assert result is True
mock_email_service.return_value.send.assert_called_once()
mock_sms_service.return_value.send.assert_called_once()
```
## Performance and Load Testing
### Performance Testing with pytest-benchmark
```python
# tests/performance/test_user_performance.py
import pytest
from src.services.user_service import UserService
from src.utils.data_processor import DataProcessor
class TestUserServicePerformance:
"""Performance tests for user service operations."""
def large_user_dataset(self):
"""Generate large dataset for performance testing."""
return [
{"name": f"User {i}", "email": f"user{i}@example.com", "age": 20 + (i % 50)}
for i in range(1000)
]
def test_user_creation_performance(self, benchmark, user_service, large_user_dataset):
"""Benchmark user creation performance."""
# Act & Assert
result = benchmark(user_service.create_bulk_users, large_user_dataset)
assert len(result) == 1000
def test_user_search_performance(self, benchmark, user_service):
"""Benchmark user search performance."""
# Arrange
# Assume users are already created in database
# Act & Assert
result = benchmark(user_service.search_users, query="User", limit=100)
assert len(result) <= 100
def test_batch_processing_performance(self, benchmark, batch_size):
"""Test performance with different batch sizes."""
# Arrange
processor = DataProcessor(batch_size=batch_size)
data = list(range(10000))
# Act & Assert
result = benchmark(processor.process_batch, data)
assert len(result) == 10000
```