﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
37371	Inconsistent behaviour when running tests with `--keepdb` flag and sqlite backend	Rebecca Smith		"`--keepdb` is expected to preserve a database between test runs. For sqlite backends, there are 2 issues:

**1. Misleading logs and unexpected behaviour using --keepdb with default TEST settings**

By default, `--keepdb` only has an effect if there is a `TEST` database name defined. If the `TEST` name is the default (None) , the sqlite backend ALWAYS uses an in-memory database, irrespective of the `--keepdb` flag.

This is documented here:
https://docs.djangoproject.com/en/6.1/ref/settings/#std-setting-TEST_NAME

However: it's not easy to find (it's not mentioned in the testing docs or the sqlite notes), and it's not documented anywhere that when the `TEST` name is None, using --keepdb will not make it change behaviour and write an ondisk file that is preserved: XXXX

Docs on [https://docs.djangoproject.com/en/6.1/topics/testing/overview/#the-test-database/ the test database] and [https://docs.djangoproject.com/en/6.1/topics/testing/overview/#preserving-the-test-database/ preserving the db] don't mention that for sqlite, --keepdb does not preserve the test db unless you have an explicit TEST setting.

In addition, when the tests run, they print misleading logs.
For example, take these settings:
{{{
DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.sqlite3',
       'NAME': BASE_DIR / 'db.sqlite3',
   }
}
}}}

Running `python manage.py test --keepdb` prints:
{{{
Found 2 test(s).
Using existing test database for alias 'default'...
System check identified no issues (0 silenced).
..
----------------------------------------------------------------------
Ran 2 tests in 0.669s

OK
Preserving test database for alias 'default'...
}}}

But no test database was preserved. (Running with `-v 2` will show the migrations being appplied on repeated test runs, despite the logs that say it's reusing an existing db).

In contrast, with these settings:
{{{
DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.sqlite3',
       'NAME': BASE_DIR / 'db.sqlite3',
       ""TEST"": {""NAME"": BASE_DIR / ""test_db.sqlite3""},
   }
}
}}}

Running `python manage.py test --keepdb` prints the exact same message as before, but this time a file called `test_db.sqlite3` **is** preserved.

I think there are a few options to improve this:
1) Raise an error when --keepdb is used with no TEST db configured, with an informative error message
2) Raise a warning when --keepdb is used with no TEST db configured, and/or fix the misleading logs
3) Make --keepdb work when there is no TEST db configured

(3) makes sqlite behave similarly to other DBs, rather than have a --keepdb flag that's silently ignored in some scenarios.
(1) or (2) keep the current behaviour but make it more obvious to the user what's going on. I'd lean towards (3) as the best option.

**2. Inconsistent behaviour when using --keepdb with default TEST settings and running tests in parallel**
When running tests in parallel with default TEST settings (i.e. TEST db name None), the testrunner's database setup creates a clone of the (in-memory) test database, one per worker. This is fine when the start method is fork, but the forksever/spawn start methods require migrating the in-memory db to disk.  This means that when the TEST db name is None, and tests are run in parallel, they actually DON'T use an in-memory db. This isn't noticeable unless also run with the --keepdb flag, which prevents cleanup of the cloned test dbs.

i.e. with these settings (no TEST db configured):
{{{
DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.sqlite3',
       'NAME': BASE_DIR / 'db.sqlite3',
   }
}
}}}

Running `python manage.py test --keepdb --parallel=auto` (with at least 2 tests so there's something to parallise) leaves behind databases called `default_1.sqlite3`, `default_2.sqlite3` etc if the multiprocessing start method is spawn or forkserver, but not if it's fork. As of python 3.14, [https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods/ fork isn't the default behaviour on any system], so users are likely to see the preserved dbs in parallel mode. The parallel case should behave consistently with serial test runs.

The fix for this will depend on how --keepdb is handled in the serial case. If we update the docs and logs to be more explicit about the fact that --keepdb will have no effect when there's no TEST db configured, then the parallel case should behave consistently and clean up its cloned dbs when there's no TEST db configured. If we modify the behaviour so that --keepdb uses an on-disk file that can be preserved, then I think the existing code will work as expected, although it would be worth documenting that running in parallel will use on-disk files, even if the TEST settings specify an in-memory file."	Bug	new	Testing framework	6.1	Normal				Unreviewed	0	0	0	0	0	0
