1import io 2 3import os 4import sys 5import subprocess 6from test import support 7import unittest 8import unittest.test 9 10 11class Test_TestProgram(unittest.TestCase): 12 13 def test_discovery_from_dotted_path(self): 14 loader = unittest.TestLoader() 15 16 tests = [self] 17 expectedPath = os.path.abspath(os.path.dirname(unittest.test.__file__)) 18 19 self.wasRun = False 20 def _find_tests(start_dir, pattern): 21 self.wasRun = True 22 self.assertEqual(start_dir, expectedPath) 23 return tests 24 loader._find_tests = _find_tests 25 suite = loader.discover('unittest.test') 26 self.assertTrue(self.wasRun) 27 self.assertEqual(suite._tests, tests) 28 29 # Horrible white box test 30 def testNoExit(self): 31 result = object() 32 test = object() 33 34 class FakeRunner(object): 35 def run(self, test): 36 self.test = test 37 return result 38 39 runner = FakeRunner() 40 41 oldParseArgs = unittest.TestProgram.parseArgs 42 def restoreParseArgs(): 43 unittest.TestProgram.parseArgs = oldParseArgs 44 unittest.TestProgram.parseArgs = lambda *args: None 45 self.addCleanup(restoreParseArgs) 46 47 def removeTest(): 48 del unittest.TestProgram.test 49 unittest.TestProgram.test = test 50 self.addCleanup(removeTest) 51 52 program = unittest.TestProgram(testRunner=runner, exit=False, verbosity=2) 53 54 self.assertEqual(program.result, result) 55 self.assertEqual(runner.test, test) 56 self.assertEqual(program.verbosity, 2) 57 58 class FooBar(unittest.TestCase): 59 def testPass(self): 60 assert True 61 def testFail(self): 62 assert False 63 64 class FooBarLoader(unittest.TestLoader): 65 """Test loader that returns a suite containing FooBar.""" 66 def loadTestsFromModule(self, module): 67 return self.suiteClass( 68 [self.loadTestsFromTestCase(Test_TestProgram.FooBar)]) 69 70 def loadTestsFromNames(self, names, module): 71 return self.suiteClass( 72 [self.loadTestsFromTestCase(Test_TestProgram.FooBar)]) 73 74 def test_defaultTest_with_string(self): 75 class FakeRunner(object): 76 def run(self, test): 77 self.test = test 78 return True 79 80 old_argv = sys.argv 81 sys.argv = ['faketest'] 82 runner = FakeRunner() 83 program = unittest.TestProgram(testRunner=runner, exit=False, 84 defaultTest='unittest.test', 85 testLoader=self.FooBarLoader()) 86 sys.argv = old_argv 87 self.assertEqual(('unittest.test',), program.testNames) 88 89 def test_defaultTest_with_iterable(self): 90 class FakeRunner(object): 91 def run(self, test): 92 self.test = test 93 return True 94 95 old_argv = sys.argv 96 sys.argv = ['faketest'] 97 runner = FakeRunner() 98 program = unittest.TestProgram( 99 testRunner=runner, exit=False, 100 defaultTest=['unittest.test', 'unittest.test2'], 101 testLoader=self.FooBarLoader()) 102 sys.argv = old_argv 103 self.assertEqual(['unittest.test', 'unittest.test2'], 104 program.testNames) 105 106 def test_NonExit(self): 107 program = unittest.main(exit=False, 108 argv=["foobar"], 109 testRunner=unittest.TextTestRunner(stream=io.StringIO()), 110 testLoader=self.FooBarLoader()) 111 self.assertTrue(hasattr(program, 'result')) 112 113 114 def test_Exit(self): 115 self.assertRaises( 116 SystemExit, 117 unittest.main, 118 argv=["foobar"], 119 testRunner=unittest.TextTestRunner(stream=io.StringIO()), 120 exit=True, 121 testLoader=self.FooBarLoader()) 122 123 124 def test_ExitAsDefault(self): 125 self.assertRaises( 126 SystemExit, 127 unittest.main, 128 argv=["foobar"], 129 testRunner=unittest.TextTestRunner(stream=io.StringIO()), 130 testLoader=self.FooBarLoader()) 131 132 133class InitialisableProgram(unittest.TestProgram): 134 exit = False 135 result = None 136 verbosity = 1 137 defaultTest = None 138 tb_locals = False 139 testRunner = None 140 testLoader = unittest.defaultTestLoader 141 module = '__main__' 142 progName = 'test' 143 test = 'test' 144 def __init__(self, *args): 145 pass 146 147RESULT = object() 148 149class FakeRunner(object): 150 initArgs = None 151 test = None 152 raiseError = 0 153 154 def __init__(self, **kwargs): 155 FakeRunner.initArgs = kwargs 156 if FakeRunner.raiseError: 157 FakeRunner.raiseError -= 1 158 raise TypeError 159 160 def run(self, test): 161 FakeRunner.test = test 162 return RESULT 163 164 165class TestCommandLineArgs(unittest.TestCase): 166 167 def setUp(self): 168 self.program = InitialisableProgram() 169 self.program.createTests = lambda: None 170 FakeRunner.initArgs = None 171 FakeRunner.test = None 172 FakeRunner.raiseError = 0 173 174 def testVerbosity(self): 175 program = self.program 176 177 for opt in '-q', '--quiet': 178 program.verbosity = 1 179 program.parseArgs([None, opt]) 180 self.assertEqual(program.verbosity, 0) 181 182 for opt in '-v', '--verbose': 183 program.verbosity = 1 184 program.parseArgs([None, opt]) 185 self.assertEqual(program.verbosity, 2) 186 187 def testBufferCatchFailfast(self): 188 program = self.program 189 for arg, attr in (('buffer', 'buffer'), ('failfast', 'failfast'), 190 ('catch', 'catchbreak')): 191 192 setattr(program, attr, None) 193 program.parseArgs([None]) 194 self.assertIs(getattr(program, attr), False) 195 196 false = [] 197 setattr(program, attr, false) 198 program.parseArgs([None]) 199 self.assertIs(getattr(program, attr), false) 200 201 true = [42] 202 setattr(program, attr, true) 203 program.parseArgs([None]) 204 self.assertIs(getattr(program, attr), true) 205 206 short_opt = '-%s' % arg[0] 207 long_opt = '--%s' % arg 208 for opt in short_opt, long_opt: 209 setattr(program, attr, None) 210 program.parseArgs([None, opt]) 211 self.assertIs(getattr(program, attr), True) 212 213 setattr(program, attr, False) 214 with support.captured_stderr() as stderr, \ 215 self.assertRaises(SystemExit) as cm: 216 program.parseArgs([None, opt]) 217 self.assertEqual(cm.exception.args, (2,)) 218 219 setattr(program, attr, True) 220 with support.captured_stderr() as stderr, \ 221 self.assertRaises(SystemExit) as cm: 222 program.parseArgs([None, opt]) 223 self.assertEqual(cm.exception.args, (2,)) 224 225 def testWarning(self): 226 """Test the warnings argument""" 227 # see #10535 228 class FakeTP(unittest.TestProgram): 229 def parseArgs(self, *args, **kw): pass 230 def runTests(self, *args, **kw): pass 231 warnoptions = sys.warnoptions[:] 232 try: 233 sys.warnoptions[:] = [] 234 # no warn options, no arg -> default 235 self.assertEqual(FakeTP().warnings, 'default') 236 # no warn options, w/ arg -> arg value 237 self.assertEqual(FakeTP(warnings='ignore').warnings, 'ignore') 238 sys.warnoptions[:] = ['somevalue'] 239 # warn options, no arg -> None 240 # warn options, w/ arg -> arg value 241 self.assertEqual(FakeTP().warnings, None) 242 self.assertEqual(FakeTP(warnings='ignore').warnings, 'ignore') 243 finally: 244 sys.warnoptions[:] = warnoptions 245 246 def testRunTestsRunnerClass(self): 247 program = self.program 248 249 program.testRunner = FakeRunner 250 program.verbosity = 'verbosity' 251 program.failfast = 'failfast' 252 program.buffer = 'buffer' 253 program.warnings = 'warnings' 254 255 program.runTests() 256 257 self.assertEqual(FakeRunner.initArgs, {'verbosity': 'verbosity', 258 'failfast': 'failfast', 259 'buffer': 'buffer', 260 'tb_locals': False, 261 'warnings': 'warnings'}) 262 self.assertEqual(FakeRunner.test, 'test') 263 self.assertIs(program.result, RESULT) 264 265 def testRunTestsRunnerInstance(self): 266 program = self.program 267 268 program.testRunner = FakeRunner() 269 FakeRunner.initArgs = None 270 271 program.runTests() 272 273 # A new FakeRunner should not have been instantiated 274 self.assertIsNone(FakeRunner.initArgs) 275 276 self.assertEqual(FakeRunner.test, 'test') 277 self.assertIs(program.result, RESULT) 278 279 def test_locals(self): 280 program = self.program 281 282 program.testRunner = FakeRunner 283 program.parseArgs([None, '--locals']) 284 self.assertEqual(True, program.tb_locals) 285 program.runTests() 286 self.assertEqual(FakeRunner.initArgs, {'buffer': False, 287 'failfast': False, 288 'tb_locals': True, 289 'verbosity': 1, 290 'warnings': None}) 291 292 def testRunTestsOldRunnerClass(self): 293 program = self.program 294 295 # Two TypeErrors are needed to fall all the way back to old-style 296 # runners - one to fail tb_locals, one to fail buffer etc. 297 FakeRunner.raiseError = 2 298 program.testRunner = FakeRunner 299 program.verbosity = 'verbosity' 300 program.failfast = 'failfast' 301 program.buffer = 'buffer' 302 program.test = 'test' 303 304 program.runTests() 305 306 # If initialising raises a type error it should be retried 307 # without the new keyword arguments 308 self.assertEqual(FakeRunner.initArgs, {}) 309 self.assertEqual(FakeRunner.test, 'test') 310 self.assertIs(program.result, RESULT) 311 312 def testCatchBreakInstallsHandler(self): 313 module = sys.modules['unittest.main'] 314 original = module.installHandler 315 def restore(): 316 module.installHandler = original 317 self.addCleanup(restore) 318 319 self.installed = False 320 def fakeInstallHandler(): 321 self.installed = True 322 module.installHandler = fakeInstallHandler 323 324 program = self.program 325 program.catchbreak = True 326 327 program.testRunner = FakeRunner 328 329 program.runTests() 330 self.assertTrue(self.installed) 331 332 def _patch_isfile(self, names, exists=True): 333 def isfile(path): 334 return path in names 335 original = os.path.isfile 336 os.path.isfile = isfile 337 def restore(): 338 os.path.isfile = original 339 self.addCleanup(restore) 340 341 342 def testParseArgsFileNames(self): 343 # running tests with filenames instead of module names 344 program = self.program 345 argv = ['progname', 'foo.py', 'bar.Py', 'baz.PY', 'wing.txt'] 346 self._patch_isfile(argv) 347 348 program.createTests = lambda: None 349 program.parseArgs(argv) 350 351 # note that 'wing.txt' is not a Python file so the name should 352 # *not* be converted to a module name 353 expected = ['foo', 'bar', 'baz', 'wing.txt'] 354 self.assertEqual(program.testNames, expected) 355 356 357 def testParseArgsFilePaths(self): 358 program = self.program 359 argv = ['progname', 'foo/bar/baz.py', 'green\\red.py'] 360 self._patch_isfile(argv) 361 362 program.createTests = lambda: None 363 program.parseArgs(argv) 364 365 expected = ['foo.bar.baz', 'green.red'] 366 self.assertEqual(program.testNames, expected) 367 368 369 def testParseArgsNonExistentFiles(self): 370 program = self.program 371 argv = ['progname', 'foo/bar/baz.py', 'green\\red.py'] 372 self._patch_isfile([]) 373 374 program.createTests = lambda: None 375 program.parseArgs(argv) 376 377 self.assertEqual(program.testNames, argv[1:]) 378 379 def testParseArgsAbsolutePathsThatCanBeConverted(self): 380 cur_dir = os.getcwd() 381 program = self.program 382 def _join(name): 383 return os.path.join(cur_dir, name) 384 argv = ['progname', _join('foo/bar/baz.py'), _join('green\\red.py')] 385 self._patch_isfile(argv) 386 387 program.createTests = lambda: None 388 program.parseArgs(argv) 389 390 expected = ['foo.bar.baz', 'green.red'] 391 self.assertEqual(program.testNames, expected) 392 393 def testParseArgsAbsolutePathsThatCannotBeConverted(self): 394 program = self.program 395 # even on Windows '/...' is considered absolute by os.path.abspath 396 argv = ['progname', '/foo/bar/baz.py', '/green/red.py'] 397 self._patch_isfile(argv) 398 399 program.createTests = lambda: None 400 program.parseArgs(argv) 401 402 self.assertEqual(program.testNames, argv[1:]) 403 404 # it may be better to use platform specific functions to normalise paths 405 # rather than accepting '.PY' and '\' as file separator on Linux / Mac 406 # it would also be better to check that a filename is a valid module 407 # identifier (we have a regex for this in loader.py) 408 # for invalid filenames should we raise a useful error rather than 409 # leaving the current error message (import of filename fails) in place? 410 411 def testParseArgsSelectedTestNames(self): 412 program = self.program 413 argv = ['progname', '-k', 'foo', '-k', 'bar', '-k', '*pat*'] 414 415 program.createTests = lambda: None 416 program.parseArgs(argv) 417 418 self.assertEqual(program.testNamePatterns, ['*foo*', '*bar*', '*pat*']) 419 420 def testSelectedTestNamesFunctionalTest(self): 421 def run_unittest(args): 422 p = subprocess.Popen([sys.executable, '-m', 'unittest'] + args, 423 stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, cwd=os.path.dirname(__file__)) 424 with p: 425 _, stderr = p.communicate() 426 return stderr.decode() 427 428 t = '_test_warnings' 429 self.assertIn('Ran 7 tests', run_unittest([t])) 430 self.assertIn('Ran 7 tests', run_unittest(['-k', 'TestWarnings', t])) 431 self.assertIn('Ran 7 tests', run_unittest(['discover', '-p', '*_test*', '-k', 'TestWarnings'])) 432 self.assertIn('Ran 2 tests', run_unittest(['-k', 'f', t])) 433 self.assertIn('Ran 7 tests', run_unittest(['-k', 't', t])) 434 self.assertIn('Ran 3 tests', run_unittest(['-k', '*t', t])) 435 self.assertIn('Ran 7 tests', run_unittest(['-k', '*test_warnings.*Warning*', t])) 436 self.assertIn('Ran 1 test', run_unittest(['-k', '*test_warnings.*warning*', t])) 437 438 439if __name__ == '__main__': 440 unittest.main() 441