test_program.py 16 KB

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