Exemplo n.º 1
0
    def __init__(self, reporter, janitor, benchmark=0):
        self.reporter = IReporter(reporter)
        self.janitor = itrial.IJanitor(janitor)
        

        # XXX NO NO NO NO NO NO NO NO NO NO GOD DAMNIT NO YOU CANNOT DO THIS
        # IT IS NOT ALLOWED DO NOT CALL WAIT() ANYWHERE EVER FOR ANY REASON
        # *EVER*
        util.wait(self.reporter.setUpReporter())



        self.benchmark = benchmark
        self.startTime, self.endTime = None, None
        self.numTests = 0
        self.couldNotImport = {}
        self.tests = []
        self.children = []
        if benchmark:
            self._registerBenchmarkAdapters()
Exemplo n.º 2
0
class TestSuite(Timed):
    """This is the main organizing object. The front-end script creates a
    TestSuite, and tells it what modules were requested on the command line.
    It also hands it a reporter. The TestSuite then takes all of the
    packages, modules, classes and methods, and adapts them to ITestRunner
    objects, which it then calls the runTests method on.
    """
    zi.implements(itrial.ITestSuite)
    moduleGlob = 'test_*.py'
    sortTests = 1
    debugger = False
    dryRun = False

    def __init__(self, reporter, janitor, benchmark=0):
        self.reporter = IReporter(reporter)
        self.janitor = itrial.IJanitor(janitor)
        

        # XXX NO NO NO NO NO NO NO NO NO NO GOD DAMNIT NO YOU CANNOT DO THIS
        # IT IS NOT ALLOWED DO NOT CALL WAIT() ANYWHERE EVER FOR ANY REASON
        # *EVER*
        util.wait(self.reporter.setUpReporter())



        self.benchmark = benchmark
        self.startTime, self.endTime = None, None
        self.numTests = 0
        self.couldNotImport = {}
        self.tests = []
        self.children = []
        if benchmark:
            self._registerBenchmarkAdapters()

    def _registerBenchmarkAdapters(self):
        from twisted import trial
        trial.benchmarking = True

    def addMethod(self, method):
        self.tests.append(method)

    def _getMethods(self):
        for runner in self.children:
            for meth in runner.children:
                yield meth
    methods = property(_getMethods)
        
    def addTestClass(self, testClass):
        if ITestCaseFactory.providedBy(testClass):
            self.tests.append(testClass)
        else:
            warnings.warn(("didn't add %s because it does not implement "
                           "ITestCaseFactory" % testClass))

    def addModule(self, module):
        if isinstance(module, types.StringType):
            _dbgPA("addModule: %r" % (module,))
            try:
                module = reflect.namedModule(module)
            except:
                self.couldNotImport[module] = failure.Failure()
                return

        if isinstance(module, types.ModuleType):
            _dbgPA("adding module: %r" % module)
            self.tests.append(module)
        
        if hasattr(module, '__doctests__'):
            vers = sys.version_info[0:2]
            if vers[0] >= 2 and vers[1] >= 3:
                runner = itrial.ITestRunner(getattr(module, '__doctests__'))
                self.tests.append(runner)
            else:
                warnings.warn(("trial's doctest support only works with "
                               "python 2.3 or later, not running doctests"))

    def addDoctest(self, obj):
        # XXX: this is a crap adaptation, ListType is adapted to 
        # ITestRunner by tdoctest.ModuleDocTestsRunner
        # it is crappy crap, awful dreadful crap
        self.tests.append(itrial.ITestRunner([obj]))

    def addPackage(self, package):
        modGlob = os.path.join(os.path.dirname(package.__file__),
                               self.moduleGlob)
        modules = map(reflect.filenameToModuleName, glob.glob(modGlob))
        for module in modules:
            self.addModule(module)

    def _packageRecurse(self, arg, dirname, names):

        # Only recurse into packages
        for ext in 'py', 'so', 'pyd', 'dll':
            if os.path.exists(os.path.join(dirname, os.extsep.join(('__init__', ext)))):
                break
        else:
            return

        testModuleNames = fnmatch.filter(names, self.moduleGlob)
        testModules = [ reflect.filenameToModuleName(opj(dirname, name))
                        for name in testModuleNames ]
        for module in testModules:
            self.addModule(module)

    def addPackageRecursive(self, package):
        packageDir = os.path.dirname(package.__file__)
        os.path.walk(packageDir, self._packageRecurse, None)

    def _getBenchmarkStats(self):
        stat = {}
        for r in self.children:
            for m in r.children:
                stat.update(getattr(m, 'benchmarkStats', {}))
        return stat
    benchmarkStats = property(_getBenchmarkStats)

    ####
    # the root of the ParentAttributeMixin tree
    def getJanitor(self):
        return self.janitor

    def getReporter(self):
        return self.reporter

    def isDebuggingRun(self):
        return self.debugger
    
    def isDryRun(self):
        return self.dryRun
    ####

    def _bail(self):
        from twisted.internet import reactor
        d = defer.Deferred()
        reactor.addSystemEventTrigger('after', 'shutdown', lambda: d.callback(None))
        reactor.fireSystemEvent('shutdown') # radix's suggestion

        treactor = interfaces.IReactorThreads(reactor, None)
        if treactor is not None:
            treactor.suggestThreadPoolSize(0)

        util.wait(d) # so that the shutdown event completes

    def _initLogging(self):
        log.startKeepingErrors()

    def run(self, seed=None):
        self.startTime = time.time()
        tests = self.tests
        if self.sortTests:
            # XXX twisted.python.util.dsu(tests, str)
            tests.sort(lambda x, y: cmp(str(x), str(y)))
        
        self._initLogging()

        # Kick-start things
        from twisted.internet import reactor
        reactor.callLater(0, reactor.crash)
        reactor.run()

        # randomize tests if requested
        r = None
        if seed is not None:
            r = random.Random(seed)
            r.shuffle(tests)
            self.reporter.write('Running tests shuffled with seed %d' % seed)

        try:
            # this is where the test run starts
            # eventually, the suite should call reporter.startSuite() with
            # the predicted number of tests to be run
            try:
                for test in tests:
                    tr = itrial.ITestRunner(test)
                    self.children.append(tr)
                    tr.parent = self

                    try:
                        tr.runTests(randomize=(seed is not None))
                    except KeyboardInterrupt:
                        # KeyboardInterrupts are normal, not a bug in trial.
                        # Just stop the test run, and do the usual reporting.
                        raise
                    except:
                        # Any other exception is problem.  Report it.
                        f = failure.Failure()
                        annoyingBorder = "-!*@&" * 20
                        trialIsBroken = """
\tWHOOP! WHOOP! DANGER WILL ROBINSON! DANGER! WHOOP! WHOOP!
\tcaught exception in TestSuite! \n\n\t\tTRIAL IS BROKEN!\n\n
\t%s""" % ('\n\t'.join(f.getTraceback().split('\n')),)
                        print "\n%s\n%s\n\n%s\n" % \
                              (annoyingBorder, trialIsBroken, annoyingBorder)
            except KeyboardInterrupt:
                log.msg(iface=ITrialDebug, kbd="KEYBOARD INTERRUPT")

            for name, exc in self.couldNotImport.iteritems():
                # XXX: AFAICT this is only used by RemoteJellyReporter
                self.reporter.reportImportError(name, exc)

            if self.benchmark:
                pickle.dump(self.benchmarkStats, file("test.stats", 'wb'))
        finally:
            self.endTime = time.time()

        # hand the reporter the TestSuite to give it access to all information
        # from the test run
        self.reporter.endSuite(self)
        try:
            util.wait(self.reporter.tearDownReporter())
        except:
            t, v, tb = sys.exc_info()
            raise RuntimeError, "your reporter is broken %r" % \
                  (''.join(v),), tb
        self._bail()