Issue #7632: Fix a serious wrong output bug for string -> float conversion.
[python.git] / Lib / unittest / main.py
blobbd758e056fab57840cdff9c9fad28c2bd30817e2
1 """Unittest main program"""
3 import sys
4 import os
5 import types
7 from . import loader, runner
10 USAGE_AS_MAIN = """\
11 Usage: %(progName)s [options] [tests]
13 Options:
14 -h, --help Show this message
15 -v, --verbose Verbose output
16 -q, --quiet Minimal output
18 Examples:
19 %(progName)s test_module - run tests from test_module
20 %(progName)s test_module.TestClass - run tests from
21 test_module.TestClass
22 %(progName)s test_module.TestClass.test_method - run specified test method
24 [tests] can be a list of any number of test modules, classes and test
25 methods.
27 Alternative Usage: %(progName)s discover [options]
29 Options:
30 -v, --verbose Verbose output
31 -s directory Directory to start discovery ('.' default)
32 -p pattern Pattern to match test files ('test*.py' default)
33 -t directory Top level directory of project (default to
34 start directory)
36 For test discovery all test modules must be importable from the top
37 level directory of the project.
38 """
40 USAGE_FROM_MODULE = """\
41 Usage: %(progName)s [options] [test] [...]
43 Options:
44 -h, --help Show this message
45 -v, --verbose Verbose output
46 -q, --quiet Minimal output
48 Examples:
49 %(progName)s - run default set of tests
50 %(progName)s MyTestSuite - run suite 'MyTestSuite'
51 %(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
52 %(progName)s MyTestCase - run all 'test*' test methods
53 in MyTestCase
54 """
56 if __name__ == '__main__':
57 USAGE = USAGE_AS_MAIN
58 else:
59 USAGE = USAGE_FROM_MODULE
62 class TestProgram(object):
63 """A command-line program that runs a set of tests; this is primarily
64 for making test modules conveniently executable.
65 """
66 USAGE = USAGE
67 def __init__(self, module='__main__', defaultTest=None,
68 argv=None, testRunner=None,
69 testLoader=loader.defaultTestLoader, exit=True,
70 verbosity=1):
71 if isinstance(module, basestring):
72 self.module = __import__(module)
73 for part in module.split('.')[1:]:
74 self.module = getattr(self.module, part)
75 else:
76 self.module = module
77 if argv is None:
78 argv = sys.argv
80 self.exit = exit
81 self.verbosity = verbosity
82 self.defaultTest = defaultTest
83 self.testRunner = testRunner
84 self.testLoader = testLoader
85 self.progName = os.path.basename(argv[0])
86 self.parseArgs(argv)
87 self.runTests()
89 def usageExit(self, msg=None):
90 if msg:
91 print msg
92 print self.USAGE % self.__dict__
93 sys.exit(2)
95 def parseArgs(self, argv):
96 if len(argv) > 1 and argv[1].lower() == 'discover':
97 self._do_discovery(argv[2:])
98 return
100 import getopt
101 long_opts = ['help','verbose','quiet']
102 try:
103 options, args = getopt.getopt(argv[1:], 'hHvq', long_opts)
104 for opt, value in options:
105 if opt in ('-h','-H','--help'):
106 self.usageExit()
107 if opt in ('-q','--quiet'):
108 self.verbosity = 0
109 if opt in ('-v','--verbose'):
110 self.verbosity = 2
111 if len(args) == 0 and self.defaultTest is None:
112 # createTests will load tests from self.module
113 self.testNames = None
114 elif len(args) > 0:
115 self.testNames = args
116 if __name__ == '__main__':
117 # to support python -m unittest ...
118 self.module = None
119 else:
120 self.testNames = (self.defaultTest,)
121 self.createTests()
122 except getopt.error, msg:
123 self.usageExit(msg)
125 def createTests(self):
126 if self.testNames is None:
127 self.test = self.testLoader.loadTestsFromModule(self.module)
128 else:
129 self.test = self.testLoader.loadTestsFromNames(self.testNames,
130 self.module)
132 def _do_discovery(self, argv, Loader=loader.TestLoader):
133 # handle command line args for test discovery
134 import optparse
135 parser = optparse.OptionParser()
136 parser.add_option('-v', '--verbose', dest='verbose', default=False,
137 help='Verbose output', action='store_true')
138 parser.add_option('-s', '--start-directory', dest='start', default='.',
139 help="Directory to start discovery ('.' default)")
140 parser.add_option('-p', '--pattern', dest='pattern', default='test*.py',
141 help="Pattern to match tests ('test*.py' default)")
142 parser.add_option('-t', '--top-level-directory', dest='top', default=None,
143 help='Top level directory of project (defaults to start directory)')
145 options, args = parser.parse_args(argv)
146 if len(args) > 3:
147 self.usageExit()
149 for name, value in zip(('start', 'pattern', 'top'), args):
150 setattr(options, name, value)
152 if options.verbose:
153 self.verbosity = 2
155 start_dir = options.start
156 pattern = options.pattern
157 top_level_dir = options.top
159 loader = Loader()
160 self.test = loader.discover(start_dir, pattern, top_level_dir)
162 def runTests(self):
163 if self.testRunner is None:
164 self.testRunner = runner.TextTestRunner
165 if isinstance(self.testRunner, (type, types.ClassType)):
166 try:
167 testRunner = self.testRunner(verbosity=self.verbosity)
168 except TypeError:
169 # didn't accept the verbosity argument
170 testRunner = self.testRunner()
171 else:
172 # it is assumed to be a TestRunner instance
173 testRunner = self.testRunner
174 self.result = testRunner.run(self.test)
175 if self.exit:
176 sys.exit(not self.result.wasSuccessful())
178 main = TestProgram