代码之家  ›  专栏  ›  技术社区  ›  Peter Moore

如何在不添加参数的情况下对基于时间的函数进行单元测试

  •  3
  • Peter Moore  · 技术社区  · 6 年前

    我创建了一个函数,该函数返回到下一次出现时的剩余秒数,但在为它编写单元测试时遇到了问题。人们如何测试这种调用 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
    

    对它的考验是。

    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
    

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

    1 回复  |  直到 6 年前
        1
  •  7
  •   Old Fox    6 年前

    您需要使用mocking框架将您的ut与依赖项隔离,这样您的ut将具有一致性行为。

    Freezegun -是一个很好的模仿图书馆的时间,我已经使用。

    只需安装此库: pip install freezegun

    你大学里的那个用了装修工 @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)