django-testing-layout
Test layout, factory_boy over fixtures, and conftest.py structure.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Test layout, factory_boy over fixtures, and conftest.py structure.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Database migrations best practices, NEVER editing old migrations, and generating data migrations.
Models, Django ORM, query optimization, and transactions
Testing, security, authentication, caching, logging, performance, and deployment
admin.py, forms.py, file uploads, and the Django admin performance guide
services.py, selectors.py, Celery tasks, Signals, and background processing
Project structure, clean architecture principles, and the Service Layer pattern
| name | django-testing-layout |
| description | Test layout, factory_boy over fixtures, and conftest.py structure. |
A well-structured testing setup prevents flaky tests, reduces boilerplate, and ensures test suites remain fast and maintainable.
Tests should live inside the app they are testing, separated by layer.
✅ Recommended Layout:
apps/billing/
├── tests/
│ ├── __init__.py
│ ├── conftest.py # App-specific Pytest fixtures
│ ├── factories.py # factory_boy definitions
│ ├── test_models.py
│ ├── test_services.py # Pure Python unit tests for business logic
│ ├── test_selectors.py
│ └── test_views.py # APIClient / WebTest integration tests
For project-wide fixtures (e.g. creating authenticated API clients, or global mock setup), use a root-level conftest.py:
myproject/
├── conftest.py # Root conftest (global fixtures)
├── apps/
│ ├── billing/
│ └── users/
❌ Anti-pattern: Using Django JSON/YAML fixtures (fixtures/data.json).
Why?
Static fixtures are notoriously brittle. If you add a required field to a model or change the schema, you must manually update every static fixture file. They also obscure test data from the test itself, making it hard to read.
✅ Recommended: Use factory_boy.
Factories generate dynamic test data on the fly and are resilient to schema changes.
# apps/users/tests/factories.py
import factory
from django.contrib.auth import get_user_model
User = get_user_model()
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
username = factory.Sequence(lambda n: f"user_{n}")
email = factory.LazyAttribute(lambda obj: f"{obj.username}@example.com")
is_active = True
In your tests:
# apps/users/tests/test_services.py
from apps.users.tests.factories import UserFactory
def test_deactivate_user(db):
# Generates a user in the DB dynamically
user = UserFactory(is_active=True)
deactivate_user(user)
assert not user.is_active
conftest.pyUse conftest.py to share setup logic seamlessly across tests via Pytest fixtures, instead of using setUp in class-based tests.
✅ Recommended conftest.py:
# conftest.py
import pytest
from rest_framework.test import APIClient
from apps.users.tests.factories import UserFactory
@pytest.fixture
def api_client():
return APIClient()
@pytest.fixture
def user():
return UserFactory()
@pytest.fixture
def auth_client(api_client, user):
"""Returns an APIClient authenticated as a normal user."""
api_client.force_authenticate(user=user)
return api_client
Usage in tests:
def test_authenticated_endpoint(auth_client):
response = auth_client.get('/api/billing/invoices/')
assert response.status_code == 200