Browse Source

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.
Chris Jerdonek 4 years ago
parent
commit
0d2816133c
1 changed files with 39 additions and 33 deletions
  1. 39 33
      tests/runtests.py

+ 39 - 33
tests/runtests.py

@@ -75,11 +75,12 @@ tempfile.tempdir = os.environ['TMPDIR'] = TMPDIR
 atexit.register(shutil.rmtree, TMPDIR)
 
 
-SUBDIRS_TO_SKIP = [
-    'data',
-    'import_error_package',
-    'test_runner_apps',
-]
+# This is a dict mapping RUNTESTS_DIR subdirectory to subdirectories of that
+# directory to skip when searching for test modules.
+SUBDIRS_TO_SKIP = {
+    '': {'import_error_package', 'test_runner_apps'},
+    'gis_tests': {'data'},
+}
 
 ALWAYS_INSTALLED_APPS = [
     'django.contrib.contenttypes',
@@ -110,22 +111,34 @@ CONTRIB_TESTS_TO_APPS = {
 
 
 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:
         # GIS tests are in nested apps
-        discovery_paths.append(('gis_tests', os.path.join(RUNTESTS_DIR, 'gis_tests')))
+        discovery_dirs.append('gis_tests')
     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):
-            if ('.' not in f.name and
-                    os.path.basename(f.name) not in SUBDIRS_TO_SKIP and
-                    not f.is_file() and
-                    os.path.exists(os.path.join(f.path, '__init__.py'))):
-                modules.append((modpath, f.name))
-    return modules
+            if (
+                '.' in f.name or
+                os.path.basename(f.name) in subdirs_to_skip or
+                f.is_file() or
+                not os.path.exists(os.path.join(f.path, '__init__.py'))
+            ):
+                continue
+            test_module = f.name
+            if dirname:
+                test_module = dirname + '.' + test_module
+            yield test_module
 
 
 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.')
         sys.exit(1)
 
-    def _module_match_label(module_label, label):
+    def _module_match_label(module_name, label):
         # Exact or ancestor match.
-        return module_label == label or module_label.startswith(label + '.')
-
-    # Load all the test model apps.
-    test_modules = get_test_modules()
+        return module_name == label or module_name.startswith(label + '.')
 
     found_start = not (start_at or start_after)
     installed_app_names = set(get_installed())
-    for modpath, module_name in test_modules:
-        if modpath:
-            module_label = modpath + '.' + module_name
-        else:
-            module_label = module_name
+    for test_module in get_test_modules():
         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
-            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
                 continue
             else:
@@ -236,15 +242,15 @@ def setup(verbosity, start_at, start_after, test_labels=None):
         ):
             continue
 
-        if module_name in CONTRIB_TESTS_TO_APPS:
-            for contrib_app in CONTRIB_TESTS_TO_APPS[module_name]:
+        if test_module in CONTRIB_TESTS_TO_APPS:
+            for contrib_app in CONTRIB_TESTS_TO_APPS[test_module]:
                 if contrib_app not in settings.INSTALLED_APPS:
                     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:
-                print("Importing application %s" % module_name)
-            settings.INSTALLED_APPS.append(module_label)
+                print("Importing application %s" % test_module)
+            settings.INSTALLED_APPS.append(test_module)
 
     # Add contrib.gis to INSTALLED_APPS if needed (rather than requiring
     # @override_settings(INSTALLED_APPS=...) on all test cases.