test_program.py 15 KB

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