Code

Ticket #8363: 8363-r14297.2.diff

File 8363-r14297.2.diff, 7.3 KB (added by ramiro, 4 years ago)
Line 
1diff --git a/django/test/simple.py b/django/test/simple.py
2--- a/django/test/simple.py
3+++ b/django/test/simple.py
4@@ -1,6 +1,3 @@
5-import sys
6-import signal
7-
8 from django.conf import settings
9 from django.db.models import get_app, get_apps
10 from django.test import _doctest as doctest
11@@ -26,7 +23,7 @@
12     try:
13         app_path = app_module.__name__.split('.')[:-1]
14         test_module = __import__('.'.join(app_path + [TEST_MODULE]), {}, {}, TEST_MODULE)
15-    except ImportError, e:
16+    except ImportError:
17         # Couldn't import tests.py. Was it due to a missing file, or
18         # due to an import error in a tests.py that actually exists?
19         import os.path
20@@ -198,8 +195,19 @@
21     def build_suite(self, test_labels, extra_tests=None, **kwargs):
22         suite = unittest.TestSuite()
23 
24+        exclude_labels = kwargs.get('exclude_labels')
25+        if exclude_labels is None:
26+            exclude_labels = []
27+
28         if test_labels:
29             for label in test_labels:
30+                if label in exclude_labels:
31+                    if self.verbosity >= 1:
32+                        if '.' in label:
33+                            print 'Skipping %s test' % label
34+                        else:
35+                            print 'Skipping tests from app %s' % label
36+                    continue
37                 if '.' in label:
38                     suite.addTest(build_test(label))
39                 else:
40@@ -269,10 +277,14 @@
41         A list of 'extra' tests may also be provided; these tests
42         will be added to the test suite.
43 
44+        It's also possible to specify a list of labels to exclude from the
45+        test suite by using the exclude_labels parameter.
46+
47         Returns the number of tests that failed.
48         """
49+        exclude_labels = kwargs.get('exclude_labels')
50         self.setup_test_environment()
51-        suite = self.build_suite(test_labels, extra_tests)
52+        suite = self.build_suite(test_labels, extra_tests, exclude_labels=exclude_labels)
53         old_config = self.setup_databases()
54         result = self.run_suite(suite)
55         self.teardown_databases(old_config)
56diff --git a/tests/runtests.py b/tests/runtests.py
57--- a/tests/runtests.py
58+++ b/tests/runtests.py
59@@ -1,5 +1,7 @@
60 #!/usr/bin/env python
61-import os, subprocess, sys, traceback
62+import os
63+import subprocess
64+import sys
65 
66 import django.contrib as contrib
67 from django.utils import unittest
68@@ -63,7 +65,7 @@
69 
70         try:
71             module = load_app(self.model_label)
72-        except Exception, e:
73+        except Exception:
74             self.fail('Unable to load invalid model module')
75 
76         # Make sure sys.stdout is not a tty so that we get errors without
77@@ -72,7 +74,7 @@
78         orig_stdout = sys.stdout
79         s = StringIO()
80         sys.stdout = s
81-        count = get_validation_errors(s, module)
82+        get_validation_errors(s, module)
83         sys.stdout = orig_stdout
84         s.seek(0)
85         error_log = s.read()
86@@ -85,7 +87,7 @@
87         self.assert_(not unexpected, "Unexpected Errors: " + '\n'.join(unexpected))
88         self.assert_(not missing, "Missing Errors: " + '\n'.join(missing))
89 
90-def setup(verbosity, test_labels):
91+def setup(verbosity, test_labels, exclude_labels):
92     from django.conf import settings
93     state = {
94         'INSTALLED_APPS': settings.INSTALLED_APPS,
95@@ -116,20 +118,31 @@
96     # in our tests.
97     settings.MANAGERS = ("admin@djangoproject.com",)
98 
99+    if exclude_labels is None:
100+        exclude_labels = []
101+
102     # Load all the ALWAYS_INSTALLED_APPS.
103     # (This import statement is intentionally delayed until after we
104     # access settings because of the USE_I18N dependency.)
105     from django.db.models.loading import get_apps, load_app
106     get_apps()
107 
108+    # Only avoid loading an app if it is fully excluded, if testcases or test
109+    # methods names were excluded then load its apps normally
110+    exclude_apps = [label for label in exclude_labels if '.' not in label]
111+
112     # Load all the test model apps.
113-    test_labels_set = set([label.split('.')[0] for label in test_labels])
114+    test_labels_set = set([label.split('.')[0] for label in test_labels if label not in exclude_apps])
115     for model_dir, model_name in get_test_models():
116         model_label = '.'.join([model_dir, model_name])
117-        # if the model was named on the command line, or
118-        # no models were named (i.e., run all), import
119-        # this model and add it to the list to test.
120+        # if the model was named on the command line, or no models were named
121+        # (i.e., run all), import this model and add it to the list to test.
122+        # Also, skip importing the test apps explicitly excluded by the user.
123         if not test_labels or model_name in test_labels_set:
124+            if model_name in exclude_apps:
125+                if verbosity >= 2:
126+                    print "Skipping import of app %s" % model_name
127+                continue
128             if verbosity >= 2:
129                 print "Importing model %s" % model_name
130             mod = load_app(model_label)
131@@ -145,9 +158,9 @@
132     for key, value in state.items():
133         setattr(settings, key, value)
134 
135-def django_tests(verbosity, interactive, failfast, test_labels):
136+def django_tests(verbosity, interactive, failfast, test_labels, exclude_labels=None):
137     from django.conf import settings
138-    state = setup(verbosity, test_labels)
139+    state = setup(verbosity, test_labels, exclude_labels)
140 
141     # Add tests for invalid models.
142     extra_tests = []
143@@ -162,7 +175,8 @@
144             except ValueError:
145                 pass
146 
147-    # Run the test suite, including the extra validation tests.
148+    # Run the test suite, including the extra validation tests and skipping
149+    # the test explicitely excluded.
150     from django.test.utils import get_runner
151     if not hasattr(settings, 'TEST_RUNNER'):
152         settings.TEST_RUNNER = 'django.test.simple.DjangoTestSuiteRunner'
153@@ -180,7 +194,7 @@
154             extra_tests=extra_tests)
155     else:
156         test_runner = TestRunner(verbosity=verbosity, interactive=interactive, failfast=failfast)
157-        failures = test_runner.run_tests(test_labels, extra_tests=extra_tests)
158+        failures = test_runner.run_tests(test_labels, extra_tests=extra_tests, exclude_labels=exclude_labels)
159 
160     teardown(state)
161     return failures
162@@ -299,6 +313,8 @@
163         help="Bisect the test suite to discover a test that causes a test failure when combined with the named test.")
164     parser.add_option('--pair', action='store', dest='pair', default=None,
165         help="Run the test suite in pairs with the named test to find problem pairs.")
166+    parser.add_option('-e', '--exclude', action='append', dest='exclude', default=None,
167+        help='Test to exclude (use multiple times to exclude multiple tests).')
168     options, args = parser.parse_args()
169     if options.settings:
170         os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
171@@ -311,6 +327,12 @@
172     elif options.pair:
173         paired_tests(options.pair, options, args)
174     else:
175-        failures = django_tests(int(options.verbosity), options.interactive, options.failfast, args)
176+        failures = django_tests(
177+                int(options.verbosity),
178+                options.interactive,
179+                options.failfast,
180+                args,
181+                options.exclude
182+            )
183         if failures:
184             sys.exit(bool(failures))