Refs #32668 -- Simplified get_test_modules() in runtests.py.

This simplifies runtests.py's get_test_modules() in a few ways.  For
example, it changes the function to yield strings instead of returning
pairs of strings, which simplifies the calling code.

This commit also changes SUBDIRS_TO_SKIP from a list to a dict since
the directories to skip depend on the parent directory.
This commit is contained in:
Chris Jerdonek 2021-04-06 08:46:05 -07:00 committed by Mariusz Felisiak
parent ffc0d57a04
commit 0d2816133c
1 changed files with 39 additions and 33 deletions

View File

@ -75,11 +75,12 @@ tempfile.tempdir = os.environ['TMPDIR'] = TMPDIR
atexit.register(shutil.rmtree, TMPDIR) atexit.register(shutil.rmtree, TMPDIR)
SUBDIRS_TO_SKIP = [ # This is a dict mapping RUNTESTS_DIR subdirectory to subdirectories of that
'data', # directory to skip when searching for test modules.
'import_error_package', SUBDIRS_TO_SKIP = {
'test_runner_apps', '': {'import_error_package', 'test_runner_apps'},
] 'gis_tests': {'data'},
}
ALWAYS_INSTALLED_APPS = [ ALWAYS_INSTALLED_APPS = [
'django.contrib.contenttypes', 'django.contrib.contenttypes',
@ -110,22 +111,34 @@ CONTRIB_TESTS_TO_APPS = {
def get_test_modules(): def get_test_modules():
modules = [] """
discovery_paths = [(None, RUNTESTS_DIR)] Scan the tests directory and yield the names of all test modules.
The yielded names have either one dotted part like "test_runner" or, in
the case of GIS tests, two dotted parts like "gis_tests.gdal_tests".
"""
discovery_dirs = ['']
if connection.features.gis_enabled: if connection.features.gis_enabled:
# GIS tests are in nested apps # GIS tests are in nested apps
discovery_paths.append(('gis_tests', os.path.join(RUNTESTS_DIR, 'gis_tests'))) discovery_dirs.append('gis_tests')
else: else:
SUBDIRS_TO_SKIP.append('gis_tests') SUBDIRS_TO_SKIP[''].add('gis_tests')
for modpath, dirpath in discovery_paths: for dirname in discovery_dirs:
dirpath = os.path.join(RUNTESTS_DIR, dirname)
subdirs_to_skip = SUBDIRS_TO_SKIP[dirname]
for f in os.scandir(dirpath): for f in os.scandir(dirpath):
if ('.' not in f.name and if (
os.path.basename(f.name) not in SUBDIRS_TO_SKIP and '.' in f.name or
not f.is_file() and os.path.basename(f.name) in subdirs_to_skip or
os.path.exists(os.path.join(f.path, '__init__.py'))): f.is_file() or
modules.append((modpath, f.name)) not os.path.exists(os.path.join(f.path, '__init__.py'))
return modules ):
continue
test_module = f.name
if dirname:
test_module = dirname + '.' + test_module
yield test_module
def get_installed(): def get_installed():
@ -206,24 +219,17 @@ def setup(verbosity, start_at, start_after, test_labels=None):
print('Aborting: A GIS database backend is required to run gis_tests.') print('Aborting: A GIS database backend is required to run gis_tests.')
sys.exit(1) sys.exit(1)
def _module_match_label(module_label, label): def _module_match_label(module_name, label):
# Exact or ancestor match. # Exact or ancestor match.
return module_label == label or module_label.startswith(label + '.') return module_name == label or module_name.startswith(label + '.')
# Load all the test model apps.
test_modules = get_test_modules()
found_start = not (start_at or start_after) found_start = not (start_at or start_after)
installed_app_names = set(get_installed()) installed_app_names = set(get_installed())
for modpath, module_name in test_modules: for test_module in get_test_modules():
if modpath:
module_label = modpath + '.' + module_name
else:
module_label = module_name
if not found_start: if not found_start:
if start_at and _module_match_label(module_label, start_at): if start_at and _module_match_label(test_module, start_at):
found_start = True found_start = True
elif start_after and _module_match_label(module_label, start_after): elif start_after and _module_match_label(test_module, start_after):
found_start = True found_start = True
continue continue
else: else:
@ -236,15 +242,15 @@ def setup(verbosity, start_at, start_after, test_labels=None):
): ):
continue continue
if module_name in CONTRIB_TESTS_TO_APPS: if test_module in CONTRIB_TESTS_TO_APPS:
for contrib_app in CONTRIB_TESTS_TO_APPS[module_name]: for contrib_app in CONTRIB_TESTS_TO_APPS[test_module]:
if contrib_app not in settings.INSTALLED_APPS: if contrib_app not in settings.INSTALLED_APPS:
settings.INSTALLED_APPS.append(contrib_app) settings.INSTALLED_APPS.append(contrib_app)
if module_label not in installed_app_names: if test_module not in installed_app_names:
if verbosity >= 2: if verbosity >= 2:
print("Importing application %s" % module_name) print("Importing application %s" % test_module)
settings.INSTALLED_APPS.append(module_label) 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.