Refs #32668 -- Refactored out setup_collect_tests() in runtests.py.

This commit is contained in:
Chris Jerdonek 2021-06-03 22:03:34 -07:00 committed by Mariusz Felisiak
parent 9b9cea04b9
commit b3083d5bd2
1 changed files with 69 additions and 51 deletions

View File

@ -142,11 +142,7 @@ def get_test_modules(gis_enabled):
yield test_module yield test_module
def get_installed(): def get_filtered_test_modules(start_at, start_after, gis_enabled, test_labels=None):
return [app_config.name for app_config in apps.get_app_configs()]
def setup(verbosity, start_at, start_after, test_labels=None):
if test_labels is None: if test_labels is None:
test_labels = [] test_labels = []
# Reduce each test label to just the top-level module part. # Reduce each test label to just the top-level module part.
@ -155,13 +151,35 @@ def setup(verbosity, start_at, start_after, test_labels=None):
test_module = label.split('.')[0] test_module = label.split('.')[0]
test_labels_set.add(test_module) test_labels_set.add(test_module)
# Force declaring available_apps in TransactionTestCase for faster tests. # It would be nice to put this validation earlier but it must come after
def no_available_apps(self): # django.setup() so that connection.features.gis_enabled can be accessed.
raise Exception("Please define available_apps in TransactionTestCase " if 'gis_tests' in test_labels_set and not gis_enabled:
"and its subclasses.") print('Aborting: A GIS database backend is required to run gis_tests.')
TransactionTestCase.available_apps = property(no_available_apps) sys.exit(1)
TestCase.available_apps = None
def _module_match_label(module_name, label):
# Exact or ancestor match.
return module_name == label or module_name.startswith(label + '.')
start_label = start_at or start_after
for test_module in get_test_modules(gis_enabled):
if start_label:
if not _module_match_label(test_module, start_label):
continue
start_label = ''
if not start_at:
assert start_after
# Skip the current one before starting.
continue
# If the module (or an ancestor) was named on the command line, or
# no modules were named (i.e., run all), include the test module.
if not test_labels or any(
_module_match_label(test_module, label) for label in test_labels_set
):
yield test_module
def setup_collect_tests(start_at, start_after, test_labels=None):
state = { state = {
'INSTALLED_APPS': settings.INSTALLED_APPS, 'INSTALLED_APPS': settings.INSTALLED_APPS,
'ROOT_URLCONF': getattr(settings, "ROOT_URLCONF", ""), 'ROOT_URLCONF': getattr(settings, "ROOT_URLCONF", ""),
@ -212,58 +230,58 @@ def setup(verbosity, start_at, start_after, test_labels=None):
# Load all the ALWAYS_INSTALLED_APPS. # Load all the ALWAYS_INSTALLED_APPS.
django.setup() django.setup()
# It would be nice to put this validation earlier but it must come after # This flag must be evaluated after django.setup() because otherwise it can
# django.setup() so that connection.features.gis_enabled can be accessed # raise AppRegistryNotReady when running gis_tests in isolation on some
# without raising AppRegistryNotReady when running gis_tests in isolation # backends (e.g. PostGIS).
# on some backends (e.g. PostGIS).
gis_enabled = connection.features.gis_enabled gis_enabled = connection.features.gis_enabled
if 'gis_tests' in test_labels_set and not gis_enabled:
print('Aborting: A GIS database backend is required to run gis_tests.')
sys.exit(1)
def _module_match_label(module_name, label): test_modules = list(get_filtered_test_modules(
# Exact or ancestor match. start_at, start_after, gis_enabled, test_labels=test_labels,
return module_name == label or module_name.startswith(label + '.') ))
return test_modules, state
start_label = start_at or start_after
installed_app_names = set(get_installed())
for test_module in get_test_modules(gis_enabled):
if start_label:
if not _module_match_label(test_module, start_label):
continue
start_label = ''
if not start_at:
assert start_after
# Skip the current one before starting.
continue
# if the module (or an ancestor) was named on the command line, or
# no modules were named (i.e., run all), import
# this module and add it to INSTALLED_APPS.
if test_labels and not any(
_module_match_label(test_module, label) for label in test_labels_set
):
continue
def get_installed():
return [app_config.name for app_config in apps.get_app_configs()]
# This function should be called only after calling django.setup(),
# since it calls connection.features.gis_enabled.
def get_apps_to_install(test_modules):
for test_module in test_modules:
if test_module in CONTRIB_TESTS_TO_APPS: if test_module in CONTRIB_TESTS_TO_APPS:
for contrib_app in CONTRIB_TESTS_TO_APPS[test_module]: yield from CONTRIB_TESTS_TO_APPS[test_module]
if contrib_app not in settings.INSTALLED_APPS: yield test_module
settings.INSTALLED_APPS.append(contrib_app)
if test_module not in installed_app_names:
if verbosity >= 2:
print("Importing application %s" % test_module)
settings.INSTALLED_APPS.append(test_module)
# Add contrib.gis to INSTALLED_APPS if needed (rather than requiring # Add contrib.gis to INSTALLED_APPS if needed (rather than requiring
# @override_settings(INSTALLED_APPS=...) on all test cases. # @override_settings(INSTALLED_APPS=...) on all test cases.
gis = 'django.contrib.gis' if connection.features.gis_enabled:
if connection.features.gis_enabled and gis not in settings.INSTALLED_APPS: yield 'django.contrib.gis'
def setup(verbosity, start_at, start_after, test_labels=None):
test_modules, state = setup_collect_tests(start_at, start_after, test_labels=test_labels)
installed_apps = set(get_installed())
for app in get_apps_to_install(test_modules):
if app in installed_apps:
continue
if verbosity >= 2: if verbosity >= 2:
print("Importing application %s" % gis) print(f'Importing application {app}')
settings.INSTALLED_APPS.append(gis) settings.INSTALLED_APPS.append(app)
installed_apps.add(app)
apps.set_installed_apps(settings.INSTALLED_APPS) apps.set_installed_apps(settings.INSTALLED_APPS)
# Force declaring available_apps in TransactionTestCase for faster tests.
def no_available_apps(self):
raise Exception(
'Please define available_apps in TransactionTestCase and its '
'subclasses.'
)
TransactionTestCase.available_apps = property(no_available_apps)
TestCase.available_apps = None
# Set an environment variable that other code may consult to see if # Set an environment variable that other code may consult to see if
# Django's own test suite is running. # Django's own test suite is running.
os.environ['RUNNING_DJANGOS_TEST_SUITE'] = 'true' os.environ['RUNNING_DJANGOS_TEST_SUITE'] = 'true'