unittest.main
Unittest main program
1"""Unittest main program""" 2 3import sys 4import argparse 5import os 6 7from . import loader, runner 8from .signals import installHandler 9 10__unittest = True 11_NO_TESTS_EXITCODE = 5 12 13MAIN_EXAMPLES = """\ 14Examples: 15 %(prog)s test_module - run tests from test_module 16 %(prog)s module.TestClass - run tests from module.TestClass 17 %(prog)s module.Class.test_method - run specified test method 18 %(prog)s path/to/test_file.py - run tests from test_file.py 19""" 20 21MODULE_EXAMPLES = """\ 22Examples: 23 %(prog)s - run default set of tests 24 %(prog)s MyTestSuite - run suite 'MyTestSuite' 25 %(prog)s MyTestCase.testSomething - run MyTestCase.testSomething 26 %(prog)s MyTestCase - run all 'test*' test methods 27 in MyTestCase 28""" 29 30def _convert_name(name): 31 # on Linux / Mac OS X 'foo.PY' is not importable, but on 32 # Windows it is. Simpler to do a case insensitive match 33 # a better check would be to check that the name is a 34 # valid Python module name. 35 if os.path.isfile(name) and name.lower().endswith('.py'): 36 if os.path.isabs(name): 37 rel_path = os.path.relpath(name, os.getcwd()) 38 if os.path.isabs(rel_path) or rel_path.startswith(os.pardir): 39 return name 40 name = rel_path 41 # on Windows both '\' and '/' are used as path 42 # separators. Better to replace both than rely on os.path.sep 43 return os.path.normpath(name)[:-3].replace('\\', '.').replace('/', '.') 44 return name 45 46def _convert_names(names): 47 return [_convert_name(name) for name in names] 48 49 50def _convert_select_pattern(pattern): 51 if not '*' in pattern: 52 pattern = '*%s*' % pattern 53 return pattern 54 55 56class TestProgram(object): 57 """A command-line program that runs a set of tests; this is primarily 58 for making test modules conveniently executable. 59 """ 60 # defaults for testing 61 module=None 62 verbosity = 1 63 failfast = catchbreak = buffer = progName = warnings = testNamePatterns = None 64 _discovery_parser = None 65 66 def __init__(self, module='__main__', defaultTest=None, argv=None, 67 testRunner=None, testLoader=loader.defaultTestLoader, 68 exit=True, verbosity=1, failfast=None, catchbreak=None, 69 buffer=None, warnings=None, *, tb_locals=False, 70 durations=None): 71 if isinstance(module, str): 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 79 80 self.exit = exit 81 self.failfast = failfast 82 self.catchbreak = catchbreak 83 self.verbosity = verbosity 84 self.buffer = buffer 85 self.tb_locals = tb_locals 86 self.durations = durations 87 if warnings is None and not sys.warnoptions: 88 # even if DeprecationWarnings are ignored by default 89 # print them anyway unless other warnings settings are 90 # specified by the warnings arg or the -W python flag 91 self.warnings = 'default' 92 else: 93 # here self.warnings is set either to the value passed 94 # to the warnings args or to None. 95 # If the user didn't pass a value self.warnings will 96 # be None. This means that the behavior is unchanged 97 # and depends on the values passed to -W. 98 self.warnings = warnings 99 self.defaultTest = defaultTest 100 self.testRunner = testRunner 101 self.testLoader = testLoader 102 self.progName = os.path.basename(argv[0]) 103 self.parseArgs(argv) 104 self.runTests() 105 106 def _print_help(self, *args, **kwargs): 107 if self.module is None: 108 print(self._main_parser.format_help()) 109 print(MAIN_EXAMPLES % {'prog': self.progName}) 110 self._discovery_parser.print_help() 111 else: 112 print(self._main_parser.format_help()) 113 print(MODULE_EXAMPLES % {'prog': self.progName}) 114 115 def parseArgs(self, argv): 116 self._initArgParsers() 117 if self.module is None: 118 if len(argv) > 1 and argv[1].lower() == 'discover': 119 self._do_discovery(argv[2:]) 120 return 121 self._main_parser.parse_args(argv[1:], self) 122 if not self.tests: 123 # this allows "python -m unittest -v" to still work for 124 # test discovery. 125 self._do_discovery([]) 126 return 127 else: 128 self._main_parser.parse_args(argv[1:], self) 129 130 if self.tests: 131 self.testNames = _convert_names(self.tests) 132 if __name__ == '__main__': 133 # to support python -m unittest ... 134 self.module = None 135 elif self.defaultTest is None: 136 # createTests will load tests from self.module 137 self.testNames = None 138 elif isinstance(self.defaultTest, str): 139 self.testNames = (self.defaultTest,) 140 else: 141 self.testNames = list(self.defaultTest) 142 self.createTests() 143 144 def createTests(self, from_discovery=False, Loader=None): 145 if self.testNamePatterns: 146 self.testLoader.testNamePatterns = self.testNamePatterns 147 if from_discovery: 148 loader = self.testLoader if Loader is None else Loader() 149 self.test = loader.discover(self.start, self.pattern, self.top) 150 elif self.testNames is None: 151 self.test = self.testLoader.loadTestsFromModule(self.module) 152 else: 153 self.test = self.testLoader.loadTestsFromNames(self.testNames, 154 self.module) 155 156 def _initArgParsers(self): 157 parent_parser = self._getParentArgParser() 158 self._main_parser = self._getMainArgParser(parent_parser) 159 self._discovery_parser = self._getDiscoveryArgParser(parent_parser) 160 161 def _getParentArgParser(self): 162 parser = argparse.ArgumentParser(add_help=False) 163 164 parser.add_argument('-v', '--verbose', dest='verbosity', 165 action='store_const', const=2, 166 help='Verbose output') 167 parser.add_argument('-q', '--quiet', dest='verbosity', 168 action='store_const', const=0, 169 help='Quiet output') 170 parser.add_argument('--locals', dest='tb_locals', 171 action='store_true', 172 help='Show local variables in tracebacks') 173 parser.add_argument('--durations', dest='durations', type=int, 174 default=None, metavar="N", 175 help='Show the N slowest test cases (N=0 for all)') 176 if self.failfast is None: 177 parser.add_argument('-f', '--failfast', dest='failfast', 178 action='store_true', 179 help='Stop on first fail or error') 180 self.failfast = False 181 if self.catchbreak is None: 182 parser.add_argument('-c', '--catch', dest='catchbreak', 183 action='store_true', 184 help='Catch Ctrl-C and display results so far') 185 self.catchbreak = False 186 if self.buffer is None: 187 parser.add_argument('-b', '--buffer', dest='buffer', 188 action='store_true', 189 help='Buffer stdout and stderr during tests') 190 self.buffer = False 191 if self.testNamePatterns is None: 192 parser.add_argument('-k', dest='testNamePatterns', 193 action='append', type=_convert_select_pattern, 194 help='Only run tests which match the given substring') 195 self.testNamePatterns = [] 196 197 return parser 198 199 def _getMainArgParser(self, parent): 200 parser = argparse.ArgumentParser(parents=[parent]) 201 parser.prog = self.progName 202 parser.print_help = self._print_help 203 204 parser.add_argument('tests', nargs='*', 205 help='a list of any number of test modules, ' 206 'classes and test methods.') 207 208 return parser 209 210 def _getDiscoveryArgParser(self, parent): 211 parser = argparse.ArgumentParser(parents=[parent]) 212 parser.prog = '%s discover' % self.progName 213 parser.epilog = ('For test discovery all test modules must be ' 214 'importable from the top level directory of the ' 215 'project.') 216 217 parser.add_argument('-s', '--start-directory', dest='start', 218 help="Directory to start discovery ('.' default)") 219 parser.add_argument('-p', '--pattern', dest='pattern', 220 help="Pattern to match tests ('test*.py' default)") 221 parser.add_argument('-t', '--top-level-directory', dest='top', 222 help='Top level directory of project (defaults to ' 223 'start directory)') 224 for arg in ('start', 'pattern', 'top'): 225 parser.add_argument(arg, nargs='?', 226 default=argparse.SUPPRESS, 227 help=argparse.SUPPRESS) 228 229 return parser 230 231 def _do_discovery(self, argv, Loader=None): 232 self.start = '.' 233 self.pattern = 'test*.py' 234 self.top = None 235 if argv is not None: 236 # handle command line args for test discovery 237 if self._discovery_parser is None: 238 # for testing 239 self._initArgParsers() 240 self._discovery_parser.parse_args(argv, self) 241 242 self.createTests(from_discovery=True, Loader=Loader) 243 244 def runTests(self): 245 if self.catchbreak: 246 installHandler() 247 if self.testRunner is None: 248 self.testRunner = runner.TextTestRunner 249 if isinstance(self.testRunner, type): 250 try: 251 try: 252 testRunner = self.testRunner(verbosity=self.verbosity, 253 failfast=self.failfast, 254 buffer=self.buffer, 255 warnings=self.warnings, 256 tb_locals=self.tb_locals, 257 durations=self.durations) 258 except TypeError: 259 # didn't accept the tb_locals or durations argument 260 testRunner = self.testRunner(verbosity=self.verbosity, 261 failfast=self.failfast, 262 buffer=self.buffer, 263 warnings=self.warnings) 264 except TypeError: 265 # didn't accept the verbosity, buffer or failfast arguments 266 testRunner = self.testRunner() 267 else: 268 # it is assumed to be a TestRunner instance 269 testRunner = self.testRunner 270 self.result = testRunner.run(self.test) 271 if self.exit: 272 if self.result.testsRun == 0 and len(self.result.skipped) == 0: 273 sys.exit(_NO_TESTS_EXITCODE) 274 elif self.result.wasSuccessful(): 275 sys.exit(0) 276 else: 277 sys.exit(1) 278 279 280main = TestProgram
MAIN_EXAMPLES =
'Examples:\n %(prog)s test_module - run tests from test_module\n %(prog)s module.TestClass - run tests from module.TestClass\n %(prog)s module.Class.test_method - run specified test method\n %(prog)s path/to/test_file.py - run tests from test_file.py\n'
MODULE_EXAMPLES =
"Examples:\n %(prog)s - run default set of tests\n %(prog)s MyTestSuite - run suite 'MyTestSuite'\n %(prog)s MyTestCase.testSomething - run MyTestCase.testSomething\n %(prog)s MyTestCase - run all 'test*' test methods\n in MyTestCase\n"
class
TestProgram:
57class TestProgram(object): 58 """A command-line program that runs a set of tests; this is primarily 59 for making test modules conveniently executable. 60 """ 61 # defaults for testing 62 module=None 63 verbosity = 1 64 failfast = catchbreak = buffer = progName = warnings = testNamePatterns = None 65 _discovery_parser = None 66 67 def __init__(self, module='__main__', defaultTest=None, argv=None, 68 testRunner=None, testLoader=loader.defaultTestLoader, 69 exit=True, verbosity=1, failfast=None, catchbreak=None, 70 buffer=None, warnings=None, *, tb_locals=False, 71 durations=None): 72 if isinstance(module, str): 73 self.module = __import__(module) 74 for part in module.split('.')[1:]: 75 self.module = getattr(self.module, part) 76 else: 77 self.module = module 78 if argv is None: 79 argv = sys.argv 80 81 self.exit = exit 82 self.failfast = failfast 83 self.catchbreak = catchbreak 84 self.verbosity = verbosity 85 self.buffer = buffer 86 self.tb_locals = tb_locals 87 self.durations = durations 88 if warnings is None and not sys.warnoptions: 89 # even if DeprecationWarnings are ignored by default 90 # print them anyway unless other warnings settings are 91 # specified by the warnings arg or the -W python flag 92 self.warnings = 'default' 93 else: 94 # here self.warnings is set either to the value passed 95 # to the warnings args or to None. 96 # If the user didn't pass a value self.warnings will 97 # be None. This means that the behavior is unchanged 98 # and depends on the values passed to -W. 99 self.warnings = warnings 100 self.defaultTest = defaultTest 101 self.testRunner = testRunner 102 self.testLoader = testLoader 103 self.progName = os.path.basename(argv[0]) 104 self.parseArgs(argv) 105 self.runTests() 106 107 def _print_help(self, *args, **kwargs): 108 if self.module is None: 109 print(self._main_parser.format_help()) 110 print(MAIN_EXAMPLES % {'prog': self.progName}) 111 self._discovery_parser.print_help() 112 else: 113 print(self._main_parser.format_help()) 114 print(MODULE_EXAMPLES % {'prog': self.progName}) 115 116 def parseArgs(self, argv): 117 self._initArgParsers() 118 if self.module is None: 119 if len(argv) > 1 and argv[1].lower() == 'discover': 120 self._do_discovery(argv[2:]) 121 return 122 self._main_parser.parse_args(argv[1:], self) 123 if not self.tests: 124 # this allows "python -m unittest -v" to still work for 125 # test discovery. 126 self._do_discovery([]) 127 return 128 else: 129 self._main_parser.parse_args(argv[1:], self) 130 131 if self.tests: 132 self.testNames = _convert_names(self.tests) 133 if __name__ == '__main__': 134 # to support python -m unittest ... 135 self.module = None 136 elif self.defaultTest is None: 137 # createTests will load tests from self.module 138 self.testNames = None 139 elif isinstance(self.defaultTest, str): 140 self.testNames = (self.defaultTest,) 141 else: 142 self.testNames = list(self.defaultTest) 143 self.createTests() 144 145 def createTests(self, from_discovery=False, Loader=None): 146 if self.testNamePatterns: 147 self.testLoader.testNamePatterns = self.testNamePatterns 148 if from_discovery: 149 loader = self.testLoader if Loader is None else Loader() 150 self.test = loader.discover(self.start, self.pattern, self.top) 151 elif self.testNames is None: 152 self.test = self.testLoader.loadTestsFromModule(self.module) 153 else: 154 self.test = self.testLoader.loadTestsFromNames(self.testNames, 155 self.module) 156 157 def _initArgParsers(self): 158 parent_parser = self._getParentArgParser() 159 self._main_parser = self._getMainArgParser(parent_parser) 160 self._discovery_parser = self._getDiscoveryArgParser(parent_parser) 161 162 def _getParentArgParser(self): 163 parser = argparse.ArgumentParser(add_help=False) 164 165 parser.add_argument('-v', '--verbose', dest='verbosity', 166 action='store_const', const=2, 167 help='Verbose output') 168 parser.add_argument('-q', '--quiet', dest='verbosity', 169 action='store_const', const=0, 170 help='Quiet output') 171 parser.add_argument('--locals', dest='tb_locals', 172 action='store_true', 173 help='Show local variables in tracebacks') 174 parser.add_argument('--durations', dest='durations', type=int, 175 default=None, metavar="N", 176 help='Show the N slowest test cases (N=0 for all)') 177 if self.failfast is None: 178 parser.add_argument('-f', '--failfast', dest='failfast', 179 action='store_true', 180 help='Stop on first fail or error') 181 self.failfast = False 182 if self.catchbreak is None: 183 parser.add_argument('-c', '--catch', dest='catchbreak', 184 action='store_true', 185 help='Catch Ctrl-C and display results so far') 186 self.catchbreak = False 187 if self.buffer is None: 188 parser.add_argument('-b', '--buffer', dest='buffer', 189 action='store_true', 190 help='Buffer stdout and stderr during tests') 191 self.buffer = False 192 if self.testNamePatterns is None: 193 parser.add_argument('-k', dest='testNamePatterns', 194 action='append', type=_convert_select_pattern, 195 help='Only run tests which match the given substring') 196 self.testNamePatterns = [] 197 198 return parser 199 200 def _getMainArgParser(self, parent): 201 parser = argparse.ArgumentParser(parents=[parent]) 202 parser.prog = self.progName 203 parser.print_help = self._print_help 204 205 parser.add_argument('tests', nargs='*', 206 help='a list of any number of test modules, ' 207 'classes and test methods.') 208 209 return parser 210 211 def _getDiscoveryArgParser(self, parent): 212 parser = argparse.ArgumentParser(parents=[parent]) 213 parser.prog = '%s discover' % self.progName 214 parser.epilog = ('For test discovery all test modules must be ' 215 'importable from the top level directory of the ' 216 'project.') 217 218 parser.add_argument('-s', '--start-directory', dest='start', 219 help="Directory to start discovery ('.' default)") 220 parser.add_argument('-p', '--pattern', dest='pattern', 221 help="Pattern to match tests ('test*.py' default)") 222 parser.add_argument('-t', '--top-level-directory', dest='top', 223 help='Top level directory of project (defaults to ' 224 'start directory)') 225 for arg in ('start', 'pattern', 'top'): 226 parser.add_argument(arg, nargs='?', 227 default=argparse.SUPPRESS, 228 help=argparse.SUPPRESS) 229 230 return parser 231 232 def _do_discovery(self, argv, Loader=None): 233 self.start = '.' 234 self.pattern = 'test*.py' 235 self.top = None 236 if argv is not None: 237 # handle command line args for test discovery 238 if self._discovery_parser is None: 239 # for testing 240 self._initArgParsers() 241 self._discovery_parser.parse_args(argv, self) 242 243 self.createTests(from_discovery=True, Loader=Loader) 244 245 def runTests(self): 246 if self.catchbreak: 247 installHandler() 248 if self.testRunner is None: 249 self.testRunner = runner.TextTestRunner 250 if isinstance(self.testRunner, type): 251 try: 252 try: 253 testRunner = self.testRunner(verbosity=self.verbosity, 254 failfast=self.failfast, 255 buffer=self.buffer, 256 warnings=self.warnings, 257 tb_locals=self.tb_locals, 258 durations=self.durations) 259 except TypeError: 260 # didn't accept the tb_locals or durations argument 261 testRunner = self.testRunner(verbosity=self.verbosity, 262 failfast=self.failfast, 263 buffer=self.buffer, 264 warnings=self.warnings) 265 except TypeError: 266 # didn't accept the verbosity, buffer or failfast arguments 267 testRunner = self.testRunner() 268 else: 269 # it is assumed to be a TestRunner instance 270 testRunner = self.testRunner 271 self.result = testRunner.run(self.test) 272 if self.exit: 273 if self.result.testsRun == 0 and len(self.result.skipped) == 0: 274 sys.exit(_NO_TESTS_EXITCODE) 275 elif self.result.wasSuccessful(): 276 sys.exit(0) 277 else: 278 sys.exit(1)
A command-line program that runs a set of tests; this is primarily for making test modules conveniently executable.
TestProgram( module='__main__', defaultTest=None, argv=None, testRunner=None, testLoader=<unittest.TestLoader object>, exit=True, verbosity=1, failfast=None, catchbreak=None, buffer=None, warnings=None, *, tb_locals=False, durations=None)
67 def __init__(self, module='__main__', defaultTest=None, argv=None, 68 testRunner=None, testLoader=loader.defaultTestLoader, 69 exit=True, verbosity=1, failfast=None, catchbreak=None, 70 buffer=None, warnings=None, *, tb_locals=False, 71 durations=None): 72 if isinstance(module, str): 73 self.module = __import__(module) 74 for part in module.split('.')[1:]: 75 self.module = getattr(self.module, part) 76 else: 77 self.module = module 78 if argv is None: 79 argv = sys.argv 80 81 self.exit = exit 82 self.failfast = failfast 83 self.catchbreak = catchbreak 84 self.verbosity = verbosity 85 self.buffer = buffer 86 self.tb_locals = tb_locals 87 self.durations = durations 88 if warnings is None and not sys.warnoptions: 89 # even if DeprecationWarnings are ignored by default 90 # print them anyway unless other warnings settings are 91 # specified by the warnings arg or the -W python flag 92 self.warnings = 'default' 93 else: 94 # here self.warnings is set either to the value passed 95 # to the warnings args or to None. 96 # If the user didn't pass a value self.warnings will 97 # be None. This means that the behavior is unchanged 98 # and depends on the values passed to -W. 99 self.warnings = warnings 100 self.defaultTest = defaultTest 101 self.testRunner = testRunner 102 self.testLoader = testLoader 103 self.progName = os.path.basename(argv[0]) 104 self.parseArgs(argv) 105 self.runTests()
def
parseArgs(self, argv):
116 def parseArgs(self, argv): 117 self._initArgParsers() 118 if self.module is None: 119 if len(argv) > 1 and argv[1].lower() == 'discover': 120 self._do_discovery(argv[2:]) 121 return 122 self._main_parser.parse_args(argv[1:], self) 123 if not self.tests: 124 # this allows "python -m unittest -v" to still work for 125 # test discovery. 126 self._do_discovery([]) 127 return 128 else: 129 self._main_parser.parse_args(argv[1:], self) 130 131 if self.tests: 132 self.testNames = _convert_names(self.tests) 133 if __name__ == '__main__': 134 # to support python -m unittest ... 135 self.module = None 136 elif self.defaultTest is None: 137 # createTests will load tests from self.module 138 self.testNames = None 139 elif isinstance(self.defaultTest, str): 140 self.testNames = (self.defaultTest,) 141 else: 142 self.testNames = list(self.defaultTest) 143 self.createTests()
def
createTests(self, from_discovery=False, Loader=None):
145 def createTests(self, from_discovery=False, Loader=None): 146 if self.testNamePatterns: 147 self.testLoader.testNamePatterns = self.testNamePatterns 148 if from_discovery: 149 loader = self.testLoader if Loader is None else Loader() 150 self.test = loader.discover(self.start, self.pattern, self.top) 151 elif self.testNames is None: 152 self.test = self.testLoader.loadTestsFromModule(self.module) 153 else: 154 self.test = self.testLoader.loadTestsFromNames(self.testNames, 155 self.module)
def
runTests(self):
245 def runTests(self): 246 if self.catchbreak: 247 installHandler() 248 if self.testRunner is None: 249 self.testRunner = runner.TextTestRunner 250 if isinstance(self.testRunner, type): 251 try: 252 try: 253 testRunner = self.testRunner(verbosity=self.verbosity, 254 failfast=self.failfast, 255 buffer=self.buffer, 256 warnings=self.warnings, 257 tb_locals=self.tb_locals, 258 durations=self.durations) 259 except TypeError: 260 # didn't accept the tb_locals or durations argument 261 testRunner = self.testRunner(verbosity=self.verbosity, 262 failfast=self.failfast, 263 buffer=self.buffer, 264 warnings=self.warnings) 265 except TypeError: 266 # didn't accept the verbosity, buffer or failfast arguments 267 testRunner = self.testRunner() 268 else: 269 # it is assumed to be a TestRunner instance 270 testRunner = self.testRunner 271 self.result = testRunner.run(self.test) 272 if self.exit: 273 if self.result.testsRun == 0 and len(self.result.skipped) == 0: 274 sys.exit(_NO_TESTS_EXITCODE) 275 elif self.result.wasSuccessful(): 276 sys.exit(0) 277 else: 278 sys.exit(1)
main =
<class 'TestProgram'>