Xcode 4 中的 SenTestingKit:异步测试?

Posted

技术标签:

【中文标题】Xcode 4 中的 SenTestingKit:异步测试?【英文标题】:SenTestingKit in Xcode 4: Asynchronous testing? 【发布时间】:2011-05-31 16:15:22 【问题描述】:

我一直在寻找一种方法来使用 SenTestingKit 在我的客户端代码和我们的服务器之间进行一些集成测试。我没有运气。似乎一旦代码在方法中运行,对象就会被销毁。这意味着任何异步响应都不会调用选择器。

问题:

    有没有办法让对象保持实例化,直到我认为合适的时候销毁它 - 即。测试完成后? 如果不是,我如何创建一个在测试完成之前阻塞(即同步执行)的类?

仅供参考,我正在运行一个我知道预期结果的测试服务器。

我已经在 Google 上进行了相当多的搜索,但还没有看到关于这一点的任何证据。我相信其他人也会感兴趣。

【问题讨论】:

接受的答案可以被视为“过时”。有几个很好的新答案。可能要重新考虑? 【参考方案1】:

您可以使用信号量等待异步方法完成。

- (void)testBlockMethod 
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    // Your block method eg. AFNetworking
    NSURL *url = [NSURL URLWithString:@"http://httpbin.org/ip"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) 
        NSLog(@"IP Address: %@", [JSON valueForKeyPath:@"origin"]);
        STAssertNotNil(JSON, @"JSON not loaded");
        // Signal that block has completed
        dispatch_semaphore_signal(semaphore);
     failure:nil];
    [operation start];

    // Run loop
    while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW))
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                                 beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
    dispatch_release(semaphore);

http://samwize.com/2012/10/03/sentestingkit-does-not-support-wait-for-blocks/

【讨论】:

我完全按照你的代码做,但它从来没有在成功块内打印日志。 在您考虑到您正在调用的代码可能不会在完成时发送信号量信号之前非常棒。 对我来说也很完美。我在另一个 SO 线程上看到了 NSCondionalLocking 的使用,它不能很好地工作,因为它会锁定主线程并阻止 AFNetworking 调度成功/错误回调。 如果你的循环和你的回调在同一个(主)线程上运行,那么像 __block BOOL finished = NO 这样的标志,然后在回调中将完成设置为 true 将起作用。回调和测试在主线程上序列化,因此信号量不需要 /need/,如下所示:mattconnolly.wordpress.com/2012/05/29/… 实际上并不那么出色。有几个问题,这里是一个:运行循环仅在有事件或超时触发时返回。这意味着在最坏的情况下,即使委托发出信号量,但在该运行循环和模式上没有排队的事件 - while 循环仍将等待长达 10 秒,直到它再次检查信号量。另一个是,你不能有超时。不太适合测试...【参考方案2】:

两种选择:

切换到GHUnit,实际上包含了对等待异步事件的支持 缩小测试的设计范围,以便您可以按原样测试事物。例如。测试您的控制器代码是否导致选择器被分离并运行,并(单独)测试该选择器是否完成了它应该做的事情。如果这两件事都有效,那么您可以确信您的控制器分离了正确的工作。

【讨论】:

不幸的是,我正在测试的是 connect-encrypt-authenticate-getsomedata 过程,如果没有持久性来处理回调,它就无法分解。 SenTestingKit 似乎没有给我我需要的持久性。但我会看看 GHUnit。 GHUnit 似乎是最好的选择。 gabriel.github.com/gh-unit/_examples.html 的示例页面准确地显示了我需要测试的情况......是时候学习一个新工具了!【参考方案3】:

Kiwi supports asynchronous testing。 Kiwi 是适用于 ios 的 Behavior Driven Development (BDD) 库,扩展了 SentTestingKit (OCUnit),因此易于设置和使用。

另外,请查看:

iOS Tests/Specs TDD/BDD and Integration & Acceptance Testing。 Testing asynchronous code on iOS with OCunit

【讨论】:

猕猴桃看起来很有趣。它是否处理异步回调?【参考方案4】:

这个项目https://github.com/hfossli/AGAsyncTestHelper有一个很方便的宏

WAIT_WHILE(<expression_to_evaluate>, <max_duration>);

哪个能让你这样写测试

- (void)testDoSomething 

    __block BOOL somethingIsDone = NO;

    [MyObject doSomethingAsyncThenRunCompletionBlockOnMainQueue:^
        somethingIsDone = YES;
    ];

    WAIT_WHILE(!somethingIsDone, 1.0); 
    NSLog(@"This won't be reached until async job is done");

【讨论】:

【参考方案5】:

检查 SenTestingKitAsync 项目 - https://github.com/nxtbgthng/SenTestingKitAsync。相关博客在这里-http://www.objc.io/issue-2/async-testing.html

【讨论】:

以上是关于Xcode 4 中的 SenTestingKit:异步测试?的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 3.1 中的单元测试

如何使用 NSDebugEnabled、NSZombieEnabled、MallocStackLogging 运行 OCUnit (SenTestingKit)?

#import <SenTestingKit/SenTestingKit.h> 未找到

“错误生成子进程:没有这样的文件或目录”Xcode

单元测试用例:XCTestCase vs Sentestcase

块中的 STFail