问题描述
我创建了一个函数,该函数返回距离下一次出现该时间还剩几秒的时间,但我在为它编写单元测试时遇到了问题.人们如何测试这种调用了 datetime.now()
的函数?
I created a function that returns seconds left until the next occurrence of that time, but I came across a problem writing a unit test for it. How do people test this type of function that has a call to datetime.now()
in it?
添加另一个参数 (current_time
) 似乎是错误的,因为它改变了函数的初始要求.
Adding another parameter (current_time
) seems wrong just to test it as it changes the initial requirements of the function.
要测试的功能是.
from datetime import datetime, time, timedelta
def get_time_left(target_time):
'''return float of number of seconds left until the target_time'''
if not isinstance( target_time, time ):
raise TypeError("target_time must be datetime.time")
curr_time = datetime.now()
target_datetime = datetime.combine( datetime.today(), target_time )
if curr_time > target_datetime:
target_datetime = curr_time + timedelta(1)
seconds_left = (curr_time - target_datetime).total_seconds()
return seconds_left
对它的测试是.
class TestDTime(unittest.TestCase):
def test_time_left(self):
dt_now = datetime.now()
tm_5sec_future = ( dt_now + timedelta(0,5) ).time()
self.assertEqual( dtime.get_time_left(tm_5sec_future), 5.0)
结果是.
======================================================================
FAIL: test_time_left (__main__.TestDTime)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/ctatest.py", line 37, in test_time_left
self.assertEqual( dtime.get_time_left(tm_5sec_future), 5.0)
AssertionError: -4.999985 != 5.0
在不向函数添加任何参数的情况下对此类进行单元测试的最佳方法是什么?
What is best approach to unit testing something like this without adding any args to the function?
推荐答案
您需要使用模拟框架将 UT 与依赖项隔离,以便您的 UT 具有一致的行为.
You need to use mocking framework to isolate your UT from dependencies so your UT will have a consistence behavior.
Freezegun - 是我曾经使用过的一个很好的模拟库.
Freezegun - is a good mocking library for times which I have been used.
只需安装这个库:pip install freezegun
在您的 UT 中使用装饰器 @freeze_time
如下:
The in your UT used the decorator @freeze_time
as the following:
@freeze_time("2018-06-03")
def test_time_left(self):
dt_now = datetime.now()
tm_5sec_future = (dt_now + timedelta(0, 5)).time()
self.assertEqual(dtime.get_time_left(tm_5sec_future), -5.0)
这篇关于如何在不添加参数的情况下对基于时间的函数进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!