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