我在 Xcode 5 的测试中也遇到了很多麻烦。一些奇怪的行为似乎仍然很麻烦 - 但是我找到了你的特定行为XCTAssertEqual
不起作用的明确原因。
如果我们看一下测试代码,我们会看到它实际上做了以下事情(直接取自XCTestsAssertionsImpl.h
——在那里可能更容易查看):
#define _XCTPrimitiveAssertEqual(a1, a2, format...) \
({ \
@try { \
__typeof__(a1) a1value = (a1); \
__typeof__(a2) a2value = (a2); \
NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \
NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \
float aNaN = NAN; \
NSValue *aNaNencoded = [NSValue value:&aNaN withObjCType:@encode(__typeof__(aNaN))]; \
if ([a1encoded isEqualToValue:aNaNencoded] || [a2encoded isEqualToValue:aNaNencoded] || ![a1encoded isEqualToValue:a2encoded]) { \
_XCTRegisterFailure(_XCTFailureDescription(_XCTAssertion_Equal, 0, @#a1, @#a2, _XCTDescriptionForValue(a1encoded), _XCTDescriptionForValue(a2encoded)),format); \
} \
} \
@catch (id exception) { \
_XCTRegisterFailure(_XCTFailureDescription(_XCTAssertion_Equal, 1, @#a1, @#a2, [exception reason]),format); \
}\
})
这是问题所在:
测试实际上做的是把这些值编码成一个NSValue
然后比较它们。“好吧,”你说,“但那有什么问题?” 在我为它制作自己的测试用例之前,我也不认为有一个。问题是 NSValue-isEqualToValue
还必须比较 NSValue 的编码类型以及它的实际值。两者必须相等才能返回方法YES
。
在您的情况下,arr.count
is an NSUInteger
which 是unsigned int
. 编译时常量3
可能会在运行时退化为 a signed int
。因此,当将两者放入一个NSValue
对象时,它们的编码类型不相等,因此根据 ,两者不能相等-[NSValue isEqualToValue]
。
您可以通过自定义示例来证明这一点。下面的代码明确地做了什么XCTAssertEqual
:
// Note explicit types
unsigned int a1 = 3;
signed int a2 = 3;
__typeof__(a1) a1value = (a1);
__typeof__(a2) a2value = (a2);
NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))];
NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))];
if (![a1encoded isEqualToValue:a2encoded]) {
NSLog(@"3 != 3 :(");
}
"3 != 3 :("
每次都会出现在日志中。
我赶紧在这里补充一下,这实际上是预期的行为。应该在进行比较时检查其类型编码NSValue
。不幸的是,这不是我们在测试两个(“相等”)整数时所期望的。
XCTAssertTrue
顺便说一句,它具有更直接的逻辑,并且通常按预期运行(再次,请参阅实际来源以了解它如何确定断言是否失败)。