【问题标题】:STAssertEquals for checking NSArray count - clean way用于检查 NSArray 计数的 STAssertEquals - 干净的方式
【发布时间】:2013-03-24 15:30:05
【问题描述】:

使用 STAssertEquals for NSArray 检查 NSArray 项目计数的正确方法是什么。

以下预计会起作用:

...
STAssertEquals(1, [myArray count], @"One item should be in array");

此代码在运行测试时会产生“类型不匹配”运行时错误。

相反,我必须对 NSUInteger 进行显式转换:

STAssertEquals((NSUInteger)1, [myArray count], @"One item should be in array");

这可行 - 但由于显式转换,看起来有点难看。

我还想避免使用 STAssertTrue,因为 STAssertEquals 看起来更合适(我们比较两个值)并显示实际值和预期值。

在 Objective-C 中检查它的正确方法是什么?

更新 1

感谢建议使用 1u 作为 unsigned int 文字的答案

STAssertEquals(1u, [myArray count], @"One item should be in array");

但正如@Aaron 提到的那样,它仍然很丑 - 我想直接使用“1” - 现在考虑使用 myArray.count == 1 。原因是1u看起来不是很干净。 1对我来说就是1。你从来没有用数学写过 1u :-) 还有其他建议吗?

更新 2

正如@H2CO3 提到的,1u 甚至不能总是工作,并且正如某些线程中所建议的那样,我们可以对期望值使用更多的声明性定义,这将解决强制转换问题:

NSUInteger expectedItemsCount = 1;
STAssertEquals(expectedItemsCount, [myArray count], @"One item should be in array");

我更喜欢它而不是 1u 解决方案,因为它看起来更干净。但是这种方法的缺点是我们有额外的行并且代码不是很紧凑。所以看起来我们必须在两种方法之间进行选择:(NSUInteger)1NSUInteger expectedItemsCount = 1;

【问题讨论】:

  • 有趣,这意味着您打开了CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION 标志,您是自己(或项目中的某个人)这样做的,还是最近的 Xcode 更新打开了它?我以为它默认是关闭的。
  • @Pascal OP 没有收到编译器警告 - 他收到 runtime 错误。
  • @Pascal 是的,系统中的另一个“Apple,你在做什么”...... :'(
  • 实际上,@aaron-golden 进一步指出“STAssertEquals 宏显式检查参数的类型并在类型不相等时报错”。 是有道理的。
  • @Pascal - 是的,它发生在运行时,正如我在构建成功后看到的那样。我没有对项目进行任何具体更改并使用 XCode 版本 4.6 (4H127)

标签: objective-c ocunit


【解决方案1】:

C 的类型系统...

1int,所以它已签名。 NSArray.countNSUInteger 所以它没有签名。使整数文字无符号:

STAssertEquals(myArray.count, 1u, @"+1 item needed");

编辑:更好的是,上面的内容在 64 位上会失败(它可以与 1ull 一起使用),所以如果你只使用类似的东西会怎样

const NSUInteger expectedLength = 1;
STAssertEquals(myArray.count, expectedLength, @"+1 item needed");

(The thread from where I stole this...)

【讨论】:

  • 第二个版本对我来说似乎有点过头了,我会投的东西。
  • @Pascal 这比铸造更好。 (在 C 中,一切都比强制转换更好。)
  • 也适用于文字?我假设在这些情况下它会提示编译器做什么,这样它就会使用正确的类型。
  • @H2CO3 感谢您的详细说明。线程中的信息肯定有助于了解我们是什么船 :-) 所以现在我自己选择更新 2 中的任一解决方案。
  • @Pascal 你是对的——编译器有时会执行隐式转换。不是这个愚蠢的断言宏
【解决方案2】:

您可以使用STAssertEquals(1U, myArray.count, @"One item should be in array"); 使 1 无符号。也许这仍然很丑陋。打字少了一点。

【讨论】:

    【解决方案3】:

    1U 是正确的。但是,如果您想避免这种丑陋(并进入一个更好的断言世界),请使用 OCHamcrest:

    assertThat(myArray, hasCountOf(1));
    

    【讨论】:

    • 感谢您的回答。它是什么?汉克雷斯特?我不想在这里使用额外的库,而是使用标准工具。当您想比较两个值时,hasCountOf 看起来也很奇怪。我从未在 Ruby 或 Java 等其他语言中看到过这种方法。但感谢您指出这一点 - 很高兴了解所有可能的解决方案。
    • Hamcrest 诞生于 Java,现在是 JUnit 的标准部分。
    • 感谢您当时提到它 - 即使在 Java 中我也没有尝试使用它。那就看看吧!
    【解决方案4】:

    如果您的项目很大,或者您希望此代码具有较长的生命周期,请考虑为此添加特定的断言。定义一个特例宏

      STArrayCount(myArray,1)
    

    可以扩展为

      STAssertTrue(myArray.count==1u,@"Expected %u but array count is %u",myArray.count,1);
    

    编写自定义断言使您的单元测试在几年后重新访问时更加清晰,并且还为额外的测试提供了一个钩子。假设今天 myArray 是一个 NSArray,但后来它变成了 BigFancyObject 的一个实例,可以做一些其他的事情。 BigFancyObjects 使您的大部分代码更加简洁并隐藏了实现细节,这一切都很棒。但是您想确保 BigFancyObject 是有效的,因为某些东西不断使它们无效。因此,您可以将 STArrayCount 重新定义为

      STAssertTrue(myArray.isValid && myArray.count==...)
    

    现在您的单元测试也检查对象的有效性。

    【讨论】:

    • 嗨@MarkBernstein。我认为创建特殊宏来检查数组计数会增加额外的复杂性。我们将使用我们已经拥有的操作,而不是定义我们自己的数学:-)
    • 当然,如果您只是偶尔这样做,您不会想要自己的宏!但总的来说,它是一种广泛有用的技术。有关详细信息,请参阅 Meszaros 关于 xUnit 测试模式的书。
    【解决方案5】:

    我这样做的方法是将它们作为对象进行比较,这将在 32 位和 64 位上工作,避免需要任何强制转换或不必要的变量声明,并维护一个包含失败值的漂亮失败消息:

    STAssertEqualObjects(@(5), @(datas.count), @"unexpected array count");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-12
      • 1970-01-01
      • 2014-10-26
      相关资源
      最近更新 更多