Home | History | Annotate | Download | only in test
      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