How do I check for LoopingCall ()?

In my code, I am using task.LoopingCall()

to run some deferred function every second. I want to make sure that this function will return the correct values ​​for a certain number of things. So, I thought I could use task.clock()

and call a method advance()

on it. However, I am not getting the correct number of expected responses.

Any idea what I am doing wrong?

Here's some test code to show what I mean. Server first:

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()

      

And now a test case:

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)

      

When I run py.test I get:

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

      

Note that the addition import time; time.sleep(5)

does indeed make a trial run. So I suspect that the problem is what task.clock

is being misused.

+3


source to share


1 answer


I believe I have found problems.

  • LoopingCall

    uses the default reactor. I needed to set it up so that it uses my own clock through a class variable clock

    . See task.clock .
  • self.clock.advance(x)

    sets the clock at the moment x

    . It does not go through (x-1, x-2, ..., now)

    , and therefore any pending that needs to be done in those intermediate stages will not be executed. Hence, a bug in the test is the correct behavior. Calling self.clock.advance(1)

    within a loop starting at 0 and ending in seconds_elapsed

    had the desired effect.


The twisted section on unit tests is worth reading a few times to get a feel for what's going on. If you have more problems, take a look at the twisted tests of the indoor unit!

+2


source







All Articles