Bạn đang đi đúng hướng. Các giải pháp được đề xuất bởi bài viết objc.io có lẽ là The Way Right để làm điều đó nhưng không yêu cầu một số refactoring. Nếu bạn muốn làm cho các bài kiểm tra diễn ra như một bước đầu tiên trước khi bạn đi vào một thay đổi mã binge, đây là cách bạn có thể làm điều đó.
Thông thường, bạn có thể sử dụng XCTestExpectations để thực hiện gần như tất cả các thử nghiệm không đồng bộ của bạn. Một mô hình tiêu chuẩn có thể đi như thế này:
XCTestExpectation *doThingPromise = [self expetationWithDescription:@"Bazingo"];
[SomeService doThingOnSucceed:^{
[doThingPromise fulfill];
} onFail:^ {
}];
[self waitForExpectationsWithTimeout:1.0 handler:^(NSError *error) {
expect(error).to.beNil();
}]
này hoạt động tốt nếu [SomeService doThingOnSucceed: onFail:] cháy ra một yêu cầu async và sau đó giải quyết trực tiếp. Nhưng nếu nó làm những điều kỳ lạ hơn như:
+ (void)doThingOnSucceed:onFail: {
[Thing do it];
[self.context performBlock:^{
// Uh oh Farfalle-Os
success();
}];
}
Khối thực hiện sẽ được thiết lập nhưng bạn sẽ không chờ đợi để hoàn thành vì bạn không thực sự chờ đợi khối bên trong, chỉ bên ngoài một. Điều quan trọng là XCTestWaits thực sự cho phép kết thúc kiểm tra và sau đó chỉ kiểm tra rằng lời hứa đã được thực hiện trong một khoảng thời gian nhưng trong thời gian đó nó sẽ bắt đầu chạy các thử nghiệm khác. Thành công đó() có thể xuất hiện bất kỳ số lượng địa điểm nào và tạo ra bất kỳ số lượng hành vi kỳ lạ nào.
Hành vi cách ly (không có cách ly) xuất phát từ thực tế là nếu bạn chỉ chạy thử nghiệm này, mọi thứ có thể tốt do may mắn nhưng nếu bạn chạy nhiều thử nghiệm thì khối CoreData có thể bị treo xung quanh cho đến khi thử nghiệm tiếp theo là không đồng bộ, sau đó sẽ "bỏ chặn" thực thi của nó và nó sẽ bắt đầu thực hiện tại một số thời gian tương lai ngẫu nhiên cho một số thử nghiệm ngẫu nhiên trong tương lai.
Tấn công ngắn hạn rõ ràng xung quanh là tạm dừng thử nghiệm của bạn cho đến khi mọi thứ kết thúc. Dưới đây là một ví dụ:
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]];
}
Điều này ngăn cản một cách rõ ràng kiểm tra từ hoàn thành cho đến khi mọi thứ kết thúc, có nghĩa là không xét nghiệm khác có thể chạy cho đến khi kiểm tra này kết thúc.
Nếu có rất nhiều trường hợp trong các bài kiểm tra/mã của bạn, tôi khuyên bạn nên sử dụng giải pháp objc.io để tạo nhóm công văn mà bạn có thể đợi sau mỗi lần kiểm tra.
Đang cố gắng để thực hiện điều này (trong Swift) và tôi thấy rằng nó hoạt động, nhưng nó không tiếp tục ngay sau khi tín hiệu semaphore. Nó treo trên Runloop.run cho đến khi thời gian chờ xảy ra. Đây có phải là dự kiến không? Mã của tôi: 'trong khi semaphore.wait (thời gian chờ: .now()) == .timedOut { RunLoop.current.run (cho đến: Ngày (timeIntervalSinceNow: 10)) }' – guptron