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