From 08f360355a0f47b35df355aae6ba88957b0e3a8d Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 16 Aug 2018 21:49:03 +0200 Subject: [PATCH] Fixed #29704 -- Fixed manage.py test --testrunner if it isn't followed by an equals sign. --- django/core/management/commands/test.py | 7 ++----- django/core/management/utils.py | 18 +++++++++++++++++- tests/test_runner/tests.py | 9 +++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/django/core/management/commands/test.py b/django/core/management/commands/test.py index e4f80aada3..3da2f93eed 100644 --- a/django/core/management/commands/test.py +++ b/django/core/management/commands/test.py @@ -2,6 +2,7 @@ import sys from django.conf import settings from django.core.management.base import BaseCommand +from django.core.management.utils import get_command_line_option from django.test.utils import get_runner @@ -18,11 +19,7 @@ class Command(BaseCommand): option. This allows a test runner to define additional command line arguments. """ - option = '--testrunner=' - for arg in argv[2:]: - if arg.startswith(option): - self.test_runner = arg[len(option):] - break + self.test_runner = get_command_line_option(argv, '--testrunner') super().run_from_argv(argv) def add_arguments(self, parser): diff --git a/django/core/management/utils.py b/django/core/management/utils.py index df61bec26f..d2b85c986f 100644 --- a/django/core/management/utils.py +++ b/django/core/management/utils.py @@ -5,7 +5,7 @@ from django.apps import apps as installed_apps from django.utils.crypto import get_random_string from django.utils.encoding import DEFAULT_LOCALE_ENCODING -from .base import CommandError +from .base import CommandError, CommandParser def popen_wrapper(args, stdout_encoding='utf-8'): @@ -106,3 +106,19 @@ def parse_apps_and_model_labels(labels): apps.add(app_config) return models, apps + + +def get_command_line_option(argv, option): + """ + Return the value of a command line option (which should include leading + dashes, e.g. '--testrunnner') from an argument list. Return None if the + option wasn't passed or if the argument list couldn't be parsed. + """ + parser = CommandParser(add_help=False, allow_abbrev=False) + parser.add_argument(option, dest='value') + try: + options, _ = parser.parse_known_args(argv[2:]) + except CommandError: + return None + else: + return options.value diff --git a/tests/test_runner/tests.py b/tests/test_runner/tests.py index eb89ad79f8..9717d329c1 100644 --- a/tests/test_runner/tests.py +++ b/tests/test_runner/tests.py @@ -201,6 +201,15 @@ class CustomTestRunnerOptionsCmdlineTests(AdminScriptTestCase): def tearDown(self): self.remove_settings('settings.py') + def test_testrunner_option(self): + args = [ + 'test', '--testrunner', 'test_runner.runner.CustomOptionsTestRunner', + '--option_a=bar', '--option_b=foo', '--option_c=31337' + ] + out, err = self.run_django_admin(args, 'test_project.settings') + self.assertNoOutput(err) + self.assertOutput(out, 'bar:foo:31337') + def test_testrunner_equals(self): args = [ 'test', '--testrunner=test_runner.runner.CustomOptionsTestRunner',