Ich habe einige Twisted-Code, der mehrere Ketten von Deferreds erstellt. Einige von diesen können fehlschlagen, ohne einen Fehler zu haben, der sie zurück in die Rückrufkette bringt. Ich war nicht in der Lage, einen Komponententest für diesen Code zu schreiben - der fehlgeschlagene Verzögerter bewirkt, dass der Test nach Abschluss des Testcodes fehlschlägt. Wie kann ich einen bestandenen Unit-Test für diesen Code schreiben? Wird erwartet, dass jeder Deferred, der im normalen Betrieb ausfallen könnte, am Ende der Kette einen Fehlerrücklauf haben sollte, der ihn zurück in die Callback-Kette bringt?Wie können verdrillte verzögerte Fehler ohne Fehler mit der Testversion getestet werden?
Das Gleiche passiert, wenn eine DeferredList in einer DeferredList fehlschlägt, es sei denn, ich erstelle die DeferredList mit consumeErrors. Dies ist auch dann der Fall, wenn die DeferredList mit fireOnEneErrback erstellt wird und ein Fehler zurückgegeben wird, der sie zurück in die Callback-Kette stellt. Gibt es irgendwelche Implikationen für consumeErrors, abgesehen von der Unterdrückung von Testfehlern und der Fehlerprotokollierung? Sollte jeder Deferred, der ohne einen Fehler fehlschlagen könnte, eine DeferredList setzen?
Beispiel Tests von Beispielcode:
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)
Große Antwort, aber Sie könnten auch "--force-gc" erwähnen. – Glyph
Guter Anruf, hinzugefügt. –
Dies passiert auch beim Aufruf von log.err mit einer Fehlerinstanz, richtig? – Chris