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