From 086f30815c0f674326fe78ba83689d0a2a96b8d7 Mon Sep 17 00:00:00 2001 From: Michael Foord Date: Sun, 21 Nov 2010 21:28:01 +0000 Subject: [PATCH] Issue 10470: 'python -m unittest' launches test discovery by default.(If you need to pass options to test discovery the discover subcommand must still be specified explicitly.) --- Doc/library/unittest.rst | 10 ++++++ Lib/unittest/main.py | 3 +- Lib/unittest/test/test_discovery.py | 51 +++++++++++++++++++++-------- Misc/ACKS | 1 + Misc/NEWS | 3 ++ 5 files changed, 54 insertions(+), 14 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index a25fd549f3e..640ed4bc63f 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -208,6 +208,10 @@ You can run tests with more detail (higher verbosity) by passing in the -v flag: python -m unittest -v test_module +When executed without arguments :ref:`unittest-test-discovery` is started:: + + python -m unittest + For a list of all the command-line options:: python -m unittest -h @@ -266,6 +270,12 @@ used from the command line. The basic command-line usage is:: cd project_directory python -m unittest discover +.. note:: + + As a shortcut, ``python -m unittest`` is the equivalent of + ``python -m unittest discover``. If you want to pass arguments to test + discovery the `discover` sub-command must be used explicitly. + The ``discover`` sub-command has the following options: .. program:: unittest discover diff --git a/Lib/unittest/main.py b/Lib/unittest/main.py index 6acff8fdbe2..8473a33795a 100644 --- a/Lib/unittest/main.py +++ b/Lib/unittest/main.py @@ -109,7 +109,8 @@ class TestProgram(object): sys.exit(2) def parseArgs(self, argv): - if len(argv) > 1 and argv[1].lower() == 'discover': + if ((len(argv) > 1 and argv[1].lower() == 'discover') or + (len(argv) == 1 and self.module is None)): self._do_discovery(argv[2:]) return diff --git a/Lib/unittest/test/test_discovery.py b/Lib/unittest/test/test_discovery.py index aa16b1780d4..7c24bf832d5 100644 --- a/Lib/unittest/test/test_discovery.py +++ b/Lib/unittest/test/test_discovery.py @@ -5,6 +5,18 @@ import sys import unittest +class TestableTestProgram(unittest.TestProgram): + module = '__main__' + exit = True + defaultTest = failfast = catchbreak = buffer = None + verbosity = 1 + progName = '' + testRunner = testLoader = None + + def __init__(self): + pass + + class TestDiscovery(unittest.TestCase): # Heavily mocked tests so I can avoid hitting the filesystem @@ -195,8 +207,7 @@ class TestDiscovery(unittest.TestCase): test.test_this_does_not_exist() def test_command_line_handling_parseArgs(self): - # Haha - take that uninstantiable class - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() args = [] def do_discovery(argv): @@ -208,13 +219,27 @@ class TestDiscovery(unittest.TestCase): program.parseArgs(['something', 'discover', 'foo', 'bar']) self.assertEqual(args, ['foo', 'bar']) + def test_command_line_handling_discover_by_default(self): + program = TestableTestProgram() + program.module = None + + args = [] + def do_discovery(argv): + args.extend(argv) + program._do_discovery = do_discovery + program.parseArgs(['something']) + self.assertEqual(args, []) + + program.parseArgs(['something']) + self.assertEqual(args, []) + def test_command_line_handling_do_discovery_too_many_arguments(self): class Stop(Exception): pass def usageExit(): raise Stop - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() program.usageExit = usageExit with self.assertRaises(Stop): @@ -223,7 +248,7 @@ class TestDiscovery(unittest.TestCase): def test_command_line_handling_do_discovery_calls_loader(self): - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() class Loader(object): args = [] @@ -237,49 +262,49 @@ class TestDiscovery(unittest.TestCase): self.assertEqual(Loader.args, [('.', 'test*.py', None)]) Loader.args = [] - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() program._do_discovery(['--verbose'], Loader=Loader) self.assertEqual(program.test, 'tests') self.assertEqual(Loader.args, [('.', 'test*.py', None)]) Loader.args = [] - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() program._do_discovery([], Loader=Loader) self.assertEqual(program.test, 'tests') self.assertEqual(Loader.args, [('.', 'test*.py', None)]) Loader.args = [] - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() program._do_discovery(['fish'], Loader=Loader) self.assertEqual(program.test, 'tests') self.assertEqual(Loader.args, [('fish', 'test*.py', None)]) Loader.args = [] - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() program._do_discovery(['fish', 'eggs'], Loader=Loader) self.assertEqual(program.test, 'tests') self.assertEqual(Loader.args, [('fish', 'eggs', None)]) Loader.args = [] - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() program._do_discovery(['fish', 'eggs', 'ham'], Loader=Loader) self.assertEqual(program.test, 'tests') self.assertEqual(Loader.args, [('fish', 'eggs', 'ham')]) Loader.args = [] - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() program._do_discovery(['-s', 'fish'], Loader=Loader) self.assertEqual(program.test, 'tests') self.assertEqual(Loader.args, [('fish', 'test*.py', None)]) Loader.args = [] - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() program._do_discovery(['-t', 'fish'], Loader=Loader) self.assertEqual(program.test, 'tests') self.assertEqual(Loader.args, [('.', 'test*.py', 'fish')]) Loader.args = [] - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() program._do_discovery(['-p', 'fish'], Loader=Loader) self.assertEqual(program.test, 'tests') self.assertEqual(Loader.args, [('.', 'fish', None)]) @@ -287,7 +312,7 @@ class TestDiscovery(unittest.TestCase): self.assertFalse(program.catchbreak) Loader.args = [] - program = object.__new__(unittest.TestProgram) + program = TestableTestProgram() program._do_discovery(['-p', 'eggs', '-s', 'fish', '-v', '-f', '-c'], Loader=Loader) self.assertEqual(program.test, 'tests') diff --git a/Misc/ACKS b/Misc/ACKS index 99c09a36f1c..aa776b4a9ad 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -695,6 +695,7 @@ Anthony Roach Mark Roberts Jim Robinson Andy Robinson +Mark Roddy Kevin Rodgers Giampaolo Rodola Mike Romberg diff --git a/Misc/NEWS b/Misc/NEWS index e68a9d7df49..f8dab00d2ac 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,9 @@ Core and Builtins Library ------- +- Issue #10470: 'python -m unittest' will now run test discovery by default, + when no extra arguments have been provided. + - Issue #3709: BaseHTTPRequestHandler will buffer the headers and write to output stream only when end_headers is invoked. This is a speedup and an internal optimization. Patch by endian.