我在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
是NSUInteger
這是一個unsigned int
的typedef。編譯時常量3
可能在運行時退化爲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
是假設比較時檢查其類型編碼。不幸的是,這並不是我們在測試兩個('相等')整數時所期待的。順便說一句,有更直接的邏輯,並且行爲如預期般一樣(同樣,請參閱實際來源以確定斷言是否失敗)。
其他一些偉大的匹配庫是: OCHamcrest和Expecta。 。還有Kiwi和Cedar--完全成熟的測試框架,內置良好的matcher庫。 。 (以防萬一你還沒有嘗試過)。 –