summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_unittest/test_program.py
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2022-06-21 08:27:59 (GMT)
committerGitHub <noreply@github.com>2022-06-21 08:27:59 (GMT)
commitc735d545343c3ab002c62596b2fb2cfa4488b0af (patch)
treeadbb76c603493bd734f4dcc9cc4871c74f22fb43 /Lib/test/test_unittest/test_program.py
parentd82e0bfe8b98a122ca443b356d81998c804b686e (diff)
downloadcpython-c735d545343c3ab002c62596b2fb2cfa4488b0af.zip
cpython-c735d545343c3ab002c62596b2fb2cfa4488b0af.tar.gz
cpython-c735d545343c3ab002c62596b2fb2cfa4488b0af.tar.bz2
gh-93839: Move Lib/unttest/test/ to Lib/test/test_unittest/ (#94043)
* Move Lib/unittest/test/ to Lib/test/test_unittest/ * Remove Lib/test/test_unittest.py * Replace unittest.test with test.test_unittest * Remove unittest.load_tests() * Rewrite unittest __init__.py and __main__.py * Update build system, CODEOWNERS, and wasm_assets.py
Diffstat (limited to 'Lib/test/test_unittest/test_program.py')
-rw-r--r--Lib/test/test_unittest/test_program.py477
1 files changed, 477 insertions, 0 deletions
diff --git a/Lib/test/test_unittest/test_program.py b/Lib/test/test_unittest/test_program.py
new file mode 100644
index 0000000..169fc4e
--- /dev/null
+++ b/Lib/test/test_unittest/test_program.py
@@ -0,0 +1,477 @@
+import io
+
+import os
+import sys
+import subprocess
+from test import support
+import unittest
+import test.test_unittest
+from test.test_unittest.test_result import BufferedWriter
+
+
+class Test_TestProgram(unittest.TestCase):
+
+ def test_discovery_from_dotted_path(self):
+ loader = unittest.TestLoader()
+
+ tests = [self]
+ expectedPath = os.path.abspath(os.path.dirname(test.test_unittest.__file__))
+
+ self.wasRun = False
+ def _find_tests(start_dir, pattern):
+ self.wasRun = True
+ self.assertEqual(start_dir, expectedPath)
+ return tests
+ loader._find_tests = _find_tests
+ suite = loader.discover('test.test_unittest')
+ self.assertTrue(self.wasRun)
+ self.assertEqual(suite._tests, tests)
+
+ # Horrible white box test
+ def testNoExit(self):
+ result = object()
+ test = object()
+
+ class FakeRunner(object):
+ def run(self, test):
+ self.test = test
+ return result
+
+ runner = FakeRunner()
+
+ oldParseArgs = unittest.TestProgram.parseArgs
+ def restoreParseArgs():
+ unittest.TestProgram.parseArgs = oldParseArgs
+ unittest.TestProgram.parseArgs = lambda *args: None
+ self.addCleanup(restoreParseArgs)
+
+ def removeTest():
+ del unittest.TestProgram.test
+ unittest.TestProgram.test = test
+ self.addCleanup(removeTest)
+
+ program = unittest.TestProgram(testRunner=runner, exit=False, verbosity=2)
+
+ self.assertEqual(program.result, result)
+ self.assertEqual(runner.test, test)
+ self.assertEqual(program.verbosity, 2)
+
+ class FooBar(unittest.TestCase):
+ def testPass(self):
+ pass
+ def testFail(self):
+ raise AssertionError
+ def testError(self):
+ 1/0
+ @unittest.skip('skipping')
+ def testSkipped(self):
+ raise AssertionError
+ @unittest.expectedFailure
+ def testExpectedFailure(self):
+ raise AssertionError
+ @unittest.expectedFailure
+ def testUnexpectedSuccess(self):
+ pass
+
+ class FooBarLoader(unittest.TestLoader):
+ """Test loader that returns a suite containing FooBar."""
+ def loadTestsFromModule(self, module):
+ return self.suiteClass(
+ [self.loadTestsFromTestCase(Test_TestProgram.FooBar)])
+
+ def loadTestsFromNames(self, names, module):
+ return self.suiteClass(
+ [self.loadTestsFromTestCase(Test_TestProgram.FooBar)])
+
+ def test_defaultTest_with_string(self):
+ class FakeRunner(object):
+ def run(self, test):
+ self.test = test
+ return True
+
+ old_argv = sys.argv
+ sys.argv = ['faketest']
+ runner = FakeRunner()
+ program = unittest.TestProgram(testRunner=runner, exit=False,
+ defaultTest='test.test_unittest',
+ testLoader=self.FooBarLoader())
+ sys.argv = old_argv
+ self.assertEqual(('test.test_unittest',), program.testNames)
+
+ def test_defaultTest_with_iterable(self):
+ class FakeRunner(object):
+ def run(self, test):
+ self.test = test
+ return True
+
+ old_argv = sys.argv
+ sys.argv = ['faketest']
+ runner = FakeRunner()
+ program = unittest.TestProgram(
+ testRunner=runner, exit=False,
+ defaultTest=['test.test_unittest', 'test.test_unittest2'],
+ testLoader=self.FooBarLoader())
+ sys.argv = old_argv
+ self.assertEqual(['test.test_unittest', 'test.test_unittest2'],
+ program.testNames)
+
+ def test_NonExit(self):
+ stream = BufferedWriter()
+ program = unittest.main(exit=False,
+ argv=["foobar"],
+ testRunner=unittest.TextTestRunner(stream=stream),
+ testLoader=self.FooBarLoader())
+ self.assertTrue(hasattr(program, 'result'))
+ out = stream.getvalue()
+ self.assertIn('\nFAIL: testFail ', out)
+ self.assertIn('\nERROR: testError ', out)
+ self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out)
+ expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, '
+ 'expected failures=1, unexpected successes=1)\n')
+ self.assertTrue(out.endswith(expected))
+
+ def test_Exit(self):
+ stream = BufferedWriter()
+ self.assertRaises(
+ SystemExit,
+ unittest.main,
+ argv=["foobar"],
+ testRunner=unittest.TextTestRunner(stream=stream),
+ exit=True,
+ testLoader=self.FooBarLoader())
+ out = stream.getvalue()
+ self.assertIn('\nFAIL: testFail ', out)
+ self.assertIn('\nERROR: testError ', out)
+ self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out)
+ expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, '
+ 'expected failures=1, unexpected successes=1)\n')
+ self.assertTrue(out.endswith(expected))
+
+ def test_ExitAsDefault(self):
+ stream = BufferedWriter()
+ self.assertRaises(
+ SystemExit,
+ unittest.main,
+ argv=["foobar"],
+ testRunner=unittest.TextTestRunner(stream=stream),
+ testLoader=self.FooBarLoader())
+ out = stream.getvalue()
+ self.assertIn('\nFAIL: testFail ', out)
+ self.assertIn('\nERROR: testError ', out)
+ self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out)
+ expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, '
+ 'expected failures=1, unexpected successes=1)\n')
+ self.assertTrue(out.endswith(expected))
+
+
+class InitialisableProgram(unittest.TestProgram):
+ exit = False
+ result = None
+ verbosity = 1
+ defaultTest = None
+ tb_locals = False
+ testRunner = None
+ testLoader = unittest.defaultTestLoader
+ module = '__main__'
+ progName = 'test'
+ test = 'test'
+ def __init__(self, *args):
+ pass
+
+RESULT = object()
+
+class FakeRunner(object):
+ initArgs = None
+ test = None
+ raiseError = 0
+
+ def __init__(self, **kwargs):
+ FakeRunner.initArgs = kwargs
+ if FakeRunner.raiseError:
+ FakeRunner.raiseError -= 1
+ raise TypeError
+
+ def run(self, test):
+ FakeRunner.test = test
+ return RESULT
+
+
+@support.requires_subprocess()
+class TestCommandLineArgs(unittest.TestCase):
+
+ def setUp(self):
+ self.program = InitialisableProgram()
+ self.program.createTests = lambda: None
+ FakeRunner.initArgs = None
+ FakeRunner.test = None
+ FakeRunner.raiseError = 0
+
+ def testVerbosity(self):
+ program = self.program
+
+ for opt in '-q', '--quiet':
+ program.verbosity = 1
+ program.parseArgs([None, opt])
+ self.assertEqual(program.verbosity, 0)
+
+ for opt in '-v', '--verbose':
+ program.verbosity = 1
+ program.parseArgs([None, opt])
+ self.assertEqual(program.verbosity, 2)
+
+ def testBufferCatchFailfast(self):
+ program = self.program
+ for arg, attr in (('buffer', 'buffer'), ('failfast', 'failfast'),
+ ('catch', 'catchbreak')):
+
+ setattr(program, attr, None)
+ program.parseArgs([None])
+ self.assertIs(getattr(program, attr), False)
+
+ false = []
+ setattr(program, attr, false)
+ program.parseArgs([None])
+ self.assertIs(getattr(program, attr), false)
+
+ true = [42]
+ setattr(program, attr, true)
+ program.parseArgs([None])
+ self.assertIs(getattr(program, attr), true)
+
+ short_opt = '-%s' % arg[0]
+ long_opt = '--%s' % arg
+ for opt in short_opt, long_opt:
+ setattr(program, attr, None)
+ program.parseArgs([None, opt])
+ self.assertIs(getattr(program, attr), True)
+
+ setattr(program, attr, False)
+ with support.captured_stderr() as stderr, \
+ self.assertRaises(SystemExit) as cm:
+ program.parseArgs([None, opt])
+ self.assertEqual(cm.exception.args, (2,))
+
+ setattr(program, attr, True)
+ with support.captured_stderr() as stderr, \
+ self.assertRaises(SystemExit) as cm:
+ program.parseArgs([None, opt])
+ self.assertEqual(cm.exception.args, (2,))
+
+ def testWarning(self):
+ """Test the warnings argument"""
+ # see #10535
+ class FakeTP(unittest.TestProgram):
+ def parseArgs(self, *args, **kw): pass
+ def runTests(self, *args, **kw): pass
+ warnoptions = sys.warnoptions[:]
+ try:
+ sys.warnoptions[:] = []
+ # no warn options, no arg -> default
+ self.assertEqual(FakeTP().warnings, 'default')
+ # no warn options, w/ arg -> arg value
+ self.assertEqual(FakeTP(warnings='ignore').warnings, 'ignore')
+ sys.warnoptions[:] = ['somevalue']
+ # warn options, no arg -> None
+ # warn options, w/ arg -> arg value
+ self.assertEqual(FakeTP().warnings, None)
+ self.assertEqual(FakeTP(warnings='ignore').warnings, 'ignore')
+ finally:
+ sys.warnoptions[:] = warnoptions
+
+ def testRunTestsRunnerClass(self):
+ program = self.program
+
+ program.testRunner = FakeRunner
+ program.verbosity = 'verbosity'
+ program.failfast = 'failfast'
+ program.buffer = 'buffer'
+ program.warnings = 'warnings'
+
+ program.runTests()
+
+ self.assertEqual(FakeRunner.initArgs, {'verbosity': 'verbosity',
+ 'failfast': 'failfast',
+ 'buffer': 'buffer',
+ 'tb_locals': False,
+ 'warnings': 'warnings'})
+ self.assertEqual(FakeRunner.test, 'test')
+ self.assertIs(program.result, RESULT)
+
+ def testRunTestsRunnerInstance(self):
+ program = self.program
+
+ program.testRunner = FakeRunner()
+ FakeRunner.initArgs = None
+
+ program.runTests()
+
+ # A new FakeRunner should not have been instantiated
+ self.assertIsNone(FakeRunner.initArgs)
+
+ self.assertEqual(FakeRunner.test, 'test')
+ self.assertIs(program.result, RESULT)
+
+ def test_locals(self):
+ program = self.program
+
+ program.testRunner = FakeRunner
+ program.parseArgs([None, '--locals'])
+ self.assertEqual(True, program.tb_locals)
+ program.runTests()
+ self.assertEqual(FakeRunner.initArgs, {'buffer': False,
+ 'failfast': False,
+ 'tb_locals': True,
+ 'verbosity': 1,
+ 'warnings': None})
+
+ def testRunTestsOldRunnerClass(self):
+ program = self.program
+
+ # Two TypeErrors are needed to fall all the way back to old-style
+ # runners - one to fail tb_locals, one to fail buffer etc.
+ FakeRunner.raiseError = 2
+ program.testRunner = FakeRunner
+ program.verbosity = 'verbosity'
+ program.failfast = 'failfast'
+ program.buffer = 'buffer'
+ program.test = 'test'
+
+ program.runTests()
+
+ # If initialising raises a type error it should be retried
+ # without the new keyword arguments
+ self.assertEqual(FakeRunner.initArgs, {})
+ self.assertEqual(FakeRunner.test, 'test')
+ self.assertIs(program.result, RESULT)
+
+ def testCatchBreakInstallsHandler(self):
+ module = sys.modules['unittest.main']
+ original = module.installHandler
+ def restore():
+ module.installHandler = original
+ self.addCleanup(restore)
+
+ self.installed = False
+ def fakeInstallHandler():
+ self.installed = True
+ module.installHandler = fakeInstallHandler
+
+ program = self.program
+ program.catchbreak = True
+
+ program.testRunner = FakeRunner
+
+ program.runTests()
+ self.assertTrue(self.installed)
+
+ def _patch_isfile(self, names, exists=True):
+ def isfile(path):
+ return path in names
+ original = os.path.isfile
+ os.path.isfile = isfile
+ def restore():
+ os.path.isfile = original
+ self.addCleanup(restore)
+
+
+ def testParseArgsFileNames(self):
+ # running tests with filenames instead of module names
+ program = self.program
+ argv = ['progname', 'foo.py', 'bar.Py', 'baz.PY', 'wing.txt']
+ self._patch_isfile(argv)
+
+ program.createTests = lambda: None
+ program.parseArgs(argv)
+
+ # note that 'wing.txt' is not a Python file so the name should
+ # *not* be converted to a module name
+ expected = ['foo', 'bar', 'baz', 'wing.txt']
+ self.assertEqual(program.testNames, expected)
+
+
+ def testParseArgsFilePaths(self):
+ program = self.program
+ argv = ['progname', 'foo/bar/baz.py', 'green\\red.py']
+ self._patch_isfile(argv)
+
+ program.createTests = lambda: None
+ program.parseArgs(argv)
+
+ expected = ['foo.bar.baz', 'green.red']
+ self.assertEqual(program.testNames, expected)
+
+
+ def testParseArgsNonExistentFiles(self):
+ program = self.program
+ argv = ['progname', 'foo/bar/baz.py', 'green\\red.py']
+ self._patch_isfile([])
+
+ program.createTests = lambda: None
+ program.parseArgs(argv)
+
+ self.assertEqual(program.testNames, argv[1:])
+
+ def testParseArgsAbsolutePathsThatCanBeConverted(self):
+ cur_dir = os.getcwd()
+ program = self.program
+ def _join(name):
+ return os.path.join(cur_dir, name)
+ argv = ['progname', _join('foo/bar/baz.py'), _join('green\\red.py')]
+ self._patch_isfile(argv)
+
+ program.createTests = lambda: None
+ program.parseArgs(argv)
+
+ expected = ['foo.bar.baz', 'green.red']
+ self.assertEqual(program.testNames, expected)
+
+ def testParseArgsAbsolutePathsThatCannotBeConverted(self):
+ program = self.program
+ # even on Windows '/...' is considered absolute by os.path.abspath
+ argv = ['progname', '/foo/bar/baz.py', '/green/red.py']
+ self._patch_isfile(argv)
+
+ program.createTests = lambda: None
+ program.parseArgs(argv)
+
+ self.assertEqual(program.testNames, argv[1:])
+
+ # it may be better to use platform specific functions to normalise paths
+ # rather than accepting '.PY' and '\' as file separator on Linux / Mac
+ # it would also be better to check that a filename is a valid module
+ # identifier (we have a regex for this in loader.py)
+ # for invalid filenames should we raise a useful error rather than
+ # leaving the current error message (import of filename fails) in place?
+
+ def testParseArgsSelectedTestNames(self):
+ program = self.program
+ argv = ['progname', '-k', 'foo', '-k', 'bar', '-k', '*pat*']
+
+ program.createTests = lambda: None
+ program.parseArgs(argv)
+
+ self.assertEqual(program.testNamePatterns, ['*foo*', '*bar*', '*pat*'])
+
+ def testSelectedTestNamesFunctionalTest(self):
+ def run_unittest(args):
+ # Use -E to ignore PYTHONSAFEPATH env var
+ cmd = [sys.executable, '-E', '-m', 'unittest'] + args
+ p = subprocess.Popen(cmd,
+ stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, cwd=os.path.dirname(__file__))
+ with p:
+ _, stderr = p.communicate()
+ return stderr.decode()
+
+ t = '_test_warnings'
+ self.assertIn('Ran 7 tests', run_unittest([t]))
+ self.assertIn('Ran 7 tests', run_unittest(['-k', 'TestWarnings', t]))
+ self.assertIn('Ran 7 tests', run_unittest(['discover', '-p', '*_test*', '-k', 'TestWarnings']))
+ self.assertIn('Ran 2 tests', run_unittest(['-k', 'f', t]))
+ self.assertIn('Ran 7 tests', run_unittest(['-k', 't', t]))
+ self.assertIn('Ran 3 tests', run_unittest(['-k', '*t', t]))
+ self.assertIn('Ran 7 tests', run_unittest(['-k', '*test_warnings.*Warning*', t]))
+ self.assertIn('Ran 1 test', run_unittest(['-k', '*test_warnings.*warning*', t]))
+
+
+if __name__ == '__main__':
+ unittest.main()