2016-09-20 200 views
2

有一个对象依赖于计时来正确运行。不幸的是,定时持续时间本身太长,不能实时对其进行实时测试,缩短持续时间会因测试对象的性质而影响测试的目的。涉及时间的Golang测试程序

测试此类对象的最佳方法是什么?理想情况下,会有一些虚拟时钟可以任意快速运行,可以使用。

type Obj struct{} 
func (o Obj) TimeCriticalFunc(d time.Duration) bool { 
    //do stuff 
    //possibly calling multiple times time.Now() or other real time related functions 
} 

func TestTimeCriticalFunc(t *testing.T) { 
    if !Obj{}.TimeCriticalFunc(10 * 24 * time.Hour) { 
     t.Fail() 
    } 
} 
+0

使用代表挂钟时间明显的参数。在测试过程中,您可以快速前进这段时间。看看package net/http/cookiejar是如何做到的。 – Volker

+0

这种方法需要修改函数本身,但我不太愿意这样做。还带来了一个问题,如果我要测试一些涉及我没有代码的函数的东西,我会很无奈 –

+0

也许这些类型的对象应该总是有一个显式的参数来表示时间。最后可能会这样做,但我确实认为这是最后的手段 –

回答

3

这实际上是在Andrew Gerrand的Testing Techniques talk中回答的。在你的代码做

var (
    timeNow = time.Now 
    timeAfter = time.After 
) 

// ... 

type Obj struct{} 
func (o Obj) TimeCriticalFunc(d time.Duration) bool { 
    // Call timeAfter and timeNow. 
} 

而且在测试中做

func TestTimeCriticalFunc(t *testing.T) { 
    timeNow = func() time.Time { 
     return myTime // Some time that you need 
    } 
    // "Redefine" timeAfter etc. 
    if !Obj{}.TimeCriticalFunc(10 * 24 * time.Hour) { 
     t.Fail() 
    } 
} 
+1

还值得注意的是,测试函数设置为'timeNow'变量(函数时间)的匿名函数/闭包可以跟踪它的次数调用,它可能会根据调用返回不同的值。例如。 'timeNow'可能会先返回'00:00',下次通话时可能会返回'00:01'等。请参阅[Go Playground]上的示例(https://play.golang.org/p/Ac7PcaTJ_Z)。 – icza