Introducing Automated Testing Late in a Django + DRF Project: Setup, Requirements, and Best Practices - Part-1

Published: (December 11, 2025 at 10:01 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Many Django REST Framework projects begin with rapid feature development and no automated test suite. At first this feels productive, but as foreign keys grow, serializers become nested, and the system gains complexity, manual testing becomes fragile and extremely time‑consuming.

This two‑part series shows exactly how to introduce pytest into an existing Django REST Framework project, even if you’re deep into development.

Part 1 covers

  • Why pytest is ideal for Django + DRF
  • Installing pytest and configuring project‑level settings
  • Creating a separate test settings file
  • Setting up a dedicated PostgreSQL test database
  • Building fixtures for API clients and test users
  • Handling custom user models safely
  • Preparing your project to run tests reliably

Part 2 will show real‑world test cases using a Blog → Writer → Category → SocialMediaMeta use case.


Why Add Tests at a Later Stage?

Many teams postpone testing until:

  • Models are stabilized
  • Views and serializers begin accumulating logic
  • Manual testing becomes slow or error‑prone
  • Refactoring becomes risky
  • Bugs begin recurring
  • Onboarding new developers becomes cumbersome

Good news: pytest integrates cleanly even in a large, fully active Django project, as long as you separate your test configuration correctly.

Install pytest and Required Plugins

pip install pytest pytest-django pytest-cov Faker

These tools provide:

  • pytest – fast, expressive testing
  • pytest-django – Django ORM, fixtures, DB setup
  • pytest-cov – code coverage
  • Faker – generating random test data

Create pytest.ini in Project Root

[pytest]
DJANGO_SETTINGS_MODULE = project.settings.test
python_files = tests.py test_*.py *_tests.py
addopts = --reuse-db -x

Key points

  • Explicitly point pytest to a test settings file.
  • --reuse-db speeds testing dramatically.
  • -x stops after the first failure (optional but useful early on).

Create settings/test.py

from .local import *

DATABASES["default"]["NAME"] = "test_db"
AUTH_PASSWORD_VALIDATORS = []

TEST_USER = {
    "id": 999,
    "email": "testuser@example.com",
}

(a) Separate database

Tests must not touch your development DB.

(b) Disable password validators

Tests should not fail due to password complexity requirements.

(c) TEST_USER

Allows bypassing complex signup flows (OTP, email verification, custom user manager logic).

PostgreSQL: Create a Dedicated Test Database

CREATE DATABASE test_db;
GRANT ALL PRIVILEGES ON DATABASE test_db TO your_db_user;
ALTER DATABASE test_db OWNER TO your_db_user;

Creating the DB manually avoids the dreaded:

permission denied to create database

Add tests/ Directory Structure

tests/
│── __init__.py
│── conftest.py
│── test_blog_creation.py
│── test_blog_listing.py
│── test_nested_blog_response.py
│── test_signals_blog_metadata.py

The key file here is conftest.py.

Create conftest.py with Critical Fixtures

import pytest
from django.contrib.auth import get_user_model
from blogs.models import Writer, Category

@pytest.fixture
def test_user(db, settings):
    User = get_user_model()
    data = settings.TEST_USER
    return User.objects.create(
        id=data["id"],
        email=data["email"],
        is_active=True,
    )

@pytest.fixture
def api_client(test_user):
    from rest_framework.test import APIClient
    client = APIClient()
    client.force_authenticate(test_user)
    return client

@pytest.fixture
def writer(db):
    return Writer.objects.create(
        name="Jane Writer",
        email="jane@example.com",
    )

@pytest.fixture
def category(db):
    return Category.objects.create(
        title="Technology",
        slug="tech",
    )

These fixtures provide:

  • An authenticated API client (no login/OTP steps)
  • A reusable test user
  • Reliable foreign‑key dependencies

Running Tests for the First Time

pytest -s

If everything is configured correctly, pytest will create the test database and run the tests successfully.

Next in Part 2: Real‑World DRF Testing Use Cases

In the next section we will cover:

  • Blog + Writer + Category + SocialMediaMeta sample models
  • Nested serializers
  • Foreign‑key creation tests
  • Signals and reverse relationships
  • Error‑validation tests
  • Testing nested JSON structures
  • Testing authenticated requests
Back to Blog

Related posts

Read more »