如何测试LoopingCall()?

时间:2013-01-30 17:18:22

标签: python twisted trial

在我的代码中,我使用task.LoopingCall()每秒运行一些延迟函数。我想确保该函数为特定数量的东西返回正确的值。所以,我想我可以使用task.clock()并在其上调用advance()方法。但是,我没有得到预期的正确数量的回复。

知道我做错了吗?

这是一个显示我的意思的测试代码。首先是服务器:

from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
from twisted.internet import task
import time

class Chat(LineReceiver):

    def __init__(self):
        self.echo = None

    def connectionMade(self):
        self.echo = task.LoopingCall(self.echo_print)
        self.echo.start(1)

    def connectionLost(self, reason='whatever'):
        if self.echo is not None and self.echo.running:
            self.echo.stop()

    def lineReceived(self, line):
        if line == 'stop':
            self.echo.stop()

    def echo_print (self):
        self.sendLine("Echo")

class ChatFactory(Factory):

    def __init__(self):
        pass

    def buildProtocol(self, addr):
        return Chat()

if __name__ == "__main__":
    reactor.listenTCP(8123, ChatFactory())
    reactor.run()

现在是测试用例:

from twisted.internet import task, base
from twisted.trial import unittest
from twisted.test import proto_helpers
from chat import ChatFactory

class TestChat (unittest.TestCase):

    def setUp (self):
        self.factory = ChatFactory()
        self.clock = task.Clock()
        self.proto = self.factory.buildProtocol(('127.0.0.1', 0))
        self.tr = proto_helpers.StringTransport()
        self.proto.callLater = self.clock.callLater
        self.proto.makeConnection(self.tr)

    def tearDown (self):
        if self.proto:
            self.proto.connectionLost()

    def test_echo (self):
        self.proto.dataReceived('ook\n')
        seconds_elapsed = 5
        self.clock.advance(seconds_elapsed)
        expected = 'Echo\r\n' * seconds_elapsed
        self.assertEqual(self.tr.value(), expected)

当我在此运行py.test时,我得到:

E           FailTest: not equal:
E           a = 'Echo\r\n'
E           b = 'Echo\r\nEcho\r\nEcho\r\nEcho\r\nEcho\r\n'

请注意,添加import time; time.sleep(5)确实会使测试通过。所以,我怀疑问题是task.clock未正确使用。

1 个答案:

答案 0 :(得分:2)

我相信我发现了问题。

  1. LoopingCall默认使用reactor。我需要设置它,以便它通过类变量clock使用我自己的时钟。请参阅task.clock课程文档。
  2. self.clock.advance(x)将时钟设置为时间x。它不会通过(x-1, x-2, ..., now),因此任何应该在这些中间步骤上运行的延迟都不会运行。因此,测试中的错误是正确的行为。在从0开始并以self.clock.advance(1)结尾的循环内调用seconds_elapsed确实产生了预期效果。
  3. unit tests上的Twisted部分值得阅读几次,以便您熟悉正在发生的事情。如果您有更多问题,请查看扭曲的内部单元测试!