Ticket #2675: timeouts-rev2-2675.patch

File timeouts-rev2-2675.patch, 9.2 KB (added by djfroofy, 5 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    """