OCUnit 中的简化断言

Posted

技术标签:

【中文标题】OCUnit 中的简化断言【英文标题】:Simplified asserts in OCUnit 【发布时间】:2010-02-11 20:06:23 【问题描述】:

我刚开始使用 OCUnit,发现断言有点麻烦。在 JUnit 中,我可以编写一个测试来比较如下数字。这个测试显然会失败,但这显示了我可以为两个数字编写的漂亮、简单的断言以及我得到的反馈:“预期 但是 ”,代码很少。

到目前为止,我在 XCode 中尝试的是:

这很有效,但不如 JUnit 优雅。你知道它是否存在断言宏 alà JUnit for XCode (OCUnit)?另外,是否可以在 XCode 中获得红/绿条?

【问题讨论】:

你可以试试AppCode,测试结果和Eclipse用JUnittv.jetbrains.net/videocontent/unit-testing-in-appcode提供的输出比较相似 【参考方案1】:

首先要注意的是 OCUnit(又名 SenTestingKit.framework)与 Xcode 集成,但并不是真正的 Xcode 的部分。 OCUnit 最初是第三方代码,后来成为 Objective-C 单元测试的事实上的标准,因此 Apple 采用了它并现在对其进行维护。

更重要的是,您看到的输出似乎有些奇怪。我正在使用 Snow Leopard 附带的 Xcode 3.2.1。我尝试了以下测试:

- (void) testNumbers 
    int number1 = 2;
    int number2 = 3;
    STAssertEquals(number1, number2, nil);
    STAssertEquals(4, 5, nil);

这是我在 Xcode 构建结果窗格/窗口中看到的错误:

-[ExampleTest testNumbers] : '2' should be equal to '3'
-[ExampleTest testNumbers] : '4' should be equal to '5'

当我双击构建日志中的错误时,Xcode 直接跳转到失败断言的行。

OCUnit 宏当然并不完美,但您在上面使用的示例非常冗长。宏需要 2+ 或 3+ 参数。 (STFail 是一个例外,只需要 1+ 个参数。)最后一个必需的参数始终是描述的可选格式字符串,并且任何其他参数都用于替换这些占位符,就像你对 @ 所做的那样987654324@ 或NSLog()。如果你通过nil,你只会得到默认错误,没有额外的细节。

我通常只在测试确实需要上下文时添加描述。例如,断言的测试和/或主题实际上意味着什么。通常,我只是将这些信息包含在断言周围的 cmets 中。越简单越好。 :-)

要回答您的最后一个问题,目前还没有一种方法可以在 Xcode 中像您在 JUnit 中看到的那样获得红/绿条。这可能是一个不错的补充,但我个人认为这不是关键。 YMMV。

【讨论】:

【参考方案2】:

正如其他人所说,您可以通过将nil 作为最后一个参数来使宏更容易接受。如果测试失败,这将为您提供默认输出。当然,您可以在需要时提供自己的字符串。我经常发现这对于具有返回 BOOLid 但通过引用获取 NSError* 的方法的代码很有用,如下所示:

- (void)testFoo 
  NSError *err;
  STAssertTrue([bar fooMethodReturningBOOLError:&err], @"Error: %@ (%@)", err, [err userInfo]);

关于红/绿条,在构建窗口中构建的最后一步,您确实会得到一个红/绿结果,但它不像在其他 IDE 中那样可见。有很多很好的心理学文献表明,让它更加突出将是一个好主意。一定要在bugreport.apple.com 提交增强请求。可以参考rdar://7685315(我的票就是这个效果)。

【讨论】:

【参考方案3】:

现在有一个很棒的框架可用,称为 OCHamcrest。它允许您的测试断言读起来像一个句子,而且通常您不必提供失败描述,对我来说,这是我在测试中不想做的最后一件事,因为它必须被维护。

这里是githubhttps://github.com/hamcrest/OCHamcrest

这是自述文件中的一个示例

NSCalendarDate* date = [NSCalendarDate dateWithString:@"26 Apr 2008" calendarFormat:@"%d %b %Y"];
assertThat(date, is(onASaturday()))

断言对 OCUnit 非常友好,添加您自己的断言非常简单。

【讨论】:

【参考方案4】:

为什么不为此创建自己的包装器?

OCUnit 将运行结果转储到控制台窗口,没有 GUI 集成,抱歉。我觉得挺方便的,不过习惯了。

【讨论】:

不是我想听到的答案,但足够公平。让我们希望 Apple 在 XCode 的下一个版本中更加关注这一点。 是的,这是真的。我的同事(通常在 Visual Studio/Eclipse 中开发)抱怨 XCode 并嘲笑它缺乏功能。确实它可能看起来很裸露,但至少它比 VS 快一点(接口方面):) 创建自定义包装器是可能的,但完全没有必要。无需额外的函数/宏杂技就很容易获得简洁的断言。详情见我的回答。

以上是关于OCUnit 中的简化断言的主要内容,如果未能解决你的问题,请参考以下文章

OCUnit - 测试用例失败时中断?

UINavigationController 中的 OCUnit 测试问题

Xcode 4 中的 SenTest OCUnit

访问 OCUnit 测试目标中的 UIImage

OCUnit 可以依赖后台线程中的代码吗? (为了测试异步请求)

单元测试和 TDD、OCUnit 与 Google 工具箱