Xcode测试单独传递,与其他测试一起运行时失败

Mos*_*she 13 xcode unit-testing nsoperation ios xctest

我写了一些异步单元测试,XCTest期望测试我写的网络类.我的大多数测试每次都有效.

当我运行整个套件时,有一些测试会失败,但是会自行传递.

其他测试失败,但使用相同的URL发出请求会在粘贴到浏览器时返回相应的数据.

我的网络代码封装在NSOperation运行的对象上NSOperationQueue.(我的操作队列是默认类型 - 我没有明确地将基础GCD队列设置为串行或并发.)

我可以看一下修复这些测试的内容?在阅读objc.io上的这篇文章后,我假设他们正遭受某种隔离问题.

pll*_*uke 8

你走在正确的道路上.objc.io文章建议的解决方案可能是正确的方法,但确实需要一些重构.如果你想在进行代码更改狂欢之前将测试作为第一步,那么你可以这样做.

通常,您可以使用XCTestExpectations来执行几乎所有的异步测试.标准模式可能如下所示:

XCTestExpectation *doThingPromise = [self expetationWithDescription:@"Bazingo"];
[SomeService doThingOnSucceed:^{
  [doThingPromise fulfill];
} onFail:^ {
}];
[self waitForExpectationsWithTimeout:1.0 handler:^(NSError *error) {
    expect(error).to.beNil();
}]
Run Code Online (Sandbox Code Playgroud)

如果[SomeService doThingOnSucceed:onFail:]触发异步请求然后直接解析,这可以正常工作.但如果它做了更奇特的事情,如:

+ (void)doThingOnSucceed:onFail: {
  [Thing do it];
  [self.context performBlock:^{
    // Uh oh Farfalle-Os
    success();
  }];
}  
Run Code Online (Sandbox Code Playgroud)

执行块将被设置但你不会等待它完成,因为你实际上并没有等待内部块,只是外部块.关键是XCTestWaits实际上让测试完成,然后只检查承诺是否在一段时间内完成,但同时它将开始运行其他测试.成功()可能出现在任意数量的地方并产生任何数量的奇怪行为.

隔离行为(与没有隔离)来自这样一个事实:如果你只运行这个测试,一切都可能因为运气好,但是如果你运行多个测试,那么CoreData块可能会被卡住,直到下一个异步测试,然后将"解锁"其执行,它将在一些随机的未来时间开始执行以进行一些随机的未来测试.

短期明确的黑客攻击是暂停你的测试,直到事情结束.这是一个例子:

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[SomeService doThingOnComplete:^{
  dispatch_semaphore_signal(semaphore);
}];
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}
Run Code Online (Sandbox Code Playgroud)

这明确阻止测试完成,直到所有内容完成,这意味着在此测试完成之前不会运行其他测试.

如果您的测试/代码中存在大量这些情况,我建议使用objc.io解决方案来创建一个您可以在每次测试后等待的调度组.