【问题标题】:Dictionaries with volatile values in Python unit tests?Python单元测试中具有可变值的字典?
【发布时间】:2009-06-26 14:49:52
【问题描述】:

我需要为返回字典的函数编写单元测试。这本字典中的一个值是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(),但这仅对浮动 iirc 有用。

【问题讨论】:

    标签: python unit-testing


    【解决方案1】:

    在进行比较之前从字典中删除时间戳:

    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
    

    一切都会恢复正常。这种事情可能很有用,尽管在您给出的简单示例中,我建议在比较之前从字典中删除时间戳。

    【讨论】:

    • 为什么我没有想到这个简单的解决方案?尽管我将测试 my_func 的许多可能返回值,但我想我会按照您的建议对日期时间进行猴子补丁。非常感谢,真的很聪明!
    • 你应该在一个拆卸方法中加入代码来切换日期时间——这样这个单元测试就不会影响其他测试类
    • 另一个选项是传入 datetime.datetime.now 作为命名参数的默认值;在单元测试中传入你自己的函数。这避免了猴子补丁。
    • Chrispy,单元测试不应该要求修改测试代码。
    猜你喜欢
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多