Opened 4 months ago
Last modified 7 weeks ago
#36496 assigned Bug
SQLite test database path not recognised when running tests in parallel
| Reported by: | Damian Posener | Owned by: | Gangadhar Yadav |
|---|---|---|---|
| Component: | Testing framework | Version: | 5.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Abhishek Srivastava | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | yes | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
How to replicate:
- Have a DATABASES configuration with one or more SQLite DBs in directories, like this:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db' / 'default' / 'db.sqlite3', }, 'other': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db' / 'other' / 'db.sqlite3', } } - Run tests with both the
--parallel=autoand--keepdbflags, i.e.python manage.py test --keepdb --parallel=auto
Expected behaviour: .sqlite3 files should be kept in db/default and db/other directories
Actual behaviour: default_X.sqlite3 and other_X.sqlite3 files are saved in the root directory instead
Why is this a problem? When running multiple test suites at once, this leads to filename collision if two test suites are using the same database name(s). It is impossible to run two Django test suites in parallel from the same directory without encountering this issue.
Setting DATABASES['<alias>']['TEST']['NAME'] does not seem to solve this either.
I've put together an example project to demonstrate the issue. Simply run python manage.py test --keepdb --parallel=auto from the base directory.
Happy to answer any other questions. :)
Attachments (1)
Change History (22)
by , 4 months ago
| Attachment: | example.zip added |
|---|
comment:1 by , 4 months ago
| Cc: | added |
|---|
follow-up: 4 comment:2 by , 4 months ago
follow-up: 5 comment:3 by , 4 months ago
Why is this a problem? When running multiple test suites at once, this leads to filename collision if two test suites are using the same database name(s). It is impossible to run two Django test suites in parallel from the same directory without encountering this issue.
I don't think that's something Django's test machinery claims to supports by the way, I can't think of multiple things that would break running multiple test suites against the same checkout of a projects.
Am I missing any step to trigger the parallel test DB creation?
You need to have at least two TestCase otherwise βthese is nothing to parallelize.
comment:4 by , 4 months ago
Replying to abhishek1999:
Hi π β Iβm trying to reproduce this bug to help confirm .
Hereβs what I did so far:
- Created a test project with the
DATABASESconfig exactly as described.- Ran
migrateβ the.sqlite3file was created correctly indb/default/.- Added a simple
TestCasewith multiple dummy tests.- Ran
python manage.py test --keepdb --parallel=auto.Environment:
- Django version:
6.0.dev20250612075530(editable install)- Python version:
3.12.11- SQLite version:
3.43.2I only see
db/default/db.sqlite3β no additionaldefault_1.sqlite3orother_1.sqlite3files appear in the project root.
Am I missing any step to trigger the parallel test DB creation?
Any suggestions are appreciated β thanks!
There is a demo project attached to this ticket as a zip file. If you extract that and run tests you can replicate the issue hopefully.
comment:5 by , 4 months ago
Replying to Simon Charette:
I don't think that's something Django's test machinery claims to supports by the way, I can't think of multiple things that would break running multiple test suites against the same checkout of a projects.
We are using Django as a CMS for 14 different websites, and the nature of that beast is a lot of separate apps, each with their own separate test suites. Being able to run app tests in parallel saves us a bunch of time, but this database thing is a bit of a thorn in our side.
I think there's also some (probably minor) security risks around Django simply dumping it's databases copies in the current working directory. For one the directory might not actually be writable. If it is writable, it may contain other .sqlite3 files that aren't meant to be overwritten (Django does not seem to check whether the DBs are its own and will happily overwrite existing ones).
Personally I'd be happy if there was at least a way to specify where Django should store the files, but there seems to be no other option than to use the current working dir.
comment:6 by , 4 months ago
Personally I'd be happy if there was at least a way to specify where Django should store the files, but there seems to be no other option than to use the current working dir.
Have you tried using the explicit TEST.NAME βsetting?
I missed that part
Setting
DATABASES['<alias>']['TEST']['NAME']does not seem to solve this either.
I think we can accept on the basis that TEST.NAME should work.
comment:7 by , 4 months ago
| Triage Stage: | Unreviewed β Accepted |
|---|
comment:8 by , 4 months ago
You need to have at least two
TestCaseotherwise βthese is nothing to parallelize.
Thanks, I was able to reproduce the issue.
comment:9 by , 4 months ago
I tried this:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db" / "default" / "db.sqlite3",
"TEST": {
"NAME": BASE_DIR / "db" / "default" / "test_db.sqlite3",
},
},
"other": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db" / "other" / "db.sqlite3",
"TEST": {
"NAME": BASE_DIR / "db" / "other" / "test_db.sqlite3",
},
},
}
I added ['TEST']['NAME'] to keep test DB files in separate folders.
I ran:
python manage.py test --parallel=auto --keepdb
I got this error:
sqlite3.OperationalError: unable to open database file
follow-up: 11 comment:10 by , 4 months ago
Damian, do you have a requirement that parallel test databases are backed by actual files instead of being in memory per worker process which should ensure isolation?
What I mean is that if you want to avoid collisions until this gets fixed you could simply set DATABASES['<alias>']['TEST']['NAME'] = ':memory:' which is a common setup to speed up tests and ensure isolation.
comment:11 by , 4 months ago
Replying to Simon Charette:
Damian, do you have a requirement that parallel test databases are backed by actual files instead of being in memory per worker process which should ensure isolation?
What I mean is that if you want to avoid collisions until this gets fixed you could simply set
DATABASES['<alias>']['TEST']['NAME'] = ':memory:'which is a common setup to speed up tests and ensure isolation.
That would rather defeat the point of using --keepdb, don't you think? :D We do run with in-memory DBs for a few applications, but that's an inefficient choice when testing apps that have a load of migrations in them.
comment:12 by , 4 months ago
| Owner: | set to |
|---|---|
| Status: | new β assigned |
comment:13 by , 4 months ago
| Owner: | removed |
|---|---|
| Status: | assigned β new |
follow-up: 15 comment:14 by , 2 months ago
| Owner: | set to |
|---|---|
| Status: | new β assigned |
comment:15 by , 2 months ago
Replying to Gangadhar Yadav:
Working on this and have a near-final fix locally. The change ensures SQLite parallel test databases are created in the same directories as the configured database files (not the project root), preventing filename collisions. Iβve verified with multiple DB aliases and
--keepdb/--parallel=auto
preparing a PR with tests and details shortly. Expect a draft PR within the next 1β2 days.
comment:16 by , 8 weeks ago
| Has patch: | set |
|---|
PR: βhttps://github.com/django/django/pull/19864
This implements the fix and adds a regression test in
tests/backends/sqlite/test_creation.py::SQLiteParallelCloneTests.
comment:17 by , 8 weeks ago
| Patch needs improvement: | set |
|---|
comment:18 by , 8 weeks ago
| Patch needs improvement: | unset |
|---|
comment:19 by , 7 weeks ago
| Patch needs improvement: | set |
|---|
comment:20 by , 7 weeks ago
| Patch needs improvement: | unset |
|---|
comment:21 by , 7 weeks ago
| Needs tests: | set |
|---|
Hi π β Iβm trying to reproduce this bug to help confirm .
Hereβs what I did so far:
DATABASESconfig exactly as described.migrateβ the.sqlite3file was created correctly indb/default/.TestCasewith multiple dummy tests.python manage.py test --keepdb --parallel=auto.Environment:
6.0.dev20250612075530(editable install)3.12.113.43.2I only see
db/default/db.sqlite3β no additionaldefault_1.sqlite3orother_1.sqlite3files appear in the project root.Am I missing any step to trigger the parallel test DB creation?
Any suggestions are appreciated β thanks!