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