用于python-3.3的模拟工具

时间:2013-10-12 20:13:14

标签: python unit-testing python-3.x mocking python-3.3

我有一些类依赖于time.perf_counter()来为事件添加时间戳,并在经过一段时间后执行操作,如下所示:

class Alarm:
    def setAlarm(self):
        self.alarmed = False
        self._saved = time.perf_counter()

    def runStep(self):
        now = time.perf_counter()
        if now - self._saved > 1000.0 and self._saved != -1:
            self.alarmed = True
            self._saved = -1

我想使用假时钟测试类Alarm,它不一定是对time.perf_counter()的调用(尽管它会更优雅,我猜)。我希望假时钟不会自行增加,而是根据我的命令,如下:

    alarm = Alarm()
    alarm.setAlarm()
    clock.increment(999.0)
    alarm.runStep()
    self.assertFalse(alarm.alarmed)
    clock.increment(1.1)    # tick another second
    alarm.runStep()
    self.assertTrue(alarm.alarmed)

请问您如何模仿time.perf_counter()或模拟我的课程,以及应该使用哪种工具进行此类工作?

1 个答案:

答案 0 :(得分:2)

您可以使用unittest.mock

例如:

import time
import unittest
import unittest.mock

class Alarm:
    def setAlarm(self):
        self.alarmed = False
        self._saved = time.perf_counter()
    def runStep(self):
        now = time.perf_counter()
        if now - self._saved > 1000.0 and self._saved != -1:
            self.alarmed = True
            self._saved = -1

class MockPerfCounter:
    def __init__(self):
        self.t = 0
    def increment(self, n):
        self.t += n
    def perf_counter(self):
        return self.t

class TestAlarm(unittest.TestCase):
    def test_foo(self):
        clock = MockPerfCounter()
        with unittest.mock.patch('time.perf_counter', clock.perf_counter):
            alarm = Alarm()
            alarm.setAlarm()
            clock.increment(999.0)
            alarm.runStep()
            self.assertFalse(alarm.alarmed)
            clock.increment(1.1)    # tick another second
            alarm.runStep()
            self.assertTrue(alarm.alarmed)

if __name__ == '__main__':
    unittest.main()

代替手动MockPerfCounter,您也可以使用unittest.mock.Mock

class TestAlarm(unittest.TestCase):
    def test_foo(self):
        clock = unittest.mock.Mock()
        clock.t = 0
        with unittest.mock.patch('time.perf_counter', lambda: clock.t):
            alarm = Alarm()
            alarm.setAlarm()
            clock.t += 999.0
            alarm.runStep()
            self.assertFalse(alarm.alarmed)
            clock.t += 1.1
            alarm.runStep()
            self.assertTrue(alarm.alarmed)