为什么使用Xcode 5.0和XCTesting进行以下单元测试?我的意思是,我理解底线:1 == 0未评估。但为什么不进行评估呢?如何才能使其失败?
- (void)testAnimationResult
{
[UIView animateWithDuration:1.5 animations:^{
// Some animation
} completion:^(BOOL finished) {
XCTAssertTrue(1 == 0, @"Error: 1 does not equal 0, of course!");
}];
}
从技术上讲,这将起作用。但当然测试将持续2秒。如果你有几千个测试,这可以加起来。
更有效的是在类别中存根UIView静态方法,以便它立即生效。然后在测试目标中包含该文件(但不包括您的应用程序目标),以便仅将类别编译到测试中。我们用:
#import "UIView+Spec.h"
@implementation UIView (Spec)
#pragma mark - Animation
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion {
if (animations) {
animations();
}
if (completion) {
completion(YES);
}
}
@end
上面只是立即执行动画块,如果也提供了立即完成块。
@dasblinkenlight走在正确的轨道上;这是我为使其正常工作所做的:
- (void)testAnimationResult
{
[UIView animateWithDuration:1.5 animations:^{
// Some animation
} completion:^(BOOL finished) {
XCTAssertTrue(1 == 0, @"Error: 1 does not equal 0, of course!");
}];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
}
这里的目标是将异步操作转换为同步操作。最常用的方法是使用信号量。
- (void)testAnimationResult {
// Create a semaphore object
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[UIView animateWithDuration:1.5 animations:^{
// Some animation
} completion:^(BOOL finished) {
// Signal the operation is complete
dispatch_semaphore_signal(sem);
}];
// Wait for the operation to complete, but not forever
double delayInSeconds = 5.0; // How long until it's too long?
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
long timeoutResult = dispatch_semaphore_wait(sem, timeout);
// Perform any tests (these could also go in the completion block,
// but it's usually clearer to put them here.
XCTAssertTrue(timeoutResult == 0, @"Semaphore timed out without completing.");
XCTAssertTrue(1 == 0, @"Error: 1 does not equal 0, of course!");
}
如果你想看一些这方面的例子,请看RNCryptorTests。
更好的方法(现在)是使用期望。
func testAnimationResult() {
let exp = expectation(description: "Wait for animation")
UIView.animate(withDuration: 0.5, animations: {
// Some animation
}) { finished in
XCTAssertTrue(1 == 0)
exp.fulfill()
}
waitForExpectations(timeout: 1.0, handler: nil)
}