test_program.py 13 KB

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