在 Nose 中伪造 time.time() 的时间戳

Faking a time stamp from time.time() in Nose

我正在构建一个设备对象以从 python 中连接的设备轮询数据,我正在尝试使用 nose 测试该对象的内部工作及其所有功能。在使用 time.time() 编写时间戳时,我 运行 通常遇到一个问题,因为每次调用该函数时,结果值都不同,这严重搞砸了一些测试,例如这个数据收集函数:

def getData(self, data):
    if type(data) is not type({}):
        #print "Bad Type!"
        raise TypeError
    else:
        #print "Good Type!"
        self.outD = {}
        datastr = ""
        for key, value in data.iteritems():
            self.outD[key] = value
        self.outD["timestamp"] = time.time()
        self.outD["id"] = self.id
        self._writeCSV()

当我测试此函数的输出并比较生成的 CSV 文件时,由于时间戳的原因,它总是失败。我可以通过添加测试标志在我的设备对象中将它分出,但我想知道 nose 是否有内置的方法来处理这样的问题,其中函数的结果可以用给定值或本地函数替换来伪造time.time() 电话。这可能吗?

您可以使用 unittest.mock。示例:

import time
from unittest import mock

@mock.patch('time.time', mock.MagicMock(return_value=12345))
def test_something():
    assert time.time() == 12345

产生以下输出:

$ nosetests3 -v
test.test_something ... ok

----------------------------------------------------------------------
Ran 1 test in 0.006s

OK

尽管 mockunittest 包的一部分,但它实际上是不相关的并且适用于任何测试框架。

对于 Python < 3.3,您可以使用 mock package from PyPI.

这是从A.C之前的回答中推导出来的。没有必要显式创建 MagicMock。其次,mock的使用也必须断言以证明其用途。

import time
import unittest.mock

@unittest.mock.patch('time.time', return_value=12345)
def test_foo(mock_time):
    assert time.time() == 12345
    mock_time.assert_called_once()

这是用 Python 3.7.

测试的

您可以简单地将 time.time() 函数分配给您自己的函数,并以适当的方式用您自己的函数定义时间:

time.time = my_time_function

分配给自己的功能可以发生在单元测试的开始,而在最后又恢复原来的功能:

class MyTests(unittest.TestCase):
    def get_time(self):
        return self.emulated_time

    def setUp(self):
        # Define the emulated time
        self.emulated_time = time.mktime(
                time.strptime("2020-01-18 02:02:05", "%Y-%m-%d %H:%M:%S"))

        # Register the time.time function and patch it then
        self.time_method = time.time
        time.time = self.get_time

    def tearDown(self):
        # Restore the time.time function
        time.time = self.time_method
    
    def test_time_span(self):
        # Register the start time, do something, emulate a time update of 1
        # second, and check that the execution duration is one second
        start_time = time.time()
        # <do something here>
        self.emulated_time += 1
        self.assertEqual(time.time(), start_time+1)

此示例已在 Python 3.6.8.

上测试