90 | | |
91 | | old_installed_apps = settings.INSTALLED_APPS |
92 | | old_root_urlconf = getattr(settings, "ROOT_URLCONF", "") |
93 | | old_template_dirs = settings.TEMPLATE_DIRS |
94 | | old_use_i18n = settings.USE_I18N |
95 | | old_login_url = settings.LOGIN_URL |
96 | | old_language_code = settings.LANGUAGE_CODE |
97 | | old_middleware_classes = settings.MIDDLEWARE_CLASSES |
| 90 | state = { |
| 91 | 'INSTALLED_APPS': settings.INSTALLED_APPS, |
| 92 | 'ROOT_URLCONF': getattr(settings, "ROOT_URLCONF", ""), |
| 93 | 'TEMPLATE_DIRS': settings.TEMPLATE_DIRS, |
| 94 | 'USE_I18N': settings.USE_I18N, |
| 95 | 'LOGIN_URL': settings.LOGIN_URL, |
| 96 | 'LANGUAGE_CODE': settings.LANGUAGE_CODE, |
| 97 | 'MIDDLEWARE_CLASSES': settings.MIDDLEWARE_CLASSES, |
| 98 | } |
175 | | # Restore the old settings. |
176 | | settings.INSTALLED_APPS = old_installed_apps |
177 | | settings.ROOT_URLCONF = old_root_urlconf |
178 | | settings.TEMPLATE_DIRS = old_template_dirs |
179 | | settings.USE_I18N = old_use_i18n |
180 | | settings.LANGUAGE_CODE = old_language_code |
181 | | settings.LOGIN_URL = old_login_url |
182 | | settings.MIDDLEWARE_CLASSES = old_middleware_classes |
| 188 | |
| 189 | def bisect_tests(bisection_label, options, test_labels): |
| 190 | state = setup(int(options.verbosity), test_labels) |
| 191 | |
| 192 | if not test_labels: |
| 193 | # Get the full list of test labels to use for bisection |
| 194 | from django.db.models.loading import get_apps |
| 195 | test_labels = [app.__name__.split('.')[-2] for app in get_apps()] |
| 196 | |
| 197 | print '***** Bisecting test suite:',' '.join(test_labels) |
| 198 | |
| 199 | # Make sure the bisection point isn't in the test list |
| 200 | # Also remove tests that need to be run in specific combinations |
| 201 | for label in [bisection_label, 'model_inheritance_same_model_name']: |
| 202 | try: |
| 203 | test_labels.remove(label) |
| 204 | except ValueError: |
| 205 | pass |
| 206 | |
| 207 | subprocess_args = ['python','runtests.py', '--settings=%s' % options.settings] |
| 208 | if options.failfast: |
| 209 | subprocess_args.append('--failfast') |
| 210 | if options.verbosity: |
| 211 | subprocess_args.append('--verbosity=%s' % options.verbosity) |
| 212 | if not options.interactive: |
| 213 | subprocess_args.append('--noinput') |
| 214 | |
| 215 | iteration = 1 |
| 216 | while len(test_labels) > 1: |
| 217 | midpoint = len(test_labels)/2 |
| 218 | test_labels_a = test_labels[:midpoint] + [bisection_label] |
| 219 | test_labels_b = test_labels[midpoint:] + [bisection_label] |
| 220 | print '***** Pass %da: Running the first half of the test suite' % iteration |
| 221 | print '***** Test labels:',' '.join(test_labels_a) |
| 222 | failures_a = subprocess.call(subprocess_args + test_labels_a) |
| 223 | |
| 224 | print '***** Pass %db: Running the second half of the test suite' % iteration |
| 225 | print '***** Test labels:',' '.join(test_labels_b) |
| 226 | print |
| 227 | failures_b = subprocess.call(subprocess_args + test_labels_b) |
| 228 | |
| 229 | if failures_a and not failures_b: |
| 230 | print "***** Problem found in first half. Bisecting again..." |
| 231 | iteration = iteration + 1 |
| 232 | test_labels = test_labels_a[:-1] |
| 233 | elif failures_b and not failures_a: |
| 234 | print "***** Problem found in second half. Bisecting again..." |
| 235 | iteration = iteration + 1 |
| 236 | test_labels = test_labels_b[:-1] |
| 237 | elif failures_a and failures_b: |
| 238 | print "***** Multiple sources of failure found" |
| 239 | break |
| 240 | else: |
| 241 | print "***** No source of failure found... try pair execution (--pair)" |
| 242 | break |
| 243 | |
| 244 | if len(test_labels) == 1: |
| 245 | print "***** Source of error:",test_labels[0] |
| 246 | teardown(state) |
| 247 | |
| 248 | def paired_tests(paired_test, options, test_labels): |
| 249 | state = setup(int(options.verbosity), test_labels) |
| 250 | |
| 251 | if not test_labels: |
| 252 | print "" |
| 253 | # Get the full list of test labels to use for bisection |
| 254 | from django.db.models.loading import get_apps |
| 255 | test_labels = [app.__name__.split('.')[-2] for app in get_apps()] |
| 256 | |
| 257 | print '***** Trying paired execution' |
| 258 | |
| 259 | # Make sure the bisection point isn't in the test list |
| 260 | # Also remove tests that need to be run in specific combinations |
| 261 | for label in [paired_test, 'model_inheritance_same_model_name']: |
| 262 | try: |
| 263 | test_labels.remove(label) |
| 264 | except ValueError: |
| 265 | pass |
| 266 | |
| 267 | subprocess_args = ['python','runtests.py', '--settings=%s' % options.settings] |
| 268 | if options.failfast: |
| 269 | subprocess_args.append('--failfast') |
| 270 | if options.verbosity: |
| 271 | subprocess_args.append('--verbosity=%s' % options.verbosity) |
| 272 | if not options.interactive: |
| 273 | subprocess_args.append('--noinput') |
| 274 | |
| 275 | for i, label in enumerate(test_labels): |
| 276 | print '***** %d of %d: Check test pairing with %s' % (i+1, len(test_labels), label) |
| 277 | failures = subprocess.call(subprocess_args + [label, paired_test]) |
| 278 | if failures: |
| 279 | print '***** Found problem pair with',label |
| 280 | return |
| 281 | teardown(state) |