Coverage for /pythoncovmergedfiles/medio/medio/usr/lib/python3.9/unittest/main.py: 18%

160 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-23 06:43 +0000

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 

12MAIN_EXAMPLES = """\ 

13Examples: 

14 %(prog)s test_module - run tests from test_module 

15 %(prog)s module.TestClass - run tests from module.TestClass 

16 %(prog)s module.Class.test_method - run specified test method 

17 %(prog)s path/to/test_file.py - run tests from test_file.py 

18""" 

19 

20MODULE_EXAMPLES = """\ 

21Examples: 

22 %(prog)s - run default set of tests 

23 %(prog)s MyTestSuite - run suite 'MyTestSuite' 

24 %(prog)s MyTestCase.testSomething - run MyTestCase.testSomething 

25 %(prog)s MyTestCase - run all 'test*' test methods 

26 in MyTestCase 

27""" 

28 

29def _convert_name(name): 

30 # on Linux / Mac OS X 'foo.PY' is not importable, but on 

31 # Windows it is. Simpler to do a case insensitive match 

32 # a better check would be to check that the name is a 

33 # valid Python module name. 

34 if os.path.isfile(name) and name.lower().endswith('.py'): 

35 if os.path.isabs(name): 

36 rel_path = os.path.relpath(name, os.getcwd()) 

37 if os.path.isabs(rel_path) or rel_path.startswith(os.pardir): 

38 return name 

39 name = rel_path 

40 # on Windows both '\' and '/' are used as path 

41 # separators. Better to replace both than rely on os.path.sep 

42 return name[:-3].replace('\\', '.').replace('/', '.') 

43 return name 

44 

45def _convert_names(names): 

46 return [_convert_name(name) for name in names] 

47 

48 

49def _convert_select_pattern(pattern): 

50 if not '*' in pattern: 

51 pattern = '*%s*' % pattern 

52 return pattern 

53 

54 

55class TestProgram(object): 

56 """A command-line program that runs a set of tests; this is primarily 

57 for making test modules conveniently executable. 

58 """ 

59 # defaults for testing 

60 module=None 

61 verbosity = 1 

62 failfast = catchbreak = buffer = progName = warnings = testNamePatterns = None 

63 _discovery_parser = None 

64 

65 def __init__(self, module='__main__', defaultTest=None, argv=None, 

66 testRunner=None, testLoader=loader.defaultTestLoader, 

67 exit=True, verbosity=1, failfast=None, catchbreak=None, 

68 buffer=None, warnings=None, *, tb_locals=False): 

69 if isinstance(module, str): 

70 self.module = __import__(module) 

71 for part in module.split('.')[1:]: 

72 self.module = getattr(self.module, part) 

73 else: 

74 self.module = module 

75 if argv is None: 

76 argv = sys.argv 

77 

78 self.exit = exit 

79 self.failfast = failfast 

80 self.catchbreak = catchbreak 

81 self.verbosity = verbosity 

82 self.buffer = buffer 

83 self.tb_locals = tb_locals 

84 if warnings is None and not sys.warnoptions: 

85 # even if DeprecationWarnings are ignored by default 

86 # print them anyway unless other warnings settings are 

87 # specified by the warnings arg or the -W python flag 

88 self.warnings = 'default' 

89 else: 

90 # here self.warnings is set either to the value passed 

91 # to the warnings args or to None. 

92 # If the user didn't pass a value self.warnings will 

93 # be None. This means that the behavior is unchanged 

94 # and depends on the values passed to -W. 

95 self.warnings = warnings 

96 self.defaultTest = defaultTest 

97 self.testRunner = testRunner 

98 self.testLoader = testLoader 

99 self.progName = os.path.basename(argv[0]) 

100 self.parseArgs(argv) 

101 self.runTests() 

102 

103 def usageExit(self, msg=None): 

104 if msg: 

105 print(msg) 

106 if self._discovery_parser is None: 

107 self._initArgParsers() 

108 self._print_help() 

109 sys.exit(2) 

110 

111 def _print_help(self, *args, **kwargs): 

112 if self.module is None: 

113 print(self._main_parser.format_help()) 

114 print(MAIN_EXAMPLES % {'prog': self.progName}) 

115 self._discovery_parser.print_help() 

116 else: 

117 print(self._main_parser.format_help()) 

118 print(MODULE_EXAMPLES % {'prog': self.progName}) 

119 

120 def parseArgs(self, argv): 

121 self._initArgParsers() 

122 if self.module is None: 

123 if len(argv) > 1 and argv[1].lower() == 'discover': 

124 self._do_discovery(argv[2:]) 

125 return 

126 self._main_parser.parse_args(argv[1:], self) 

127 if not self.tests: 

128 # this allows "python -m unittest -v" to still work for 

129 # test discovery. 

130 self._do_discovery([]) 

131 return 

132 else: 

133 self._main_parser.parse_args(argv[1:], self) 

134 

135 if self.tests: 

136 self.testNames = _convert_names(self.tests) 

137 if __name__ == '__main__': 

138 # to support python -m unittest ... 

139 self.module = None 

140 elif self.defaultTest is None: 

141 # createTests will load tests from self.module 

142 self.testNames = None 

143 elif isinstance(self.defaultTest, str): 

144 self.testNames = (self.defaultTest,) 

145 else: 

146 self.testNames = list(self.defaultTest) 

147 self.createTests() 

148 

149 def createTests(self, from_discovery=False, Loader=None): 

150 if self.testNamePatterns: 

151 self.testLoader.testNamePatterns = self.testNamePatterns 

152 if from_discovery: 

153 loader = self.testLoader if Loader is None else Loader() 

154 self.test = loader.discover(self.start, self.pattern, self.top) 

155 elif self.testNames is None: 

156 self.test = self.testLoader.loadTestsFromModule(self.module) 

157 else: 

158 self.test = self.testLoader.loadTestsFromNames(self.testNames, 

159 self.module) 

160 

161 def _initArgParsers(self): 

162 parent_parser = self._getParentArgParser() 

163 self._main_parser = self._getMainArgParser(parent_parser) 

164 self._discovery_parser = self._getDiscoveryArgParser(parent_parser) 

165 

166 def _getParentArgParser(self): 

167 parser = argparse.ArgumentParser(add_help=False) 

168 

169 parser.add_argument('-v', '--verbose', dest='verbosity', 

170 action='store_const', const=2, 

171 help='Verbose output') 

172 parser.add_argument('-q', '--quiet', dest='verbosity', 

173 action='store_const', const=0, 

174 help='Quiet output') 

175 parser.add_argument('--locals', dest='tb_locals', 

176 action='store_true', 

177 help='Show local variables in tracebacks') 

178 if self.failfast is None: 

179 parser.add_argument('-f', '--failfast', dest='failfast', 

180 action='store_true', 

181 help='Stop on first fail or error') 

182 self.failfast = False 

183 if self.catchbreak is None: 

184 parser.add_argument('-c', '--catch', dest='catchbreak', 

185 action='store_true', 

186 help='Catch Ctrl-C and display results so far') 

187 self.catchbreak = False 

188 if self.buffer is None: 

189 parser.add_argument('-b', '--buffer', dest='buffer', 

190 action='store_true', 

191 help='Buffer stdout and stderr during tests') 

192 self.buffer = False 

193 if self.testNamePatterns is None: 

194 parser.add_argument('-k', dest='testNamePatterns', 

195 action='append', type=_convert_select_pattern, 

196 help='Only run tests which match the given substring') 

197 self.testNamePatterns = [] 

198 

199 return parser 

200 

201 def _getMainArgParser(self, parent): 

202 parser = argparse.ArgumentParser(parents=[parent]) 

203 parser.prog = self.progName 

204 parser.print_help = self._print_help 

205 

206 parser.add_argument('tests', nargs='*', 

207 help='a list of any number of test modules, ' 

208 'classes and test methods.') 

209 

210 return parser 

211 

212 def _getDiscoveryArgParser(self, parent): 

213 parser = argparse.ArgumentParser(parents=[parent]) 

214 parser.prog = '%s discover' % self.progName 

215 parser.epilog = ('For test discovery all test modules must be ' 

216 'importable from the top level directory of the ' 

217 'project.') 

218 

219 parser.add_argument('-s', '--start-directory', dest='start', 

220 help="Directory to start discovery ('.' default)") 

221 parser.add_argument('-p', '--pattern', dest='pattern', 

222 help="Pattern to match tests ('test*.py' default)") 

223 parser.add_argument('-t', '--top-level-directory', dest='top', 

224 help='Top level directory of project (defaults to ' 

225 'start directory)') 

226 for arg in ('start', 'pattern', 'top'): 

227 parser.add_argument(arg, nargs='?', 

228 default=argparse.SUPPRESS, 

229 help=argparse.SUPPRESS) 

230 

231 return parser 

232 

233 def _do_discovery(self, argv, Loader=None): 

234 self.start = '.' 

235 self.pattern = 'test*.py' 

236 self.top = None 

237 if argv is not None: 

238 # handle command line args for test discovery 

239 if self._discovery_parser is None: 

240 # for testing 

241 self._initArgParsers() 

242 self._discovery_parser.parse_args(argv, self) 

243 

244 self.createTests(from_discovery=True, Loader=Loader) 

245 

246 def runTests(self): 

247 if self.catchbreak: 

248 installHandler() 

249 if self.testRunner is None: 

250 self.testRunner = runner.TextTestRunner 

251 if isinstance(self.testRunner, type): 

252 try: 

253 try: 

254 testRunner = self.testRunner(verbosity=self.verbosity, 

255 failfast=self.failfast, 

256 buffer=self.buffer, 

257 warnings=self.warnings, 

258 tb_locals=self.tb_locals) 

259 except TypeError: 

260 # didn't accept the tb_locals 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 sys.exit(not self.result.wasSuccessful()) 

274 

275main = TestProgram