Ticket #2675: timeouts-rev2-2675.patch

File timeouts-rev2-2675.patch, 9.2 KB (added by djfroofy, 3 years ago)

This patch addresses concerns raised in last review by spiv.

  • twisted/topfiles/2675.bugfix

     
     1Allow setting default timeout for trial TestCases via -t/--timeout argument to trial. 
  • twisted/scripts/trial.py

     
    1313from twisted import plugin 
    1414from twisted.python.util import spewer 
    1515from twisted.python.compat import set 
    16 from twisted.trial import runner, itrial, reporter 
     16from twisted.trial import runner, itrial, reporter, util 
    1717 
    1818 
    1919# Yea, this is stupid.  Leave it for for command-line compatibility for a 
     
    128128         'Path to use as working directory for tests.'], 
    129129        ['reporter', None, 'verbose', 
    130130         'The reporter to use for this test run.  See --help-reporters for ' 
    131          'more info.']] 
     131         'more info.'], 
     132        ['timeout', 't', util.DEFAULT_TIMEOUT_DURATION, 
     133         'The default timeout in seconds. You can use the value 0 for no ' 
     134         'timeout but this may cause your tests to hang.', float]] 
    132135 
    133136    zsh_actions = {"tbformat":"(plain emacs cgitb)", 
    134137                   "reporter":_zshReporterAction} 
     
    338341        print 'Running tests shuffled with seed %d\n' % config['random'] 
    339342    if not config['until-failure']: 
    340343        loader.suiteFactory = runner.DestructiveTestSuite 
     344    if config['timeout']: 
     345        loader.suiteFactory.defaultTimeout = config['timeout'] 
    341346    return loader 
    342347 
    343348 
  • twisted/trial/test/test_script.py

     
    480480        self.assertDeprecationWarning(self.config.opt_extra, 
    481481                                      self.flushWarnings([self.test_xDeprecation])) 
    482482 
     483 
     484class DefaultTimeoutTests(unittest.TestCase): 
     485    """ 
     486    Test for C{--timeout} argument. 
     487    """ 
     488 
     489    def test_defaultTimeoutSetOnSuiteFactory(self): 
     490        """ 
     491        Test C{--timeout} argument results in defaultTimeout being set 
     492        on the loaded C{suiteFactory}. 
     493        """ 
     494        options = trial.Options() 
     495        options.parseOptions(["--timeout", "20"]) 
     496        loader = trial._getLoader(options) 
     497        self.assertEquals(loader.suiteFactory.defaultTimeout, 20) 
     498 
  • twisted/trial/test/test_runner.py

     
    490490        self.assertEqual(['runcall'], debugger._calls) 
    491491 
    492492 
     493    def test_defaultTimeout(self): 
     494        """ 
     495        The integral value passed by --timeout argument to trial is used 
     496        to set the default timeout value on loaded tests that do not 
     497        explicitly set a timeout otherwise. 
     498        """ 
     499        self.parseOptions(['--timeout', '25', 'twisted.trial.test.sample']) 
     500        myRunner = self.getRunner() 
     501        suite = trial._getSuite(self.config) 
     502        # Gather up non-stdlib unittests (i.e. trial.unittest.TestCases  
     503        # instances only) 
     504        tests = [test for test in unittest._iterateTests(suite) 
     505                 if isinstance(test, unittest.TestCase)] 
     506        firstTest = tests[0] 
     507        firstTest.timeout = 1 
     508        secondTest = tests[1] 
     509        secondTest.timeout = 2 
     510        # Remaining tests in suit that do not explicity set a timeout 
     511        tests = tests[2:] 
     512        result = myRunner.run(suite) 
     513        self.assertEquals(firstTest.timeout, 1) 
     514        self.assertEquals(secondTest.timeout, 2) 
     515        for test in tests: 
     516            self.assertEquals(test.timeout, 25) 
     517        self.flushWarnings() 
    493518 
    494519class RemoveSafelyTests(unittest.TestCase): 
    495520    """ 
  • twisted/trial/test/test_deferred.py

     
    6060 
    6161 
    6262class TestNeverFire(unittest.TestCase): 
    63     def setUp(self): 
    64         self._oldTimeout = util.DEFAULT_TIMEOUT_DURATION 
    65         util.DEFAULT_TIMEOUT_DURATION = 0.1 
    6663 
    67     def tearDown(self): 
    68         util.DEFAULT_TIMEOUT_DURATION = self._oldTimeout 
    69  
    7064    def _loadSuite(self, klass): 
    7165        loader = runner.TestLoader() 
    7266        r = reporter.TestResult() 
    7367        s = loader.loadClass(klass) 
     68        s.defaultTimeout = 0.1 
    7469        return r, s 
    7570 
    7671    def test_setUp(self): 
     
    8580        self.failUnless(result.errors[0][1].check(defer.TimeoutError)) 
    8681 
    8782 
     83 
    8884class TestTester(unittest.TestCase): 
    8985    def getTest(self, name): 
    9086        raise NotImplementedError("must override me") 
  • twisted/trial/runner.py

     
    149149            if result.shouldStop: 
    150150                break 
    151151            test = self._tests.pop(0) 
     152            if self.defaultTimeout: 
     153                if isinstance(test, unittest.TestCase): 
     154                    self._suggestTimeout(test, self.defaultTimeout) 
    152155            test(result) 
    153156        return result 
    154157 
  • twisted/trial/unittest.py

     
    710710                    result.addExpectedFailure(self, f, todo) 
    711711                else: 
    712712                    result.addError(self, f) 
    713         onTimeout = utils.suppressWarnings( 
    714             onTimeout, util.suppress(category=DeprecationWarning)) 
    715713        method = getattr(self, methodName) 
    716714        d = defer.maybeDeferred(utils.runWithWarningsSuppressed, 
    717715                                self.getSuppress(), method) 
    718         call = reactor.callLater(timeout, onTimeout, d) 
    719         d.addBoth(lambda x : call.active() and call.cancel() or x) 
     716        # If a timeout is not explicitly given we let the test hang 
     717        if timeout is not None: 
     718            onTimeout = utils.suppressWarnings( 
     719                onTimeout, util.suppress(category=DeprecationWarning)) 
     720            call = reactor.callLater(timeout, onTimeout, d) 
     721            d.addBoth(lambda x : call.active() and call.cancel() or x) 
    720722        return d 
    721723 
    722724    def shortDescription(self): 
     
    11651167        """ 
    11661168        Returns the timeout value set on this test. Checks on the instance 
    11671169        first, then the class, then the module, then packages. As soon as it 
    1168         finds something with a C{timeout} attribute, returns that. Returns 
    1169         L{util.DEFAULT_TIMEOUT_DURATION} if it cannot find anything. See 
    1170         L{TestCase} docstring for more details. 
     1170        finds something with a C{timeout} attribute, returns that. If it 
     1171        cannot find any value for timeout, then C{None} is returned which may 
     1172        result in a test hang. 
    11711173        """ 
    1172         timeout =  util.acquireAttribute(self._parents, 'timeout', 
    1173                                          util.DEFAULT_TIMEOUT_DURATION) 
     1174        timeout =  util.acquireAttribute(self._parents, 'timeout', None) 
     1175        if timeout is None: 
     1176            return None 
    11741177        try: 
    11751178            return float(timeout) 
    11761179        except (ValueError, TypeError): 
     
    11801183            # both do this. 
    11811184            warnings.warn("'timeout' attribute needs to be a number.", 
    11821185                          category=DeprecationWarning) 
    1183             return util.DEFAULT_TIMEOUT_DURATION 
    11841186 
    11851187    def getSuppress(self): 
    11861188        """ 
     
    13841386class TestSuite(pyunit.TestSuite): 
    13851387    """ 
    13861388    Extend the standard library's C{TestSuite} with support for the visitor 
    1387     pattern and a consistently overrideable C{run} method. 
     1389    pattern and a consistently overrideable C{run} method. This also supplies 
     1390    C{defaultTimeout} which can be applied to instances of 
     1391    L{twisted.trial.unittest.TestCase}. 
    13881392    """ 
    13891393 
    13901394    visit = suiteVisit 
     1395    defaultTimeout = None 
    13911396 
    13921397    def __call__(self, result): 
    13931398        return self.run(result) 
     
    14021407        for test in self._tests: 
    14031408            if result.shouldStop: 
    14041409                break 
     1410            if self.defaultTimeout: 
     1411                if isinstance(test, TestCase): 
     1412                    self._suggestTimeout(test, self.defaultTimeout) 
    14051413            test(result) 
    14061414        return result 
    14071415 
    14081416 
     1417    def _suggestTimeout(self, test, timeout): 
     1418        """ 
     1419        Suggest the timeout for the L{TestCase}. If C{timeout} is C{None} 
     1420        this method is a noop. Also, if the current C{TestCase} already 
     1421        supplies a non-C{None} timeout value, this method is a noop. Otherwise 
     1422        the given C{timeout} will be set on this test instance. 
     1423        """ 
     1424        if timeout is None: 
     1425            return 
     1426        testTimeout = util.acquireAttribute(test._parents, 'timeout', None) 
     1427        if testTimeout is None: 
     1428            test.timeout = timeout 
    14091429 
     1430 
    14101431class TestDecorator(components.proxyForInterface(itrial.ITestCase, 
    14111432                                                 "_originalTest")): 
    14121433    """