skip to content

Throwaway Database Setup

The test runner creates a test_ database, runs migrations into it, and can keep or parallelise it across runs; fixtures or model factories seed data. Interviewers probe slow suites.

part ofDjangooverview, primer and where to startread it →
on this pageshow

explore

questions

5

When you run Django's manage.py test, which database do the tests use, and what happens to it before and after the run?

level: juniorimportance: must knowfreq 58%

answer

  1. never the configured database itself
  2. a prefix on NAME
  3. migrate runs first
  4. SQLite takes a shortcut
  5. destroyed unless told otherwise

basics

~20 s

Django's test runner creates a separate database named 'test_' plus each NAME in DATABASES (in memory for SQLite), runs migrate into it, runs the tests, and destroys it at the end unless --keepdb is passed.

solid answer

~40 s

`manage.py test` never touches the database your settings point at. For each database alias the collected tests declare, the runner creates a new one named `test_` + `NAME`, or `TEST["NAME"]` if you set it; with SQLite the default is an in-memory database. It then runs `migrate` into it (with `run_syncdb`, so apps without migrations get tables too) and `createcachetable`, runs the suite, and drops the database afterwards, whether tests passed or failed. `--keepdb` preserves it between runs. Everything else comes from the normal settings, so the configured `USER` needs permission to create databases. If a previous run was killed and left the test database behind, the runner asks whether to destroy it; `--noinput` answers yes automatically.

code

bash · 5 lines
bash
$ python manage.py test
Found 412 test(s).
Creating test database for alias 'default'...
...
Destroying test database for alias 'default'...

go deeper

for a junior

Know the lifecycle: a test_ prefixed database is created, migrated, used and destroyed, and SQLite uses memory by default.

for a middle

Explain which aliases get a test database, what the TEST dictionary controls, and why the database user needs create privileges.

for a senior

Anticipate environment problems: import-time queries hitting the real database, leftover test databases on CI, and engine differences between test and production.

for a principal

Decide the test database strategy for the organisation: same engine as production, CI database provisioning, and naming on shared servers.

## A throwaway database per run Tests that touch models must never run against the database your application uses. Django's default test runner, `DiscoverRunner` (what `manage.py test` uses), therefore builds a **separate, blank database** before any test runs and removes it afterwards. ## Before the tests: creation and migration 1. **Decide which databases are needed.** The runner looks at the `databases` attribute of every collected test case. `TestCase` and `TransactionTestCase` default to `{"default"}`, and `SimpleTestCase` declares none, so a suite of pure `SimpleTestCase` classes creates no database at all. Unused aliases are skipped. 2. **Pick a name.** The test database is called **`test_` + `NAME`**, for example `test_shop` for `NAME="shop"`. Setting `TEST["NAME"]` in the alias's `DATABASES` entry overrides it. With **SQLite** and no `TEST["NAME"]`, Django uses an **in-memory** database with shared cache, so nothing touches the filesystem. 3. **Create it** with the same `ENGINE`, `HOST`, `PORT` and `USER` as the real alias. That user therefore needs the privilege to create and drop databases; on PostgreSQL it also needs read access to the built-in `postgres` database, which Django connects to while creating the new one. 4. **Run `migrate`** into it, with `run_syncdb=True` so apps that have no migrations still get tables. Data migrations (`RunPython`) run too, so rows they insert exist in the test database. 5. **Run `createcachetable`** so the database cache backend works if configured. 6. **Run system checks** against the test databases, then start the suite. ## After the tests: destruction When the suite finishes, pass or fail, the runner destroys every test database it created. Two options change that: - **`--keepdb`** keeps it for the next run, creating it if missing and applying any unapplied migrations. - **`--noinput`** matters when a previous run was interrupted and left `test_shop` behind: instead of prompting "Type 'yes' if you would like to try deleting the test database", the runner destroys and recreates it. This is the usual flag on CI. ## The `TEST` settings dictionary | Key | Default | What it controls | |---|---|---| | `NAME` | `None` | explicit test database name; `None` means `test_` + `NAME`, or in-memory on SQLite | | `MIGRATE` | `True` | `False` skips migrations and builds tables straight from the models | | `MIRROR` | `None` | make this alias mirror another during tests, for replica setups | | `DEPENDENCIES` | `["default"]` for non-default aliases | creation order between aliases | | `CHARSET` / `COLLATION` | backend default | encoding of the created database (collation is MySQL only) | | `TEMPLATE` | none | PostgreSQL template to create the database from | ```python DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "NAME": "shop", "USER": "shop_app", "TEST": {"NAME": "shop_ci"}, # instead of test_shop } } ``` ## Traps worth knowing - **Import-time queries.** Code that queries the database at module import time, or in `AppConfig.ready()`, runs before the test database exists and can read the real database. Django's docs call this out; the fix is to move the query out of import time. - **Per-test cleanliness is a different mechanism.** The runner creates the database once per run; keeping each test isolated from the next is the job of the test case classes (transaction rollback in `TestCase`, table flush in `TransactionTestCase`). - **SQLite versus production.** An in-memory SQLite test database is fast, but if production runs PostgreSQL, constraint, JSON and locking behaviour can differ. Most teams run tests against the same engine as production. - **Leftover databases.** A killed CI job can leave `test_shop` on a shared server; `--noinput` on the next run cleans it up without hanging on a prompt. ## Multiple databases Projects with several aliases get one test database per alias that some test declares in its `databases` attribute. Two refinements matter: - **Mirrors.** An alias with `TEST["MIRROR"] = "default"` is not created at all; during tests it points at the default test database, which lets replica-routing code be tested. Because it relies on seeing committed data, it must be exercised from `TransactionTestCase`. - **Creation order.** `TEST["DEPENDENCIES"]` controls which alias is created first, which matters when one database's setup needs another to exist. Circular dependencies raise `ImproperlyConfigured`. ## What interviewers want to hear A good junior answer names the `test_` prefix, the fact that migrations run first, and that the database disappears afterwards. A stronger answer adds that only aliases the tests need are created, that the database user must be allowed to create databases, and that `--keepdb` and `--noinput` change the start and end of the lifecycle.

  • Why can a query in a module's top-level code read production data during tests?
    Modules are imported while the test runner collects tests and sets up Django, before the test database is created and before connection settings are swapped to point at it. A query at import time, or in `AppConfig.ready()`, therefore runs against the configured database. Move such queries into functions called at request or task time.
  • What does setting TEST['NAME'] change for a PostgreSQL alias?
    It replaces the default `test_` + `NAME` with the name you give, for example `shop_ci`. The database is still created and destroyed by the runner, and every other connection setting still comes from the alias. It is useful when several projects share a server or when a hosting policy restricts database names.

It is like a chef given a fresh copy of the kitchen for every rehearsal: the recipe book (migrations) is followed to stock it, the rehearsal happens, and the copy is demolished afterwards so the restaurant's real kitchen is never touched.

saying these in an interview costs you the question

  • Believing Django tests run against the configured database and roll back afterwards
  • Thinking migrations are skipped by default and tables come straight from models
  • Saying the test database is kept by default between runs
  • Assuming the test database needs no extra privileges for the database user
  • Claiming SimpleTestCase-only suites still create a test database
open as a page

In Django tests, how does seeding data with TestCase.fixtures compare with building it through model factories, and which do teams prefer?

level: middleimportance: should knowfreq 46%

basics

~20 s

TestCase.fixtures loads serialized files through loaddata, once per class, with raw saves that skip custom save() logic and drift as models change. Model factories build objects in Python per test, so most teams prefer factories and keep fixtures for small static reference data.

open as a page

What does Django's test --keepdb option save, and when can a kept test database give you misleading results?

level: middleimportance: should knowfreq 40%

basics

~20 s

--keepdb skips creating and destroying the test database, only applying unapplied migrations. It misleads when an already-applied migration was edited, when switching branches leaves a different schema, or when MIGRATE is False and models changed.

open as a page

How does Django's test --parallel option split the suite and the database, and what makes a suite unsafe to run with it?

level: seniorimportance: should knowfreq 36%

basics

~20 s

--parallel runs test case classes in several processes, one per CPU core by default, and gives each process its own clone of the test database. Tests are unsafe when they share anything else: files, an external cache, ports or order.

open as a page

A Django test suite now takes 20 minutes; how do you find where the time goes and cut the database-related share of it?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Measure first with --timing and --durations, then attack what dominates: --keepdb for setup, --parallel for idle cores, setUpTestData and factories instead of per-test data, a fast password hasher in test settings, and TestCase over TransactionTestCase where possible.

open as a page