Founder & Lead Engineer, RAITHub
RAITHub ships and tests production software. See QA as a Service or talk to us.
Testing a Django app means covering four layers: models and business logic, views and forms, the API (usually Django REST Framework) with its permissions, and the few end-to-end journeys that matter. Use pytest with pytest-django against a disposable test database, the Django test client for views, and a browser tool for journeys. An outside QA team can do this whether or not they built the app.
If you would rather have the suite built and run for you, see how RAITHub would test this near the end. RAITHub builds in Python and tests apps in these stacks; testing a framework does not require having built in it.
What should a Django test suite cover?
Django's structure points the test plan. Models hold business rules and constraints; views and forms handle requests and validation; Django REST Framework (DRF) exposes the API with permission classes; migrations change the schema. Each needs its own kind of test, and the permission layer is where the expensive bugs hide.
| Layer | What to test | Typical tool |
|---|---|---|
| Models and logic | Methods, validators, constraints, signals; pure business rules | pytest with pytest-django |
| Views and forms | Status, redirects, form validation, the right data for the right user | Django test client |
| API (DRF) | Status, serializer output, authentication, permissions per role, errors | DRF APIClient / pytest |
| Migrations | They apply cleanly, and data migrations transform rows correctly | pytest against a fresh test DB |
| End-to-end | Sign-in, the core workflow, checkout, in a real browser | Playwright or Cypress |
Most of the protection comes from the lower layers, which run fast against a test database. A small end-to-end set proves the whole thing holds together; that shape is the test pyramid, in the test pyramid for a SaaS.
What tools fit a Django app?
pytest with the pytest-django plugin is the common choice: it runs Django's tests with pytest's fixtures and clearer assertions, and manages the test database for you (pytest-django docs). Django's own test client and DRF's APIClient send requests to your views and endpoints in-process, so API tests run without a live server. For the browser journeys, Playwright or Cypress sits on top; Playwright vs Cypress in 2026 compares them, and the cross-browser testing checklist covers the browser pass.
Django creates and destroys a separate test database automatically, so tests never touch your real data (Django testing docs). Keep that behaviour: test against a real database, not mocks, so the tests catch wrong queries and unenforced constraints.
What does a good Django API test look like?
Test the endpoint through DRF's client with an authenticated user, and check both that the right user succeeds and that the wrong user is refused. The second half is the test that stops one user reading another's data. This pytest example uses the DRF APIClient:
Free checklist
AI-Built App Launch Readiness Checklist
25 checks before you let real users in. Enter your email and we’ll reveal it below (and send you a copy).
One email, the checklist, no spam. By submitting you agree we can email you this checklist and reply to your enquiry.
# tests/test_orders.py
import pytest
from rest_framework.test import APIClient
@pytest.mark.django_db
def test_user_cannot_read_another_users_order(alice, bob, make_order):
order = make_order(owner=alice)
client = APIClient()
client.force_authenticate(user=bob)
res = client.get(f"/api/orders/{order.id}/")
assert res.status_code in (403, 404)
Write that kind of test for every endpoint and role. The django_db marker gives the test a clean database transaction that rolls back after it, so each test is independent. For the full endpoint checklist, status, schema, validation, authentication, idempotency and errors, see the API testing guide.
What breaks in a Django app in production?
The expensive Django bugs are usually data and permission bugs, not crashes. A migration that applies locally but fails on production data; a DRF permission class that protects the list view but not the detail view; a query that is correct but fires once per row and crawls under load; a form that accepts input the model constraint then rejects at the database. Tests at the model, view and API layers catch these before a deploy does.
| Failure | How a test catches it |
|---|---|
| Migration fails on real data | Run migrations against a seeded test database in CI |
| Missing permission on a detail view | Authorisation test per endpoint and role |
| N+1 query under load | Assert query counts, then load-test the endpoint |
| Constraint rejects valid-looking input | Model and form validation tests on edge cases |
Buy, build or hire?
| Option | Choose this when | Watch out for |
|---|---|---|
| A tool or SaaS testing platform | You want recorded browser checks fast, with little code | Recorded tests break often and live outside your repository |
| Freelancers or crowdtesting | You need a one-off manual pass before a launch | No suite remains, and no one maintains it |
| An in-house QA hire | You release weekly and want QA on the team long-term | Needs someone who writes Python, not only a manual tester |
| A managed QAaaS team | You want the suite built across layers, gated in CI and kept current | Make sure the tests live in your repository and you own them |
Why RAITHub for testing a Django app?
RAITHub tests apps in these stacks whether or not it built them, and Python is part of its own stack: PadhAI, the AI tutoring platform RAITHub built, runs 11 services, two of them in Python. The method does not change with the framework: map the risk, test the money and data paths at the lowest layer that catches them, and gate the suite in CI. The test counts come from real repositories, 400+ on this site, 750+ on TheSkinProof (the founder's own venture), 1,024 on PropDesk; how that discipline works is in QA-first development: how RAITHub tests.
When you don't need RAITHub: if you want an engineer placed inside your team under your management, that is staff augmentation, which RAITHub does not offer; and a prototype you reshape weekly may only need a short manual pass. For the broader method, see how to test a SaaS application.
How RAITHub would test this
Through QA and test automation, part of QA as a service, RAITHub would:
- map your models, views, API endpoints and roles, and rank the money and data paths by cost of failure
- write pytest tests for models and logic, Django test-client tests for views, and DRF tests with an authorisation matrix per role
- test migrations against a seeded database, and add a small Playwright set for the journeys that matter
- wire the suite into your CI so a failing change blocks the release, with tests and configuration in your repository
Buy it as a monthly QA plan, a fixed-price one-off audit, or a dedicated QA team that RAITHub manages and bills monthly. Testers are never placed under your management. You own the tests and the IP, and an NDA is signed first. Start with a free 15-minute call, then a written fixed quote. Talk to RAITHub about testing your Django app.
Frequently asked questions
How do I test a Django app?
Use pytest with pytest-django against a disposable test database: test models and logic, use the Django test client for views, test the DRF API with permissions per role, check migrations, and add a small browser suite for key journeys, all in CI.
Should I use pytest or Django's built-in test runner?
Both work. Many teams prefer pytest with pytest-django for its fixtures and clearer assertions, while it still manages Django's test database for you. The built-in runner is fine too; the layers you test matter more than the runner.
Do Django tests use my real database?
No. Django creates a separate test database and destroys it afterwards, so tests never touch real data. Keep testing against a real (test) database rather than mocks, so wrong queries and unenforced constraints are caught.
How do I test a Django REST Framework API?
Use DRF's APIClient to send authenticated requests and check status, serializer output and permissions. For every endpoint and role, add a test that a user cannot reach another user's data; that is the test that stops data leaks.
Can RAITHub test a Django app if it did not build it in Django?
Yes. Testing an app does not require having built it, and RAITHub works in Python. It starts with the money and data paths, writes tests that pin down current behaviour, and gates them in CI before widening coverage.
Will I own the tests?
Yes. The tests and CI configuration live in your repository, the IP is assigned to you, and the engagement runs month-to-month, so the suite keeps protecting you after it ends.
Related posts
Ready to discuss your project?
Book a free 15-minute technical audit with our engineering team.