当我使用业务逻辑编写代码时,我的代码通常取决于当前时间。例如,查看每个未完成订单并检查是否应发送发票(这取决于作业结束后的天数)的算法。在这些情况下,创建发票不是由显式用户操作触发的,而是由后台作业触发的。
现在这给我带来了一个测试问题:
到目前为止,我找到了两个解决方案:
第二种方法对我来说毕竟要成功得多。因此,我正在寻找一种方法来设置Python的datetime+time模块返回的时间。设置日期通常就足够了,我不需要设置当前的小时或秒(尽管这会很好)。
有这样的公用事业吗?我可以使用(内部)Python API吗?
freezegun包是专门为此目的而制作的。它允许您更改测试代码的日期。它可以直接使用,也可以通过decorator或上下文管理器使用。一个例子:
有关更多示例,请参见项目:https://github.com/spulec/freezegun
您可以通过创建一个作为代理的自定义日期时间模块(甚至是一个假的——见下面的示例),然后将其插入sys.modules字典来修补系统。从那时起,每次导入datetime模块都将返回您的代理。
仍然有datetime类的警告,特别是当有人这样做时;为此,您只需为该类添加另一个代理即可。
下面是我所说的一个例子——当然,这只是我在5分钟内抛出的一些东西,可能有几个问题(例如,datetime类的类型不正确);但希望它已经有用。
最后-值得吗?
坦率地说,我更喜欢我们的第二个解决方案:)。
是的,python是一种非常动态的语言,在这里您可以做很多有趣的事情,但是以这种方式修补代码总是有一定的风险,即使我们在这里讨论的是测试代码。
但是,我认为附件函数会使测试补丁更加明确,而且您的代码在测试内容方面也会更加明确,从而提高可读性。
因此,如果改变不是太贵的话,我会采用你的第二种方法。
实际上,Monkey补丁
time.time
可能已经足够了,因为它为Python中几乎所有其他基于时间的例程提供了基础。这似乎可以很好地处理您的用例,而无需使用更复杂的技巧,而且何时执行也无所谓(除了少数stdlib包,如Queue.py和threading.py,在这种情况下,您必须在导入它们之前进行修补):也就是说,在多年来为各种类型的自动化测试模拟对象的过程中,我很少需要这种方法,因为大多数时候需要模拟的是我自己的应用程序代码,而不是stdlib例程。毕竟,你知道他们已经开始工作了。如果遇到自己的代码必须处理库例程返回的值的情况,则可能需要模拟库例程本身,至少在检查自己的应用程序如何处理时间戳时是这样。
到目前为止,最好的方法是构建您自己的日期/时间服务例程,您只在应用程序代码中使用这些例程,并在其中构建测试功能,以便根据需要提供假结果。例如,有时我会做一个更复杂的类似的事情:
现在在我的应用程序代码中,我只需要
import apptime as time; time.time()
来获取当前时间值,而在测试代码中,我可以首先在apptime.time = MyTimeService(mock_time_func)
代码中setUp()
来提供假时间结果。更新:几年后有一个替代方案,如Dave Forgac's answer所述。
相关问题 更多 >
编程相关推荐