annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/unittest/main.py @ 69:33d812a61356

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