【发布时间】:2010-07-14 20:24:40
【问题描述】:
我有一些 Twisted 代码可以创建多个延迟链。其中一些可能会失败,而没有将它们放回回调链上的 errback。我无法为此代码编写单元测试 - 失败的 Deferred 导致测试代码完成后测试失败。如何为此代码编写通过单元测试?是否期望每个在正常操作中可能失败的 Deferred 都应该在链的末尾有一个 errback 将其放回回调链上?
当 DeferredList 中的 Deferred 失败时也会发生同样的事情,除非我使用 consumeErrors 创建 DeferredList。即使 DeferredList 是使用 fireOnOneErrback 创建的,并且被赋予了一个 errback 并将其放回回调链上,情况也是如此。除了抑制测试失败和错误记录之外,consumeErrors 是否有任何影响?是否应该将每个可能在没有 errback 的情况下失败的 Deferred 都放入 DeferredList?
示例代码的示例测试:
from twisted.trial import unittest
from twisted.internet import defer
def get_dl(**kwargs):
"Return a DeferredList with a failure and any kwargs given."
return defer.DeferredList(
[defer.succeed(True), defer.fail(ValueError()), defer.succeed(True)],
**kwargs)
def two_deferreds():
"Create a failing Deferred, and create and return a succeeding Deferred."
d = defer.fail(ValueError())
return defer.succeed(True)
class DeferredChainTest(unittest.TestCase):
def check_success(self, result):
"If we're called, we're on the callback chain."
self.fail()
def check_error(self, failure):
"""
If we're called, we're on the errback chain.
Return to put us back on the callback chain.
"""
return True
def check_error_fail(self, failure):
"""
If we're called, we're on the errback chain.
"""
self.fail()
# This fails after all callbacks and errbacks have been run, with the
# ValueError from the failed defer, even though we're
# not on the errback chain.
def test_plain(self):
"""
Test that a DeferredList without arguments is on the callback chain.
"""
# check_error_fail asserts that we are on the callback chain.
return get_dl().addErrback(self.check_error_fail)
# This fails after all callbacks and errbacks have been run, with the
# ValueError from the failed defer, even though we're
# not on the errback chain.
def test_fire(self):
"""
Test that a DeferredList with fireOnOneErrback errbacks on failure,
and that an errback puts it back on the callback chain.
"""
# check_success asserts that we don't callback.
# check_error_fail asserts that we are on the callback chain.
return get_dl(fireOnOneErrback=True).addCallbacks(
self.check_success, self.check_error).addErrback(
self.check_error_fail)
# This succeeds.
def test_consume(self):
"""
Test that a DeferredList with consumeErrors errbacks on failure,
and that an errback puts it back on the callback chain.
"""
# check_error_fail asserts that we are on the callback chain.
return get_dl(consumeErrors=True).addErrback(self.check_error_fail)
# This succeeds.
def test_fire_consume(self):
"""
Test that a DeferredList with fireOnOneCallback and consumeErrors
errbacks on failure, and that an errback puts it back on the
callback chain.
"""
# check_success asserts that we don't callback.
# check_error_fail asserts that we are on the callback chain.
return get_dl(fireOnOneErrback=True, consumeErrors=True).addCallbacks(
self.check_success, self.check_error).addErrback(
self.check_error_fail)
# This fails after all callbacks and errbacks have been run, with the
# ValueError from the failed defer, even though we're
# not on the errback chain.
def test_two_deferreds(self):
# check_error_fail asserts that we are on the callback chain.
return two_deferreds().addErrback(self.check_error_fail)
【问题讨论】:
标签: python unit-testing testing twisted