objective-c ocunit xctest

objective c - Error XCTAssertEqual:("3") no es igual a("3")



objective-c ocunit (5)

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.");

¿Qué no entiendo acerca de XCTAssertEqual? ¿Por qué falla la última afirmación?


En caso de que alguien más esté buscando el problema con la doble comparación como yo (la solución anterior no funcionará para flotación y doble), intente:

XCTAssertEqualWithAccuracy(number.doubleValue, 12.34, 0.01);

Genera un error cuando (la diferencia entre (/ a expression1) y (/ a expression2) es> (/ a accuracy))).


También he tenido bastantes problemas con las pruebas de Xcode 5. Todavía parece bastante problemático con algún comportamiento extraño; sin embargo, he encontrado la razón definitiva por la que su XCTAssertEqual particular no funciona.

Si echamos un vistazo al código de prueba, vemos que realmente hace lo siguiente (tomado directamente de XCTestsAssertionsImpl.h - puede ser más fácil verlo allí):

#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); / }/ })

Aquí está el problema:

Lo que realmente hace la prueba es codificar los valores en un NSValue y luego compararlos. "Está bien", dices, "¿pero cuál es el problema con eso?" No pensé que hubiera ninguno hasta que hice mi propio caso de prueba. El problema es que NSValue''s -isEqualToValue también debe comparar el tipo de codificación NSValue así como su valor real. Ambos deben ser iguales para que el método devuelva YES .

En su caso, arr.count es un NSUInteger que es un tipodef de unsigned int . La constante de tiempo de compilación 3 presumiblemente degenera en un signed int en tiempo de ejecución. Por lo tanto, cuando los dos se colocan en un objeto NSValue , sus tipos de codificación no son iguales y, por lo tanto, los dos NO PUEDEN ser iguales según -[NSValue isEqualToValue] .

Puedes probar esto con un ejemplo personalizado. El siguiente código explícitamente hace exactamente lo que hace 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 :(" aparecerá en el registro cada vez.

Me apresuro a agregar aquí que esto es, de hecho, el comportamiento esperado. Se supone que NSValue comprueba su codificación de tipo al hacer comparaciones. Lamentablemente, no es lo que esperábamos cuando probamos dos enteros (''iguales'').

XCTAssertTrue , por cierto, tiene una lógica mucho más directa, y se comporta generalmente como se esperaba (de nuevo, vea la fuente real de cómo determina si la aserción falla).


También me atrapó este problema, muy agradecido por las soluciones provisionales aquí. Rápido para su información, parece que esto fue arreglado en la versión Xcode 5.1.

https://developer.apple.com/library/mac/releasenotes/DeveloperTools/RN-Xcode/xc5_release_notes/xc5_release_notes.html

La macro XCTAssertEqual (anteriormente STAssertEquals usando OCUnit) compara correctamente valores escalares de diferentes tipos sin conversión, por ejemplo, int y NSInteger. Ya no puede aceptar tipos no escalares, como estructuras, para comparar. (14435933)

Todavía no me he actualizado de Xcode 5.0.2, pero mi colega sí, y las mismas pruebas de XC que fallaban anteriormente debido a este problema pasan ahora sin la solución alternativa de conversión.


Una alternativa es simplemente usar casting:

XCTAssertEqual(arr.count, (NSUInteger)3, @"Wrong array size.");

Puede ser la mejor solución con el estado actual de las herramientas, especialmente si tiene un código donde está usando mucho XCTAssertEqual y no quiere cambiar a XCTAssertTrue .

(Noté que @RobNapier hizo esta sugerencia en un comentario).


Yo también tuve este problema. Como @ephemera y @napier indicaron, este es un problema de tipo .

Puede resolverse suministrando un valor del tipo correcto, usando los modificadores c-literal.

XCTAssertEqual(arr.count, 3ul, @"Wrong array size.");

Puede encontrar el tipo correcto buscando el tipo de devolución de la función utilizada en el lado izquierdo - ALT-click en arr. count

- (NSUInteger)count;

Ahora haga ALT-clic en NSUInteger para encontrar su tipo:

typedef unsigned long NSUInteger;

Ahora encuentre el formato numérico literal c para unsigned long, google es un buen amigo pero esta página funciona:

http://www.tutorialspoint.com/cprogramming/c_constants.htm

Como una sugerencia rápida aquí, puede que necesite usar U (sin firmar) L (largo) o F (flotar), y asegúrese de escribir 1.0 en lugar de 1 para obtener un doble. La minúscula también funciona, como en mi ejemplo anterior.