Python单元测试中具有volatile值的字典?

poj*_*ojo 2 python unit-testing

我需要为返回字典的函数编写单元测试.这本词典中的一个值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!
Run Code Online (Sandbox Code Playgroud)

这样做有什么最佳实践或优雅的解决方案吗?我知道assertAlmostEqual(),但这对浮子iirc只有用.

Eli*_*ght 9

在进行比较之前,只需从dict中删除时间戳:

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})
Run Code Online (Sandbox Code Playgroud)

如果您发现自己正在进行大量与时间相关的测试,datetime.now()那么您可以为您的单元测试进行monkeypatch 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
Run Code Online (Sandbox Code Playgroud)

现在无论何时调用datetime.datetime.now()单元测试,它都会返回constant_now时间戳.如果你想/需要切换回原版,datetime.datetime.now()那么你可以简单地说

datetime.datetime = old_datetime_class
Run Code Online (Sandbox Code Playgroud)

事情会恢复正常.这种事情可能很有用,但在您给出的简单示例中,我建议您在比较之前删除dict中的时间戳.

  • 另一种选择是传入datetime.datetime.now作为命名参数的默认值; 在单元测试中传递你自己的功能.这避免了monkeypatching. (3认同)
  • 你应该放置代码以在拆解方法中切换日期时间 - 这样单元测试不会影响其他测试类 (2认同)