这是一个提供“时间旅行”和“时间冻结”功能的库,使测试依赖时间的代码变得非常简单。灵感来自 ruby timecop 珍宝。
使用CocoaPods安装 Timecop 到您的项目中,请向您的 Podfile 添加以下内容
pod 'Timecop'
运行时间敏感测试
Person *joe = [Persons findJoe];
[joe purchaseHome];
XCTAssertFalse( [joe MortgageDue] );
// move ahead a month and assert that the mortgage is due
NSDate *aMonthLater = [NSDate dateWithTimeIntervalSinceNow:60*60*24*30];
[Timecop freezeWithDate:aMonthLater block:^{
XCTAssertTrue( [joe mortgageDue] );
}];
冻结用于静态模拟“现在”的概念。随着您的程序执行,Time.now 不会改变,除非您调用 Timecop API 执行后续调用。另一方面,travel 计算当前我们认为 Time.now 是什么与传入时间之间的偏移量(请记住,我们支持嵌套旅行)。它使用这个偏移量来模拟时间的流逝。为了演示,考虑以下代码片段
NSDate *aHourAgo = [NSDate dateWithTimeIntervalSinceNow:60*60*-1];
[Timecop freezeWithDate:aHourAgo];
sleep(10)
if( aHourAgo == [NSDate date] ){
NSLog(@"TIME NOT PASSED");
}
[Timecop finishTravel]; // "turn off" Timecop
[Timecop travelWithDate:aHourAgo];
sleep(10)
if( aHourAgo != [NSDate date] ){
NSLog(@"TIME PASSED!");
}
假设您想测试一个“实时”集成,其中整个一天可能只需几分钟,同时您能够通过后续对应用程序的调用模拟“真实”活动。例如,一个这样的用例是可以测试在很短的时间内运行的 30 天周期的报告和发票,同时也可以模拟通过后续调用应用程序的活动。
# seconds will now seem like hours
[Timecop scaleWithFactor:3600];
NSLog(@"current date :%@", [NSDate date]);
// sleep 1sec
sleep(1);
// seconds later, hours have past it's gone a hour!
NSLog(@"a hour passed! :%@", [NSDate date]);
安全模式强制您使用 Timecop 的块语法,因为它总是将时间恢复原状。如果您在安全模式下运行并使用不带块的时间戳,将会抛出异常以告知用户他们没有采取安全措施。
// turn on safe mode
[Timecop setSafeMode:YES];
// using method without block
[Timecop freezeWithDate:nil];
// *** Terminating app due to uncaught exception 'Timecop Exception', reason: 'Safe mode is enabled, only calls passing a block are allowed.'