XCTest 在使用期望失败时通过
XCTest passes when it should fail using expectations
我正在测试一种在后台运行并在完成时执行代码块的方法。我正在使用期望来处理测试的异步执行。我写了一个简单的测试来显示行为:
- (void) backgroundMethodWithCallback: (void(^)(void)) callback {
dispatch_queue_t backgroundQueue;
backgroundQueue = dispatch_queue_create("background.queue", NULL);
dispatch_async(backgroundQueue, ^(void) {
callback();
});
}
- (void) testMethodWithCallback {
XCTestExpectation *expectation = [self expectationWithDescription:@"Add collection bundle"];
[self backgroundMethodWithCallback:^{
[expectation fulfill];
usleep(50);
XCTFail(@"fail test");
}];
[self waitForExpectationsWithTimeout: 2 handler:^(NSError *error) {
if (error != nil) {
XCTFail(@"timeout");
}
}];
}
对于此测试,XCTFail(@"fail test");
行应该失败,但测试正在通过。
我还注意到,只有当回调中的代码 运行 花费了一定时间时才会发生这种情况(在我的例子中,我正在检查文件系统上的一些文件)。这就是为什么 usleep(50);
行是重现案例所必需的。
在所有测试检查之后必须满足预期。将行移动到回调块的末尾足以使测试失败:
- (void) testMethodWithCallback {
XCTestExpectation *expectation = [self expectationWithDescription:@"Add collection bundle"];
[self backgroundMethodWithCallback:^{
usleep(50);
XCTFail(@"fail test");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout: 2 handler:^(NSError *error) {
if (error != nil) {
XCTFail(@"timeout");
}
}];
}
我没有找到关于此的明确文档,但在 apple developer guide 之后,fulfill
消息在块的末尾发送,这很有意义。
注意:我首先在swift中找到an example,其中在回调开始时调用了fulfill
方法。我不知道的是示例是否不正确或者与 Objective-C.
有区别
backgroundMethodWithCallback
调用的块立即满足预期,从而让测试在调用 XCTFail
之前完成。如果该块在完成执行其他操作之前满足预期,那么您最终会遇到竞争条件,其中测试的行为取决于执行块其余部分的速度。但是,如果测试本身已经完成,那么不应该合理地期望 XCTFail
被捕获。
最重要的是,如果您将 [expectation fulfill]
移动到块的末尾,则可以消除此竞争条件。
我正在测试一种在后台运行并在完成时执行代码块的方法。我正在使用期望来处理测试的异步执行。我写了一个简单的测试来显示行为:
- (void) backgroundMethodWithCallback: (void(^)(void)) callback {
dispatch_queue_t backgroundQueue;
backgroundQueue = dispatch_queue_create("background.queue", NULL);
dispatch_async(backgroundQueue, ^(void) {
callback();
});
}
- (void) testMethodWithCallback {
XCTestExpectation *expectation = [self expectationWithDescription:@"Add collection bundle"];
[self backgroundMethodWithCallback:^{
[expectation fulfill];
usleep(50);
XCTFail(@"fail test");
}];
[self waitForExpectationsWithTimeout: 2 handler:^(NSError *error) {
if (error != nil) {
XCTFail(@"timeout");
}
}];
}
对于此测试,XCTFail(@"fail test");
行应该失败,但测试正在通过。
我还注意到,只有当回调中的代码 运行 花费了一定时间时才会发生这种情况(在我的例子中,我正在检查文件系统上的一些文件)。这就是为什么 usleep(50);
行是重现案例所必需的。
在所有测试检查之后必须满足预期。将行移动到回调块的末尾足以使测试失败:
- (void) testMethodWithCallback {
XCTestExpectation *expectation = [self expectationWithDescription:@"Add collection bundle"];
[self backgroundMethodWithCallback:^{
usleep(50);
XCTFail(@"fail test");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout: 2 handler:^(NSError *error) {
if (error != nil) {
XCTFail(@"timeout");
}
}];
}
我没有找到关于此的明确文档,但在 apple developer guide 之后,fulfill
消息在块的末尾发送,这很有意义。
注意:我首先在swift中找到an example,其中在回调开始时调用了fulfill
方法。我不知道的是示例是否不正确或者与 Objective-C.
backgroundMethodWithCallback
调用的块立即满足预期,从而让测试在调用 XCTFail
之前完成。如果该块在完成执行其他操作之前满足预期,那么您最终会遇到竞争条件,其中测试的行为取决于执行块其余部分的速度。但是,如果测试本身已经完成,那么不应该合理地期望 XCTFail
被捕获。
最重要的是,如果您将 [expectation fulfill]
移动到块的末尾,则可以消除此竞争条件。