mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
Fixed #31169 -- Adapted the parallel test runner to use spawn.
Co-authored-by: Valz <ahmadahussein0@gmail.com> Co-authored-by: Nick Pope <nick@nickpope.me.uk>
This commit is contained in:
committed by
Carlton Gibson
parent
3eaba13a47
commit
3b3f38b3b0
@@ -70,6 +70,8 @@ class SessionMiddlewareSubclass(SessionMiddleware):
|
||||
],
|
||||
)
|
||||
class SystemChecksTestCase(SimpleTestCase):
|
||||
databases = "__all__"
|
||||
|
||||
def test_checks_are_performed(self):
|
||||
admin.site.register(Song, MyAdmin)
|
||||
try:
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import copy
|
||||
import multiprocessing
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
from django.db import DEFAULT_DB_ALIAS, connection, connections
|
||||
from django.db import DEFAULT_DB_ALIAS, NotSupportedError, connection, connections
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
||||
@@ -33,3 +35,9 @@ class TestDbSignatureTests(SimpleTestCase):
|
||||
creation_class = test_connection.creation_class(test_connection)
|
||||
clone_settings_dict = creation_class.get_test_db_clone_settings("1")
|
||||
self.assertEqual(clone_settings_dict["NAME"], expected_clone_name)
|
||||
|
||||
@mock.patch.object(multiprocessing, "get_start_method", return_value="forkserver")
|
||||
def test_get_test_db_clone_settings_not_supported(self, *mocked_objects):
|
||||
msg = "Cloning with start method 'forkserver' is not supported."
|
||||
with self.assertRaisesMessage(NotSupportedError, msg):
|
||||
connection.creation.get_test_db_clone_settings(1)
|
||||
|
||||
@@ -362,5 +362,7 @@ class CheckFrameworkReservedNamesTests(SimpleTestCase):
|
||||
|
||||
|
||||
class ChecksRunDuringTests(SimpleTestCase):
|
||||
databases = "__all__"
|
||||
|
||||
def test_registered_check_did_run(self):
|
||||
self.assertTrue(my_check.did_run)
|
||||
|
||||
@@ -11,6 +11,8 @@ from django.test.utils import isolate_apps
|
||||
|
||||
@isolate_apps("contenttypes_tests", attr_name="apps")
|
||||
class GenericForeignKeyTests(SimpleTestCase):
|
||||
databases = "__all__"
|
||||
|
||||
def test_missing_content_type_field(self):
|
||||
class TaggedItem(models.Model):
|
||||
# no content_type field
|
||||
|
||||
@@ -22,6 +22,13 @@ class RemoveStaleContentTypesTests(TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
with captured_stdout():
|
||||
call_command(
|
||||
"remove_stale_contenttypes",
|
||||
interactive=False,
|
||||
include_stale_apps=True,
|
||||
verbosity=2,
|
||||
)
|
||||
cls.before_count = ContentType.objects.count()
|
||||
cls.content_type = ContentType.objects.create(
|
||||
app_label="contenttypes_tests", model="Fake"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from datetime import date
|
||||
|
||||
from django.test import modify_settings
|
||||
|
||||
from . import PostgreSQLTestCase
|
||||
from .models import (
|
||||
HStoreModel,
|
||||
@@ -16,6 +18,7 @@ except ImportError:
|
||||
pass # psycopg2 isn't installed.
|
||||
|
||||
|
||||
@modify_settings(INSTALLED_APPS={"append": "django.contrib.postgres"})
|
||||
class BulkSaveTests(PostgreSQLTestCase):
|
||||
def test_bulk_update(self):
|
||||
test_data = [
|
||||
|
||||
@@ -3,6 +3,7 @@ import argparse
|
||||
import atexit
|
||||
import copy
|
||||
import gc
|
||||
import multiprocessing
|
||||
import os
|
||||
import shutil
|
||||
import socket
|
||||
@@ -10,6 +11,7 @@ import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import warnings
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
@@ -24,7 +26,7 @@ else:
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import connection, connections
|
||||
from django.test import TestCase, TransactionTestCase
|
||||
from django.test.runner import get_max_test_processes, parallel_type
|
||||
from django.test.runner import _init_worker, get_max_test_processes, parallel_type
|
||||
from django.test.selenium import SeleniumTestCaseBase
|
||||
from django.test.utils import NullTimeKeeper, TimeKeeper, get_runner
|
||||
from django.utils.deprecation import RemovedInDjango50Warning
|
||||
@@ -382,7 +384,8 @@ def django_tests(
|
||||
msg += " with up to %d processes" % max_parallel
|
||||
print(msg)
|
||||
|
||||
test_labels, state = setup_run_tests(verbosity, start_at, start_after, test_labels)
|
||||
process_setup_args = (verbosity, start_at, start_after, test_labels)
|
||||
test_labels, state = setup_run_tests(*process_setup_args)
|
||||
# Run the test suite, including the extra validation tests.
|
||||
if not hasattr(settings, "TEST_RUNNER"):
|
||||
settings.TEST_RUNNER = "django.test.runner.DiscoverRunner"
|
||||
@@ -395,6 +398,11 @@ def django_tests(
|
||||
parallel = 1
|
||||
|
||||
TestRunner = get_runner(settings)
|
||||
TestRunner.parallel_test_suite.init_worker = partial(
|
||||
_init_worker,
|
||||
process_setup=setup_run_tests,
|
||||
process_setup_args=process_setup_args,
|
||||
)
|
||||
test_runner = TestRunner(
|
||||
verbosity=verbosity,
|
||||
interactive=interactive,
|
||||
@@ -718,6 +726,11 @@ if __name__ == "__main__":
|
||||
options.settings = os.environ["DJANGO_SETTINGS_MODULE"]
|
||||
|
||||
if options.selenium:
|
||||
if multiprocessing.get_start_method() == "spawn" and options.parallel != 1:
|
||||
parser.error(
|
||||
"You cannot use --selenium with parallel tests on this system. "
|
||||
"Pass --parallel=1 to use --selenium."
|
||||
)
|
||||
if not options.tags:
|
||||
options.tags = ["selenium"]
|
||||
elif "selenium" not in options.tags:
|
||||
|
||||
@@ -86,6 +86,16 @@ class DiscoverRunnerParallelArgumentTests(SimpleTestCase):
|
||||
mocked_cpu_count,
|
||||
):
|
||||
mocked_get_start_method.return_value = "spawn"
|
||||
self.assertEqual(get_max_test_processes(), 12)
|
||||
with mock.patch.dict(os.environ, {"DJANGO_TEST_PROCESSES": "7"}):
|
||||
self.assertEqual(get_max_test_processes(), 7)
|
||||
|
||||
def test_get_max_test_processes_forkserver(
|
||||
self,
|
||||
mocked_get_start_method,
|
||||
mocked_cpu_count,
|
||||
):
|
||||
mocked_get_start_method.return_value = "forkserver"
|
||||
self.assertEqual(get_max_test_processes(), 1)
|
||||
with mock.patch.dict(os.environ, {"DJANGO_TEST_PROCESSES": "7"}):
|
||||
self.assertEqual(get_max_test_processes(), 1)
|
||||
|
||||
@@ -480,8 +480,6 @@ class ManageCommandTests(unittest.TestCase):
|
||||
# Isolate from the real environment.
|
||||
@mock.patch.dict(os.environ, {}, clear=True)
|
||||
@mock.patch.object(multiprocessing, "cpu_count", return_value=12)
|
||||
# Python 3.8 on macOS defaults to 'spawn' mode.
|
||||
@mock.patch.object(multiprocessing, "get_start_method", return_value="fork")
|
||||
class ManageCommandParallelTests(SimpleTestCase):
|
||||
def test_parallel_default(self, *mocked_objects):
|
||||
with captured_stderr() as stderr:
|
||||
@@ -507,8 +505,8 @@ class ManageCommandParallelTests(SimpleTestCase):
|
||||
# Parallel is disabled by default.
|
||||
self.assertEqual(stderr.getvalue(), "")
|
||||
|
||||
def test_parallel_spawn(self, mocked_get_start_method, mocked_cpu_count):
|
||||
mocked_get_start_method.return_value = "spawn"
|
||||
@mock.patch.object(multiprocessing, "get_start_method", return_value="spawn")
|
||||
def test_parallel_spawn(self, *mocked_objects):
|
||||
with captured_stderr() as stderr:
|
||||
call_command(
|
||||
"test",
|
||||
@@ -517,8 +515,8 @@ class ManageCommandParallelTests(SimpleTestCase):
|
||||
)
|
||||
self.assertIn("parallel=1", stderr.getvalue())
|
||||
|
||||
def test_no_parallel_spawn(self, mocked_get_start_method, mocked_cpu_count):
|
||||
mocked_get_start_method.return_value = "spawn"
|
||||
@mock.patch.object(multiprocessing, "get_start_method", return_value="spawn")
|
||||
def test_no_parallel_spawn(self, *mocked_objects):
|
||||
with captured_stderr() as stderr:
|
||||
call_command(
|
||||
"test",
|
||||
|
||||
Reference in New Issue
Block a user