XCTAssertEqual错误:(“3”)不等于(“3”)
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有什么不了解? 为什么最后的断言失败?
Xcode 5的testing也遇到了一些麻烦。 它似乎仍然有一些奇怪的行为错误 – 但是我发现你的特定XCTAssertEqual
无法正常工作的明确原因。
如果我们看一下testing代码,我们可以看到它实际上做了以下操作(直接从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); \ }\ })
这是问题:
testing实际上是在将值编码成NSValue
,然后进行比较。 “好吧,”你说,“但那有什么问题呢?” 直到我为自己做了一个testing用例,我才觉得有一个。 问题是NSValue的-isEqualToValue
还必须比较NSValue的编码types及其实际值。 两者必须相同才能返回YES
。
在你的情况下, arr.count
是一个NSUInteger
,它是unsigned int
的typedef。 编译时常量3
可能在运行时退化为带signed int
。 因此,当两个被放入一个NSValue
对象,他们的编码types是不相等的,因此两个不能相等根据-[NSValue isEqualToValue]
。
你可以用一个自定义的例子certificate这一点。 下面的代码明确地做了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
应该在比较时检查它的types编码。 不幸的是,这只是testing两个('相等')整数时所期望的。
XCTAssertTrue
一句, XCTAssertTrue
有更直接的逻辑,并且行为与预期的一样(同样,请参阅实际来源以确定断言是否失败)。
我也有这个问题。 正如@ephemera和@napier所示,这是一个types问题。
它可以通过使用c-literal修饰符提供正确types的值来解决。
XCTAssertEqual(arr.count, 3ul, @"Wrong array size.");
您可以通过查找左侧使用的函数的返回types来find正确的typesALT-click
arr。 count
:
- (NSUInteger)count;
现在在ALT上点击NSUInteger
来查找它的types:
typedef unsigned long NSUInteger;
现在findC字面数字格式为无符号的长 – 谷歌是一个很好的朋友,但这个网页的工作原理:
http://www.tutorialspoint.com/cprogramming/c_constants.htm
作为一个快速提示,您可能需要使用U(无符号)L(long)或F(float),并确保写入1.0而不是1来获得双精度值。 小写字母也有效,就像我上面的例子。
如果别人正在寻找像我这样的双重比较的问题(上面的解决scheme不适用于float和double),请尝试:
XCTAssertEqualWithAccuracy(number.doubleValue, 12.34, 0.01);
((\expression式1)和(\expression式2)之间的差异>(\ a精度)))时生成失败。
一种替代方法是使用铸造:
XCTAssertEqual(arr.count, (NSUInteger)3, @"Wrong array size.");
这可能是当前工具状态的最佳解决scheme,尤其是如果您有代码的情况下,您正在使用XCTAssertEqual
并且不想切换到XCTAssertTrue
。
(我注意到@RobNapier在评论中提出了这个build议。)
我也受到这个问题的困扰,非常感谢这里提供的解决方法。 Quick FYI,看来这是在Xcode 5.1版本中修复的。
XCTAssertEqualmacros(以前使用OCUnit的STAssertEquals)正确地比较了不同types的标量值,例如int和NSInteger。 它不能再接受非标量types,比如结构体。 (14435933)
我还没有从Xcode 5.0.2升级,但我的同事已经和以前由于这个问题失败了相同的XCtesting现在传递没有施法解决方法。
- 避免“NSArray被列举时发生了变异”
- Xcode版本(CFBundleShortVersionString)和build(CFBundleVersion)之间的区别
- Xcode不断要求input密码才能使用系统密钥链
- 获取属性名称作为string
- UISlider捕捉固定数量的步骤(如iOS 7设置应用中的文本大小)
- 点(“。”)运算符和箭头(“ – >”)运算符在C和Objective-C中使用
- 像在UIDocumentInteractionController中一样添加图像到UIActionSheetbutton
- NSNotificationCenter的post导致“EXC_BAD_ACCESS”exception
- Objective-C中的常量