如何在不添加参数的情况下对基于时间的功能进

Pet*_*ore 3 python datetime unit-testing assert mocking

我创建了一个函数,它返回剩下的秒数直到下一次出现,但是我遇到了为它编写单元测试的问题.人们如何测试这种有调用功能的功能datetime.now()

添加另一个参数(current_time)似乎是错误的,只是为了测试它,因为它改变了函数的初始要求.

功能测试是.

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

对它的测试是.

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

结果是.

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

在不向函数添加任何参数的情况下对单元测试进行单元测试的最佳方法是什么?

Old*_*Fox 7

您需要使用模拟框架将您的UT与依赖关系隔离,以便您的UT具有一致性行为.

Freezegun - 对于我曾经使用过的时代来说,它是一个很好的模拟库.

只需安装此库: pip install freezegun

您的UT使用装饰器@freeze_time如下:

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