175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen"""Unittest main program"""
275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenimport sys
475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenimport os
575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenimport types
675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenfrom unittest2 import loader, runner
875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chentry:
975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    from unittest2.signals import installHandler
1075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenexcept ImportError:
1175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    installHandler = None
1275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
1375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen__unittest = True
1475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
1575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenFAILFAST     = "  -f, --failfast   Stop on first failure\n"
1675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenCATCHBREAK   = "  -c, --catch      Catch control-C and display results\n"
1775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenBUFFEROUTPUT = "  -b, --buffer     Buffer stdout and stderr during test runs\n"
1875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
1975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenUSAGE_AS_MAIN = """\
2075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenUsage: %(progName)s [options] [tests]
2175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
2275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenOptions:
2375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  -h, --help       Show this message
2475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  -v, --verbose    Verbose output
2575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  -q, --quiet      Minimal output
2675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen%(failfast)s%(catchbreak)s%(buffer)s
2775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenExamples:
2875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  %(progName)s test_module                       - run tests from test_module
2975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  %(progName)s test_module.TestClass             - run tests from
3075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                                                   test_module.TestClass
3175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  %(progName)s test_module.TestClass.test_method - run specified test method
3275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
3375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen[tests] can be a list of any number of test modules, classes and test
3475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenmethods.
3575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
3675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenAlternative Usage: %(progName)s discover [options]
3775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
3875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenOptions:
3975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  -v, --verbose    Verbose output
4075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen%(failfast)s%(catchbreak)s%(buffer)s  -s directory     Directory to start discovery ('.' default)
4175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  -p pattern       Pattern to match test files ('test*.py' default)
4275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  -t directory     Top level directory of project (default to
4375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                   start directory)
4475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
4575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenFor test discovery all test modules must be importable from the top
4675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenlevel directory of the project.
4775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen"""
4875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
4975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenUSAGE_FROM_MODULE = """\
5075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenUsage: %(progName)s [options] [test] [...]
5175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
5275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenOptions:
5375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  -h, --help       Show this message
5475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  -v, --verbose    Verbose output
5575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  -q, --quiet      Minimal output
5675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen%(failfast)s%(catchbreak)s%(buffer)s
5775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenExamples:
5875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  %(progName)s                               - run default set of tests
5975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  %(progName)s MyTestSuite                   - run suite 'MyTestSuite'
6075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  %(progName)s MyTestCase.testSomething      - run MyTestCase.testSomething
6175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen  %(progName)s MyTestCase                    - run all 'test*' test methods
6275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                                               in MyTestCase
6375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen"""
6475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
6575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
6675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenclass TestProgram(object):
6775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    """A command-line program that runs a set of tests; this is primarily
6875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen       for making test modules conveniently executable.
6975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    """
7075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    USAGE = USAGE_FROM_MODULE
7175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
7275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    # defaults for testing
7375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    failfast = catchbreak = buffer = progName = None
7475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
7575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def __init__(self, module='__main__', defaultTest=None,
7675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                 argv=None, testRunner=None,
7775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                 testLoader=loader.defaultTestLoader, exit=True,
7875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                 verbosity=1, failfast=None, catchbreak=None, buffer=None):
7975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if isinstance(module, basestring):
8075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.module = __import__(module)
8175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            for part in module.split('.')[1:]:
8275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                self.module = getattr(self.module, part)
8375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        else:
8475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.module = module
8575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if argv is None:
8675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            argv = sys.argv
8775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
8875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.exit = exit
8975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.verbosity = verbosity
9075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.failfast = failfast
9175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.catchbreak = catchbreak
9275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.buffer = buffer
9375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.defaultTest = defaultTest
9475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.testRunner = testRunner
9575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.testLoader = testLoader
9675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.progName = os.path.basename(argv[0])
9775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.parseArgs(argv)
9875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.runTests()
9975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
10075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def usageExit(self, msg=None):
10175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if msg:
10275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            print msg
10375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        usage = {'progName': self.progName, 'catchbreak': '', 'failfast': '',
10475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                 'buffer': ''}
10575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.failfast != False:
10675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            usage['failfast'] = FAILFAST
10775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.catchbreak != False and installHandler is not None:
10875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            usage['catchbreak'] = CATCHBREAK
10975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.buffer != False:
11075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            usage['buffer'] = BUFFEROUTPUT
11175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        print self.USAGE % usage
11275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        sys.exit(2)
11375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
11475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def parseArgs(self, argv):
11575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if len(argv) > 1 and argv[1].lower() == 'discover':
11675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self._do_discovery(argv[2:])
11775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            return
11875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
11975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        import getopt
12075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer']
12175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        try:
12275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            options, args = getopt.getopt(argv[1:], 'hHvqfcb', long_opts)
12375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            for opt, value in options:
12475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if opt in ('-h','-H','--help'):
12575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    self.usageExit()
12675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if opt in ('-q','--quiet'):
12775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    self.verbosity = 0
12875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if opt in ('-v','--verbose'):
12975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    self.verbosity = 2
13075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if opt in ('-f','--failfast'):
13175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    if self.failfast is None:
13275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                        self.failfast = True
13375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    # Should this raise an exception if -f is not valid?
13475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if opt in ('-c','--catch'):
13575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    if self.catchbreak is None and installHandler is not None:
13675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                        self.catchbreak = True
13775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    # Should this raise an exception if -c is not valid?
13875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if opt in ('-b','--buffer'):
13975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    if self.buffer is None:
14075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                        self.buffer = True
14175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    # Should this raise an exception if -b is not valid?
14275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            if len(args) == 0 and self.defaultTest is None:
14375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                # createTests will load tests from self.module
14475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                self.testNames = None
14575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            elif len(args) > 0:
14675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                self.testNames = args
14775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if __name__ == '__main__':
14875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    # to support python -m unittest ...
14975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    self.module = None
15075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            else:
15175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                self.testNames = (self.defaultTest,)
15275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.createTests()
15375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        except getopt.error, msg:
15475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.usageExit(msg)
15575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
15675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def createTests(self):
15775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.testNames is None:
15875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.test = self.testLoader.loadTestsFromModule(self.module)
15975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        else:
16075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.test = self.testLoader.loadTestsFromNames(self.testNames,
16175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                                                           self.module)
16275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
16375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def _do_discovery(self, argv, Loader=loader.TestLoader):
16475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        # handle command line args for test discovery
16575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.progName = '%s discover' % self.progName
16675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        import optparse
16775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        parser = optparse.OptionParser()
16875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        parser.prog = self.progName
16975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        parser.add_option('-v', '--verbose', dest='verbose', default=False,
17075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                          help='Verbose output', action='store_true')
17175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.failfast != False:
17275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            parser.add_option('-f', '--failfast', dest='failfast', default=False,
17375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                              help='Stop on first fail or error',
17475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                              action='store_true')
17575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.catchbreak != False and installHandler is not None:
17675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            parser.add_option('-c', '--catch', dest='catchbreak', default=False,
17775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                              help='Catch ctrl-C and display results so far',
17875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                              action='store_true')
17975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.buffer != False:
18075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            parser.add_option('-b', '--buffer', dest='buffer', default=False,
18175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                              help='Buffer stdout and stderr during tests',
18275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                              action='store_true')
18375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        parser.add_option('-s', '--start-directory', dest='start', default='.',
18475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                          help="Directory to start discovery ('.' default)")
18575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        parser.add_option('-p', '--pattern', dest='pattern', default='test*.py',
18675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                          help="Pattern to match tests ('test*.py' default)")
18775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        parser.add_option('-t', '--top-level-directory', dest='top', default=None,
18875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                          help='Top level directory of project (defaults to start directory)')
18975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
19075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        options, args = parser.parse_args(argv)
19175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if len(args) > 3:
19275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.usageExit()
19375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
19475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        for name, value in zip(('start', 'pattern', 'top'), args):
19575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            setattr(options, name, value)
19675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
19775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        # only set options from the parsing here
19875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        # if they weren't set explicitly in the constructor
19975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.failfast is None:
20075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.failfast = options.failfast
20175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.catchbreak is None and installHandler is not None:
20275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.catchbreak = options.catchbreak
20375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.buffer is None:
20475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.buffer = options.buffer
20575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
20675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if options.verbose:
20775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.verbosity = 2
20875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
20975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        start_dir = options.start
21075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        pattern = options.pattern
21175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        top_level_dir = options.top
21275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
21375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        loader = Loader()
21475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.test = loader.discover(start_dir, pattern, top_level_dir)
21575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
21675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def runTests(self):
21775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.catchbreak:
21875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            installHandler()
21975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.testRunner is None:
22075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.testRunner = runner.TextTestRunner
22175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if isinstance(self.testRunner, (type, types.ClassType)):
22275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            try:
22375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                testRunner = self.testRunner(verbosity=self.verbosity,
22475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                                             failfast=self.failfast,
22575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                                             buffer=self.buffer)
22675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            except TypeError:
22775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                # didn't accept the verbosity, buffer or failfast arguments
22875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                testRunner = self.testRunner()
22975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        else:
23075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            # it is assumed to be a TestRunner instance
23175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            testRunner = self.testRunner
23275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.result = testRunner.run(self.test)
23375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.exit:
23475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            sys.exit(not self.result.wasSuccessful())
23575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
23675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenmain = TestProgram
23775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
23875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chendef main_():
23975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    TestProgram.USAGE = USAGE_AS_MAIN
24075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    main(module=None)
24175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
242