【问题标题】:Twisted unittest "Reactor Unclean" when using TimeoutMixin使用 TimeoutMixin 时扭曲的单元测试“Reactor Unclean”
【发布时间】:2021-03-26 23:43:32
【问题描述】:

我正在实现一个可以用不同超时实例化的协议,所以我使用TimeoutMixin。这个想法可以用这个虚拟类来表示:

my_protocol.py

from twisted.protocols import basic, policies
from twisted.internet import protocol

class MyProtocol(basic.LineReceiver, policies.TimeoutMixin):
    def __init__(self, timeout):
        self.setTimeout(timeout)

    def lineReceived(self, line):
        self.transport.write(line)

为了使用 Twisted Trial 对其进行测试,请大致遵循 official tutorial

test_my_protocol.py

from twisted.trial import unittest
from twisted.test import proto_helpers

import my_protocol

class TestMyProtocol(unittest.TestCase):
    def setUp(self):
        self.protocol = my_protocol.MyProtocol(1)
        self.transport = proto_helpers.StringTransport()
        self.protocol.makeConnection(self.transport)

    def test_echo(self):
        self.protocol.lineReceived(b"test")
        self.assertEqual(self.transport.value(), b"test")

    def tearDown(self):
        self.protocol.transport.loseConnection()

运行测试时出现以下错误:

$ python -m twisted.trial test_my_protocol
test_my_protocol
  TestMyProtocol
    test_echo ...                                                       [ERROR]

===============================================================================
[ERROR]
Traceback (most recent call last):
Failure: twisted.trial.util.DirtyReactorAggregateError: Reactor was unclean.
DelayedCalls: (set twisted.internet.base.DelayedCall.debug = True to debug)
<DelayedCall 0x7ff1f9a8d070 [0.9994857311248779s] called=0 cancelled=0 TimeoutMixin.__timedOut()>

test_my_protocol.TestMyProtocol.test_echo
-------------------------------------------------------------------------------
Ran 1 tests in 0.011s

FAILED (errors=1)

official docs 在这个话题上是这么说的:

对 reactor.callLater 的调用会创建 IDelayedCall 。这些需要在测试期间运行或取消,否则它们将超过测试。这会很糟糕,因为它们可能会干扰以后的测试,从而在不相关的测试中造成混乱的失败!出于这个原因,Trial 会检查反应堆,以确保在测试后反应堆中没有剩余的 IDelayedCall ,如果有则测试失败。确保这一切正常运行的最简洁和最简单的方法是从测试中返回 Deferred。

但我不知道在 TimeoutMixin 的情况下该怎么办。

【问题讨论】:

    标签: python unit-testing twisted deferred twisted.internet


    【解决方案1】:

    您已将协议连接到 proto_helpers.StringTransport。在许多方面,这是一件好事,对测试有益。然而,一个缺点是StringTransport 没有实现loseConnection 你可能会怎么做。它所做的只是记录调用该方法的事实。它不会将通知传递给您的协议。

    幸运的是,StringTransportWithDisconnection确实将通知传递给协议。如果你切换到这个,那么你的协议的connectionLost 方法将被调用。然后,您需要进行另一项更改。调用 connectionLost 时,TimeoutMixin 不会自动取消其超时。因此,您需要在调用self.setTimeout(None) 的协议中添加connectionLost

    【讨论】:

    • 非常感谢!在文档的一些额外帮助下,测试现在通过了。在self.transport = proto_helpers.StringTransportWithDisconnection() 之后必须添加self.transport.protocol = self.protocol
    猜你喜欢
    • 2010-12-07
    • 2011-08-14
    • 2011-05-07
    • 2013-09-25
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    • 2013-08-17
    相关资源
    最近更新 更多