Fixed #30245 -- Added -k option to DiscoverRunner.
This commit is contained in:
parent
719b746620
commit
568eed9e79
|
@ -17,6 +17,7 @@ from django.test.utils import (
|
|||
teardown_databases as _teardown_databases, teardown_test_environment,
|
||||
)
|
||||
from django.utils.datastructures import OrderedSet
|
||||
from django.utils.version import PY37
|
||||
|
||||
try:
|
||||
import tblib.pickling_support
|
||||
|
@ -407,7 +408,7 @@ class DiscoverRunner:
|
|||
def __init__(self, pattern=None, top_level=None, verbosity=1,
|
||||
interactive=True, failfast=False, keepdb=False,
|
||||
reverse=False, debug_mode=False, debug_sql=False, parallel=0,
|
||||
tags=None, exclude_tags=None, **kwargs):
|
||||
tags=None, exclude_tags=None, test_name_patterns=None, **kwargs):
|
||||
|
||||
self.pattern = pattern
|
||||
self.top_level = top_level
|
||||
|
@ -421,6 +422,14 @@ class DiscoverRunner:
|
|||
self.parallel = parallel
|
||||
self.tags = set(tags or [])
|
||||
self.exclude_tags = set(exclude_tags or [])
|
||||
self.test_name_patterns = None
|
||||
if test_name_patterns:
|
||||
# unittest does not export the _convert_select_pattern function
|
||||
# that converts command-line arguments to patterns.
|
||||
self.test_name_patterns = {
|
||||
pattern if '*' in pattern else '*%s*' % pattern
|
||||
for pattern in test_name_patterns
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def add_arguments(cls, parser):
|
||||
|
@ -433,7 +442,7 @@ class DiscoverRunner:
|
|||
help='The test matching pattern. Defaults to test*.py.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-k', '--keepdb', action='store_true',
|
||||
'--keepdb', action='store_true',
|
||||
help='Preserves the test DB between runs.'
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -461,6 +470,15 @@ class DiscoverRunner:
|
|||
'--exclude-tag', action='append', dest='exclude_tags',
|
||||
help='Do not run tests with the specified tag. Can be used multiple times.',
|
||||
)
|
||||
if PY37:
|
||||
parser.add_argument(
|
||||
'-k', action='append', dest='test_name_patterns',
|
||||
help=(
|
||||
'Only run test methods and classes that match the pattern '
|
||||
'or substring. Can be used multiple times. Same as '
|
||||
'unittest -k option.'
|
||||
),
|
||||
)
|
||||
|
||||
def setup_test_environment(self, **kwargs):
|
||||
setup_test_environment(debug=self.debug_mode)
|
||||
|
@ -470,6 +488,7 @@ class DiscoverRunner:
|
|||
suite = self.test_suite()
|
||||
test_labels = test_labels or ['.']
|
||||
extra_tests = extra_tests or []
|
||||
self.test_loader.testNamePatterns = self.test_name_patterns
|
||||
|
||||
discover_kwargs = {}
|
||||
if self.pattern is not None:
|
||||
|
|
|
@ -1360,7 +1360,7 @@ The ``test`` command receives options on behalf of the specified
|
|||
:option:`--testrunner`. These are the options of the default test runner:
|
||||
:class:`~django.test.runner.DiscoverRunner`.
|
||||
|
||||
.. django-admin-option:: --keepdb, -k
|
||||
.. django-admin-option:: --keepdb
|
||||
|
||||
Preserves the test database between test runs. This has the advantage of
|
||||
skipping both the create and destroy actions which can greatly decrease the
|
||||
|
@ -1438,6 +1438,18 @@ May be specified multiple times and combined with :option:`test --exclude-tag`.
|
|||
Excludes tests :ref:`marked with the specified tags <topics-tagging-tests>`.
|
||||
May be specified multiple times and combined with :option:`test --tag`.
|
||||
|
||||
.. django-admin-option:: -k TEST_NAME_PATTERNS
|
||||
|
||||
.. versionadded:: 3.0
|
||||
|
||||
Runs test methods and classes matching test name patterns, in the same way as
|
||||
:option:`unittest's -k option<unittest.-k>`. Can be specified multiple times.
|
||||
|
||||
.. admonition:: Python 3.7 and later
|
||||
|
||||
This feature is only available for Python 3.7 and later.
|
||||
|
||||
|
||||
``testserver``
|
||||
--------------
|
||||
|
||||
|
|
|
@ -238,6 +238,9 @@ Tests
|
|||
attribute :attr:`~django.test.Response.exc_info`, a tuple providing
|
||||
information of the exception that occurred.
|
||||
|
||||
* Tests and test cases to run can be selected by test name pattern using the
|
||||
new :option:`test -k` option.
|
||||
|
||||
URLs
|
||||
~~~~
|
||||
|
||||
|
@ -360,6 +363,9 @@ Miscellaneous
|
|||
This converts ``'`` to ``'`` instead of the previous equivalent decimal
|
||||
code ``'``.
|
||||
|
||||
* The ``django-admin test -k`` option now works as the :option:`unittest
|
||||
-k<unittest.-k>` option rather than as a shortcut for ``--keepdb``.
|
||||
|
||||
.. _deprecated-features-3.0:
|
||||
|
||||
Features deprecated in 3.0
|
||||
|
|
|
@ -424,7 +424,7 @@ behavior. This class defines the ``run_tests()`` entry point, plus a
|
|||
selection of other methods that are used to by ``run_tests()`` to set up,
|
||||
execute and tear down the test suite.
|
||||
|
||||
.. class:: DiscoverRunner(pattern='test*.py', top_level=None, verbosity=1, interactive=True, failfast=False, keepdb=False, reverse=False, debug_mode=False, debug_sql=False, **kwargs)
|
||||
.. class:: DiscoverRunner(pattern='test*.py', top_level=None, verbosity=1, interactive=True, failfast=False, keepdb=False, reverse=False, debug_mode=False, debug_sql=False, test_name_patterns=None, **kwargs)
|
||||
|
||||
``DiscoverRunner`` will search for tests in any file matching ``pattern``.
|
||||
|
||||
|
@ -463,6 +463,9 @@ execute and tear down the test suite.
|
|||
as the traceback. If ``verbosity`` is ``2``, then queries in all tests are
|
||||
output.
|
||||
|
||||
``test_name_patterns`` can be used to specify a set of patterns for
|
||||
filtering test methods and classes by their names.
|
||||
|
||||
Django may, from time to time, extend the capabilities of the test runner
|
||||
by adding new arguments. The ``**kwargs`` declaration allows for this
|
||||
expansion. If you subclass ``DiscoverRunner`` or write your own test
|
||||
|
|
|
@ -28,6 +28,7 @@ else:
|
|||
RemovedInDjango31Warning, RemovedInDjango40Warning,
|
||||
)
|
||||
from django.utils.log import DEFAULT_LOGGING
|
||||
from django.utils.version import PY37
|
||||
|
||||
try:
|
||||
import MySQLdb
|
||||
|
@ -271,7 +272,8 @@ class ActionSelenium(argparse.Action):
|
|||
|
||||
|
||||
def django_tests(verbosity, interactive, failfast, keepdb, reverse,
|
||||
test_labels, debug_sql, parallel, tags, exclude_tags):
|
||||
test_labels, debug_sql, parallel, tags, exclude_tags,
|
||||
test_name_patterns):
|
||||
state = setup(verbosity, test_labels, parallel)
|
||||
extra_tests = []
|
||||
|
||||
|
@ -290,6 +292,7 @@ def django_tests(verbosity, interactive, failfast, keepdb, reverse,
|
|||
parallel=actual_test_processes(parallel),
|
||||
tags=tags,
|
||||
exclude_tags=exclude_tags,
|
||||
test_name_patterns=test_name_patterns,
|
||||
)
|
||||
failures = test_runner.run_tests(
|
||||
test_labels or get_installed(),
|
||||
|
@ -416,7 +419,7 @@ if __name__ == "__main__":
|
|||
help='Tells Django to stop running the test suite after first failed test.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-k', '--keepdb', action='store_true',
|
||||
'--keepdb', action='store_true',
|
||||
help='Tells Django to preserve the test database between runs.',
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -469,6 +472,14 @@ if __name__ == "__main__":
|
|||
'--exclude-tag', dest='exclude_tags', action='append',
|
||||
help='Do not run tests with the specified tag. Can be used multiple times.',
|
||||
)
|
||||
if PY37:
|
||||
parser.add_argument(
|
||||
'-k', dest='test_name_patterns', action='append',
|
||||
help=(
|
||||
'Only run test methods and classes matching test name pattern. '
|
||||
'Same as unittest -k option. Can be used multiple times.'
|
||||
),
|
||||
)
|
||||
|
||||
options = parser.parse_args()
|
||||
|
||||
|
@ -507,6 +518,7 @@ if __name__ == "__main__":
|
|||
options.keepdb, options.reverse, options.modules,
|
||||
options.debug_sql, options.parallel, options.tags,
|
||||
options.exclude_tags,
|
||||
getattr(options, 'test_name_patterns', None),
|
||||
)
|
||||
if failures:
|
||||
sys.exit(1)
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import os
|
||||
from argparse import ArgumentParser
|
||||
from contextlib import contextmanager
|
||||
from unittest import TestSuite, TextTestRunner, defaultTestLoader
|
||||
from unittest import TestSuite, TextTestRunner, defaultTestLoader, skipUnless
|
||||
|
||||
from django.db import connections
|
||||
from django.test import SimpleTestCase
|
||||
from django.test.runner import DiscoverRunner
|
||||
from django.test.utils import captured_stdout
|
||||
from django.utils.version import PY37
|
||||
|
||||
|
||||
@contextmanager
|
||||
|
@ -23,6 +24,13 @@ def change_cwd(directory):
|
|||
|
||||
class DiscoverRunnerTests(SimpleTestCase):
|
||||
|
||||
@staticmethod
|
||||
def get_test_methods_names(suite):
|
||||
return [
|
||||
t.__class__.__name__ + '.' + t._testMethodName
|
||||
for t in suite._tests
|
||||
]
|
||||
|
||||
def test_init_debug_mode(self):
|
||||
runner = DiscoverRunner()
|
||||
self.assertFalse(runner.debug_mode)
|
||||
|
@ -71,6 +79,34 @@ class DiscoverRunnerTests(SimpleTestCase):
|
|||
|
||||
self.assertEqual(count, 1)
|
||||
|
||||
@skipUnless(PY37, 'unittest -k option requires Python 3.7 and later')
|
||||
def test_name_patterns(self):
|
||||
all_test_1 = [
|
||||
'DjangoCase1.test_1', 'DjangoCase2.test_1',
|
||||
'SimpleCase1.test_1', 'SimpleCase2.test_1',
|
||||
'UnittestCase1.test_1', 'UnittestCase2.test_1',
|
||||
]
|
||||
all_test_2 = [
|
||||
'DjangoCase1.test_2', 'DjangoCase2.test_2',
|
||||
'SimpleCase1.test_2', 'SimpleCase2.test_2',
|
||||
'UnittestCase1.test_2', 'UnittestCase2.test_2',
|
||||
]
|
||||
all_tests = sorted([*all_test_1, *all_test_2, 'UnittestCase2.test_3_test'])
|
||||
for pattern, expected in [
|
||||
[['test_1'], all_test_1],
|
||||
[['UnittestCase1'], ['UnittestCase1.test_1', 'UnittestCase1.test_2']],
|
||||
[['*test'], ['UnittestCase2.test_3_test']],
|
||||
[['test*'], all_tests],
|
||||
[['test'], all_tests],
|
||||
[['test_1', 'test_2'], sorted([*all_test_1, *all_test_2])],
|
||||
[['test*1'], all_test_1],
|
||||
]:
|
||||
with self.subTest(pattern):
|
||||
suite = DiscoverRunner(
|
||||
test_name_patterns=pattern
|
||||
).build_suite(['test_runner_apps.simple'])
|
||||
self.assertEqual(expected, self.get_test_methods_names(suite))
|
||||
|
||||
def test_file_path(self):
|
||||
with change_cwd(".."):
|
||||
count = DiscoverRunner().build_suite(
|
||||
|
@ -170,7 +206,7 @@ class DiscoverRunnerTests(SimpleTestCase):
|
|||
msg="Methods of Django cases should be reversed.")
|
||||
self.assertIn('test_2', suite[4].id(),
|
||||
msg="Methods of simple cases should be reversed.")
|
||||
self.assertIn('test_2', suite[8].id(),
|
||||
self.assertIn('test_2', suite[9].id(),
|
||||
msg="Methods of unittest cases should be reversed.")
|
||||
|
||||
def test_overridable_get_test_runner_kwargs(self):
|
||||
|
|
|
@ -55,3 +55,6 @@ class UnittestCase2(TestCase):
|
|||
|
||||
def test_2(self):
|
||||
pass
|
||||
|
||||
def test_3_test(self):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue