#31169 closed New feature (fixed)
Allow parallel test runner to work with Windows/macOS `spawn` process start method.
| Reported by: | Brandon Navra | Owned by: | David Smith |
|---|---|---|---|
| Component: | Testing framework | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Ichlasul Affan, Ryan Siemens, Adam Wróbel | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Python 3.8 on MacOS has changed the default start method for the multiprocessing module from fork to spawn: ​https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods.
When running tests with the --parallel flag, this causes the worker processes to fail with django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. as they no longer have a copy of the parent memory state. It can also cause the workers to fail to find the cloned dbs ( {{django.db.utils.OperationalError: FATAL: database "xxx_1" does not exist}} ) as the db test prefix is missing.
I have attached a patch which changes django.test.runner._init_worker (the worker initialiser for ParallelTestSuite) to run django.setup() and set the db name to one with the test_ prefix.
Attachments (1)
Change History (32)
by , 6 years ago
| Attachment: | Ensure_Django_is_setup_correctly_in_parallel_test_workers.patch added |
|---|
comment:1 by , 6 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 6 years ago
comment:3 by , 6 years ago
I'm still trying to research the exact root cause. The Python issue which triggered this change has snippets of info: https://code.djangoproject.com/ticket/31169
but nothing conclusive. My theory is that the memory copying semantics between MacOS and Windows are different and hence the spawn method doesn't have identical behaviour between the two.
comment:5 by , 6 years ago
| Summary: | Parallel test mode not working on MacOS with recent versions of Python 3 → Allow parallel test runner to work with Windows/macOS `spawn` process start method. |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
| Type: | Bug → New feature |
| Version: | 3.0 → master |
Parallel running is disabled on Windows:
def default_test_processes():
"""Default number of test processes when using the --parallel option."""
# The current implementation of the parallel test runner requires
# multiprocessing to start subprocesses with fork().
if multiprocessing.get_start_method() != 'fork':
return 1
try:
return int(os.environ['DJANGO_TEST_PROCESSES'])
except KeyError:
return multiprocessing.cpu_count()
I'll accept this as a new feature: the limitation has been there since it was implemented.
Brandon, your patch is tiny. Is it really that simple? We'd need tests and a few other adjustments (like to the function above) but, fancy opening a PR?
comment:6 by , 6 years ago
So this occurs on macOS 10.15. (I have 10.14 currently so can't experiment there.)
Applying the patch on Windows, alas, doesn't immediately solve the issue, but it is INSTALLED_APPS/AppRegistry errors that are raised, so it's going to be in the right ball-park.
More investigating needed, but this would be a good one to land.
comment:7 by , 6 years ago
I created a PR with the changes from my patch: ​https://github.com/django/django/pull/12321
FYI" I am on macOS 10.14.6
I'm not sure how best to adjust default_test_processes as i've always used the --parallel flag with a parameter.
Also, could you provide some guidance on how you'd like this tested
comment:8 by , 6 years ago
FYI" I am on macOS 10.14.6
Super. I had a 3.7. env active. I can reproduce with Python 3.8.
comment:10 by , 6 years ago
Thanks for the report. I had the same issue but did not find the root cause in https://code.djangoproject.com/ticket/31116.
I would love to see that being resolved.
comment:11 by , 6 years ago
| Patch needs improvement: | set |
|---|
comment:12 by , 6 years ago
I ran into this while running the Django test suite, and when applying the patch in ​PR 12321, I get the same problem with a different exception:
Traceback (most recent call last):
File "/Users/inglesp/.pyenv/versions/3.8.0/lib/python3.8/multiprocessing/process.py", line 313, in _bootstrap
self.run()
File "/Users/inglesp/.pyenv/versions/3.8.0/lib/python3.8/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/Users/inglesp/.pyenv/versions/3.8.0/lib/python3.8/multiprocessing/pool.py", line 114, in worker
task = get()
File "/Users/inglesp/.pyenv/versions/3.8.0/lib/python3.8/multiprocessing/queues.py", line 358, in get
return _ForkingPickler.loads(res)
File "/Users/inglesp/src/django/django/tests/fixtures_regress/tests.py", line 18, in <module>
from .models import (
File "/Users/inglesp/src/django/django/tests/fixtures_regress/models.py", line 1, in <module>
from django.contrib.auth.models import User
File "/Users/inglesp/src/django/django/django/contrib/auth/models.py", line 3, in <module>
from django.contrib.contenttypes.models import ContentType
File "/Users/inglesp/src/django/django/django/contrib/contenttypes/models.py", line 133, in <module>
class ContentType(models.Model):
File "/Users/inglesp/src/django/django/django/db/models/base.py", line 113, in __new__
raise RuntimeError(
RuntimeError: Model class django.contrib.contenttypes.models.ContentType doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
I'm on OSX 10.15 with Python 3.8.
comment:13 by , 6 years ago
| Cc: | added |
|---|
An attempt at a fix: ​https://github.com/django/django/pull/12547
comment:14 by , 6 years ago
| Cc: | added |
|---|
comment:15 by , 5 years ago
| Has patch: | unset |
|---|---|
| Owner: | changed from to |
| Patch needs improvement: | unset |
| Status: | new → assigned |
comment:16 by , 5 years ago
For those looking for a workaround, here's how to add the appropriate call to reset back to fork mode: ​https://adamj.eu/tech/2020/07/21/how-to-use-djangos-parallel-testing-on-macos-with-python-3.8-plus/
comment:17 by , 5 years ago
| Has patch: | set |
|---|
comment:18 by , 5 years ago
| Cc: | removed |
|---|
comment:19 by , 5 years ago
| Cc: | added |
|---|
comment:20 by , 4 years ago
| Patch needs improvement: | set |
|---|
PR is working nicely on macOS but needs a rebase, and a refactoring for review comments.
comment:21 by , 4 years ago
| Cc: | added |
|---|
comment:22 by , 4 years ago
| Owner: | changed from to |
|---|---|
| Patch needs improvement: | unset |
comment:23 by , 4 years ago
| Patch needs improvement: | set |
|---|
A few issues on the PR to resolve, but looking very promising: 39.813s vs 249.146s on macOS, which is a bit of a speed-up 🙂
comment:25 by , 4 years ago
| Patch needs improvement: | unset |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
comment:27 by , 4 years ago
| Patch needs improvement: | set |
|---|---|
| Triage Stage: | Ready for checkin → Accepted |
comment:28 by , 4 years ago
| Patch needs improvement: | unset |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
spawn()is also a default method on Windows, and we don't encounter any issues with it 🤔.