Skip to content

bpo-30523: unittest: add --list-tests option #1885

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Doc/library/unittest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,10 @@ Command-line options

Stop the test run on the first error or failure.

.. cmdoption:: --list-tests

Only display the list of test names, don't run tests.

.. cmdoption:: --locals

Show local variables in tracebacks.
Expand All @@ -229,6 +233,9 @@ Command-line options
.. versionadded:: 3.5
The command-line option ``--locals``.

.. versionadded:: 3.7
The command-line option ``--list-tests``.

The command line can also be used for test discovery, for running all of the
tests in a project or just a subset.

Expand Down
12 changes: 10 additions & 2 deletions Lib/unittest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ class TestProgram(object):
def __init__(self, module='__main__', defaultTest=None, argv=None,
testRunner=None, testLoader=loader.defaultTestLoader,
exit=True, verbosity=1, failfast=None, catchbreak=None,
buffer=None, warnings=None, *, tb_locals=False):
buffer=None, warnings=None,
*, tb_locals=False, list_tests=False):
if isinstance(module, str):
self.module = __import__(module)
for part in module.split('.')[1:]:
Expand All @@ -73,6 +74,7 @@ def __init__(self, module='__main__', defaultTest=None, argv=None,
self.failfast = failfast
self.catchbreak = catchbreak
self.verbosity = verbosity
self.list_tests = list_tests
self.buffer = buffer
self.tb_locals = tb_locals
if warnings is None and not sys.warnoptions:
Expand Down Expand Up @@ -164,6 +166,10 @@ def _getParentArgParser(self):
parser.add_argument('--locals', dest='tb_locals',
action='store_true',
help='Show local variables in tracebacks')
parser.add_argument('--list-tests',
action='store_true',
help="Only display the list of test names, "
"don't run tests")
if self.failfast is None:
parser.add_argument('-f', '--failfast', dest='failfast',
action='store_true',
Expand Down Expand Up @@ -231,7 +237,9 @@ def _do_discovery(self, argv, Loader=None):
def runTests(self):
if self.catchbreak:
installHandler()
if self.testRunner is None:
if self.list_tests:
self.testRunner = runner.TextListTestRunner
elif self.testRunner is None:
self.testRunner = runner.TextTestRunner
if isinstance(self.testRunner, type):
try:
Expand Down
30 changes: 30 additions & 0 deletions Lib/unittest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import warnings

from . import result
from .case import TestCase
from .suite import TestSuite
from .signals import registerResult

__unittest = True
Expand Down Expand Up @@ -219,3 +221,31 @@ def run(self, test):
else:
self.stream.write("\n")
return result


class TextListTestRunner(TextTestRunner):
"""A test runner class that only displays test names, don't run them."""
resultclass = TextTestResult

def list_tests(self, test_list, test):
if isinstance(test, TestSuite):
for subtest in test:
self.list_tests(test_list, subtest)
elif isinstance(test, TestCase):
name = []
cls = test.__class__
if cls.__module__ != "__main__":
name.append(cls.__module__)
name.append(cls.__name__)
name.append(test._testMethodName)
test_list.append('.'.join(name))
else:
raise ValueError("unknown test object: %s" % type(test))

def run(self, test):
test_list = []
self.list_tests(test_list, test)
test_list.sort()
for name in test_list:
self.stream.writeln(name)
return self._makeResult()
1 change: 1 addition & 0 deletions Lib/unittest/test/test_break.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ def __init__(self, catchbreak):
self.testRunner = FakeRunner
self.test = test
self.result = None
self.list_tests = False

p = Program(False)
p.runTests()
Expand Down
1 change: 1 addition & 0 deletions Lib/unittest/test/test_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ class InitialisableProgram(unittest.TestProgram):
module = '__main__'
progName = 'test'
test = 'test'
list_tests = False
def __init__(self, *args):
pass

Expand Down