python - 如何更改 Python 中所有模块的日期/时间?

标签 python unit-testing datetime testing time

当我使用业务逻辑编写时,我的代码通常取决于当前时间。例如,该算法查看每个未完成的订单并检查是否应发送发票(这取决于作业结束后的天数)。在这些情况下,创建发票不是由显式用户操作触发,而是由后台作业触发。

现在,当涉及到测试时,这给我带来了一个问题:

  • 我可以轻松测试发票创建本身
  • 但是,很难在测试中创建订单并检查后台作业是否在正确的时间识别正确的订单。

到目前为止,我找到了两个解决方案:

  • 在测试设置中,计算相对于当前日期的工作日期。缺点:代码变得相当复杂,因为不再有明确的日期。有时,对于边缘情况,业务逻辑非常复杂,因此由于所有这些相对日期,调试变得困难。
  • 我有自己的日期/时间访问器函数,我在整个代码中都使用这些函数。在测试中,我只是设置了一个当前日期,所有模块都得到这个日期。因此,我可以模拟 2 月份的订单创建,并轻松检查发票是否在 4 月份创建。缺点:第 3 方模块不使用这种机制,因此很难集成和测试这些。

毕竟,第二种方法对我来说更成功。因此,我正在寻找一种方法来设置 Python 的 datetime+time 模块返回的时间。设置日期通常就足够了,我不需要设置当前的小时或秒(即使这样会很好)。

有这样的实用程序吗?是否有我可以使用的(内部)Python API?

最佳答案

Monkey-patching time.time 实际上可能就足够了,因为它为 Python 中几乎所有其他基于时间的例程提供了基础。这似乎可以很好地处理您的用例,而无需诉诸更复杂的技巧,并且何时执行都没关系(除了少数 stdlib 包,例如 Queue.py 和 threading.py 执行 from time import时间 在这种情况下,您必须在它们被导入之前进行修补):

>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2010, 4, 17, 14, 5, 35, 642000)
>>> import time
>>> def mytime(): return 120000000.0
...
>>> time.time = mytime
>>> datetime.datetime.now()
datetime.datetime(1973, 10, 20, 17, 20)

也就是说,多年来为各种类型的自动化测试模拟对象,我很少需要这种方法,因为大多数时候需要模拟的是我自己的应用程序代码,而不是 stdlib 例程。毕竟,你知道他们已经工作了。如果您遇到您自己的代码必须处理库例程返回的值的情况,您可能希望自己模拟库例程,至少在检查您自己的应用程序如何处理时间戳时是这样。

到目前为止,最好的方法是构建您自己的日期/时间服务例程,专门用于您的应用程序代码,并在此基础上构建测试以根据需要提供虚假结果的能力。例如,我有时会做一个更复杂的等价物:

# in file apptime.py (for example)
import time as _time

class MyTimeService(object):
    def __init__(self, get_time=None):
        self.get_time = get_time or _time.time

    def __call__(self):
        return self.get_time()

time = MyTimeService()

现在在我的应用程序代码中,我只需 import apptime as time; time.time() 来获取当前时间值,而在测试代码中,我可以先在 setUp() 中执行 apptime.time = MyTimeService(mock_time_func) > 提供虚假时间结果的代码。

更新: 多年后出现了替代方案,如 Dave Forgac's answer 中所述.

关于python - 如何更改 Python 中所有模块的日期/时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2658026/

相关文章:

python - 如何同时运行 kivy 和 flask 应用程序?

python - 从 python2 转换为 python3 时处理 encode()

c# - 错误单元测试 webapi Controller

node.js - 为什么 sinon 不取代实际的函数调用?

c++ - 确定夏令时是否适用于特定日期

python - 按日期和时间查询存储在 MongoDB 中的数据

c++ - 如何从 boost::posix_time::ptime 获取自纪元时间以来的毫秒数

python - awk:致命:无法打开文件 'file' 进行读取(权限被拒绝)

Python 使用 BS4 在整个 XML 中添加子子元素

java - 使用 TestNG 让每个测试方法在其自己的测试类实例中运行?