问题描述
NSMutableArray *arr = [NSMutableArray array];
[arr addObject:@"1"];
[arr addObject:@"2"];
[arr addObject:@"3"];
// This statement is fine.
XCTAssertTrue(arr.count == 3, @"Wrong array size.");
// This assertion fails with an error: ((arr.count) equal to (3)) failed: ("3") is not equal to ("3")
XCTAssertEqual(arr.count, 3, @"Wrong array size.");
我对XCTAssertEqual不了解什么?为什么最后一个断言失败?
What don't I understand about XCTAssertEqual? Why does the last assertion fail?
推荐答案
我在Xcode 5的测试中也遇到了很多麻烦.似乎仍然存在某些奇怪行为的小问题-但是,我已经找到了确定的原因,即您的特定XCTAssertEqual
无法正常工作.
I have also had quite a bit of trouble with Xcode 5's tests. It still seems quite buggy with some odd behaviour - however I have found the definitive reason your particular XCTAssertEqual
isn't working.
如果我们看一下测试代码,就会发现它实际上执行以下操作(直接取自XCTestsAssertionsImpl.h
-可能更容易在此处查看):
If we have a look at the test code we see it actually does the following (taken directly from XCTestsAssertionsImpl.h
- it may be easier to view there):
#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
.
What the test is actually doing is encoding the values into an NSValue
and then comparing them. "Okay," you say, "but what's the problem with that?" I didn't think there was one either until I made my own test case for it. The problem is that NSValue's -isEqualToValue
must also compare the NSValue's encoding type as well as its actual value. Both must be equal for the method to return YES
.
在您的情况下,arr.count
是NSUInteger
,它是unsigned int
的typedef.编译时常量3
可能在运行时退化为signed int
.因此,当将两者放入NSValue
对象时,它们的编码类型不相等,因此根据-[NSValue isEqualToValue]
两者不能相等.
In your case, arr.count
is an NSUInteger
which is a typedef of unsigned int
. The compile-time constant 3
presumably degenerates into a signed int
at runtime. Thus when the two are put into an NSValue
object, their encoding types are not equal and thus the two CANNOT be equal according to -[NSValue isEqualToValue]
.
您可以通过一个自定义示例来证明这一点.以下代码明确地完全执行XCTAssertEqual
的作用:
You can prove this with a custom example. The following code explicitly does exactly what XCTAssertEqual
does:
// 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 :("
每次都会出现在日志中.
"3 != 3 :("
will appear in the log every time.
我不得不在这里补充说,这实际上是预期的行为. NSValue
应该 在进行比较时检查其类型编码.不幸的是,这并不是我们在测试两个(相等")整数时所期望的.
I hasten to add here that this is, in fact, expected behaviour. NSValue
is supposed to check its type encoding when doing comparisons. Unfortunately it's just not what we were expecting when testing two ('equal') integers.
XCTAssertTrue
具有更简单的逻辑,并且通常按预期方式运行(再次,请参见实际来源以了解如何确定断言是否失败).
XCTAssertTrue
, incidentally, has much more straightforward logic, and behaves generally as expected (again, see the actual source for how it determines whether the assertion fails).
这篇关于XCTAssertEqual错误:("3")不等于("3")的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!