Ho anche avuto un po 'di problemi con i test di Xcode 5. Sembra ancora abbastanza buggato con qualche strano comportamento - tuttavia ho trovato la ragione definitiva per cui il tuo particolare non funziona.
Se abbiamo uno sguardo al codice di prova lo vediamo in realtà fa il seguente (preso direttamente da XCTestsAssertionsImpl.h
- potrebbe essere più semplice per vedere lì):
#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); \
}\
})
Ecco il problema:
Quello che il test sta effettivamente facendo è codificare i valori in un NSValue
e poi confrontarli. "Okay," dici, "ma qual è il problema?" Non pensavo che ce ne fosse uno fino a quando non ho fatto il mio caso di prova per questo. Il problema è che lo -isEqualToValue
di NSValue deve anche confrontare il tipo di codifica di NSValue e il suo valore effettivo. Entrambi devono essere uguali per il metodo per restituire YES
.
Nel tuo caso, arr.count
è un NSUInteger
che è un typedef di unsigned int
. La costante in fase di compilazione 3
degenera presumibilmente in un signed int
in fase di runtime. Pertanto, quando i due vengono inseriti in un oggetto NSValue
, i loro tipi di codifica non sono uguali e quindi i due non possono essere uguali in base a -[NSValue isEqualToValue]
.
Puoi dimostrarlo con un esempio personalizzato. Il seguente codice fa esplicitamente esattamente ciò che fa 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 :("
apparirà nel registro ogni volta.
Mi affretto ad aggiungere qui che questo è, in effetti, un comportamento previsto. NSValue
è supposto per verificare la codifica del tipo durante i confronti. Sfortunatamente non è quello che ci aspettavamo quando testavo due interi ('uguali').
XCTAssertTrue
, per inciso, ha una logica molto più diretta e si comporta in genere come previsto (di nuovo, vedere la sorgente effettiva di come determina se l'asserzione non riesce).
Alcune altre librerie grandi matcher sono: OCHamcrest e Expecta. . c'è anche Kiwi e Cedar: framework di test a pieno titolo con belle librerie di match incorporate. . (Nel caso non li abbia ancora provati). –