Python单元测试中的易变值字典?

2 投票
1 回答
2154 浏览
提问于 2025-04-15 12:31

我需要为一个返回字典的函数写单元测试。这个字典里的一个值是 datetime.datetime.now(),这个值在每次测试运行时都会变化。

我想在我的断言中完全忽略这个键。目前我有一个字典比较的函数,但我真的想像这样使用 assertEqual:

def my_func(self):
    return {'monkey_head_count': 3, 'monkey_creation': datetime.datetime.now()}

... unit tests

class MonkeyTester(unittest.TestCase):
    def test_myfunc(self):
        self.assertEqual(my_func(), {'monkey_head_count': 3}) # I want to ignore the timestamp!

有没有什么好的方法或者优雅的解决方案来做到这一点?我知道 assertAlmostEqual(),但我记得那只是对浮点数有用。

1 个回答

9

在进行比较之前,先把字典里的时间戳删掉:

class MonkeyTester(unittest.TestCase):
    def test_myfunc(self):
        without_timestamp = my_func()
        del without_timestamp["monkey_creation"]
        self.assertEqual(without_timestamp, {'monkey_head_count': 3})

如果你经常需要进行一些和时间相关的测试,比如用到 datetime.now(),那么你可以对 datetime 类进行一些修改,以便在单元测试中使用。想想这个方法:

import datetime
constant_now = datetime.datetime(2009,8,7,6,5,4)
old_datetime_class = datetime.datetime
class new_datetime(datetime.datetime):
    @staticmethod
    def now():
        return constant_now

datetime.datetime = new_datetime

这样每次在你的单元测试中调用 datetime.datetime.now() 时,它都会返回一个固定的时间戳 constant_now。如果你想要恢复到原来的 datetime.datetime.now(),你只需要简单地执行:

datetime.datetime = old_datetime_class

这样一来,一切就会恢复正常。虽然这种方法很有用,但在你给出的简单例子中,我建议在比较之前直接把字典里的时间戳删掉。

撰写回答