xcode5 ocunit xctest

xcode5 - ¿Cómo migro de SenTestingKit/OCUnit a XCTest?



(2)

Editar -> Refactorizar -> Convertir a XCTest

Las pruebas de OCUnit seguirán funcionando, pero también podría migrar. Los cambios terminan siendo bastante mínimos.

Estoy en el proceso de migrar mi proyecto de Xcode 4.6.3 a Xcode 5.0.2. Las pruebas unitarias del proyecto se desarrollaron con SenTestingKit / OCUnit. Ahora cuando estoy ejecutando las pruebas en Xcode 5, recibo un error del script RunUnitTests diciéndome que

RunUnitTests está obsoleto.

Posiblemente relacionado está esta nota en las notas de la versión de Xcode 5:

SenTestingKit y OCUnit están en desuso. Usa el migrador para moverte a XCTest.

Lamentablemente, no he podido obtener más información sobre este misterioso "migrador". Posiblemente mi google-fu carece [de nuevo], así que mi pregunta principal es: ¿cómo migro las pruebas unitarias desde SenTestingKit / OCUnit al nuevo XCTest (con o sin el "migrador")?

Una pregunta secundaria, en caso de que la migración sea una tarea complicada: ¿es posible hacer que Xcode 5 ejecute pruebas unitarias que todavía se basan en SenTestingKit / OCUnit? Después de todo esto son simplemente obsoletos, por lo que todavía deberían estar disponibles y funcionales.


Gracias a la respuesta de Shaggy Frog sabemos que el misterioso "migrador" mencionado en las notas de la versión de Xcode es un asistente lanzado al seleccionar "Editar> Refactorizar> Convertir a XCTest". Voy a escribir sobre mi experiencia con este asistente en dos partes. La primera parte es una respuesta incompleta a la pregunta principal, la segunda parte responde a la pregunta secundaria.

Parte 1: Cómo migrar de OCUnit a XCTest

Lo primero que debe tener en cuenta es que para que el asistente funcione, debe seleccionar un objetivo de prueba unitario . Si tiene seleccionado el objetivo principal, el asistente simplemente no enumera ningún objetivo para convertir.

Una vez que me enteré de esto, pude pasar por el asistente, pero en mi caso el resultado final fue un fracaso espectacular. El asistente afirmó que no era necesario realizar cambios en la fuente y que solo era necesario actualizar la configuración para migrar a XCTest. Al final, el asistente ni siquiera logró hacerlo correctamente: eliminó la referencia al marco SenTestingKit, pero no incluyó una referencia al marco XCTest.

De todos modos, lo que sigue es una lista de los cambios que tuve que hacer manualmente porque el asistente no pudo hacerlos por mí. Si el asistente funciona mejor para usted, es posible que no necesite hacer todas estas cosas.

  1. Elimine la fase de compilación "Ejecutar secuencia de comandos" del objetivo de prueba de unidad
  2. Cambie la clase base de todas las clases de casos de prueba de SenTestCase a XCTestCase
  3. Cambie el encabezado importado de <SenTestingKit/SenTestingKit.h> a <XCTest/XCTest.h>
  4. En la configuración de compilación del objetivo de prueba, cambie la extensión de octest de octest a xctest .
  5. Cambie el nombre de todas las macros assert de ST* a XCT* (p STAssertTrue Ej. STAssertTrue convierte en XCTAssertTrue )
  6. Excepción a lo anterior: STAssertEquals necesita ser renombrado a XCTAssertEqual (observe la "s" que falta al final). Sabrá que se ha olvidado de esto si obtiene esta advertencia del compilador: warning: implicit declaration of function ''XCTAssertEquals'' is invalid in C99
  7. Las nuevas macros XCTest assert no permiten que se pase nil como descripción de la falla. Por ejemplo, XCTAssertNotNil(anObject, nil) no es posible y se debe cambiar a XCTAssertNotNil(anObject) . Sabrá que tiene este problema cuando obtenga este error de compilación: error: called object type ''NSString *'' is not a function or function pointer .
  8. Si necesita pasar una descripción de falla, las nuevas macros de XCTest assert requieren una expresión constante para el especificador de formato, tal como lo NSString método de clase stringWithFormat: Sabrá que tiene este problema cuando obtenga este error de compilación: error: expected '')'' . Algunos ejemplos:

NSString* formatSpecifier = @"%@"; NSString* failureDescription = @"foo"; // These are OK XCTAssertNotNil(anObject, @"foo") XCTAssertNotNil(anObject, @"%@", failureDescription) // These are not OK XCTAssertNotNil(anObject, failureDescription); XCTAssertNotNil(anObject, formatSpecifier, failureDescription);

Por último, pero no por ello menos importante, como ya se mencionó anteriormente, la referencia al marco XCTest debe agregarse al objetivo de la prueba unitaria. Sabrá que lo ha olvidado si obtiene errores del enlazador, como los Undefined symbols for architecture i386: "_OBJC_CLASS_$_XCTestCase", referenced from: foo .

Actualización de Xcode 6 : ya no se necesita vincular con XCTest en Xcode 6 (de hecho, XCTest ya no figura como un marco disponible). En su lugar, establezca la configuración de compilación CLANG_ENABLE_MODULES en YES (expuesta en la interfaz de usuario como "Habilitar módulos (C y Objective-C)"). Esto hará que clang se vincule automáticamente contra XCTest cuando vea una declaración #import <XCTest/XCTest.h> . Los detalles están disponibles en la sección "Módulos" de la documentación de clang .

Parte 2: Cómo ejecutar pruebas OCUnit en Xcode 5

En este punto, recibí un error del enlazador que me hizo darme cuenta de que mi misión de migrar a XCTest había fallado. El motivo: XCTest no forma parte de SDK 6.1, pero aún estoy desarrollando mi proyecto con el SDK base iOS 6.1 ( esta respuesta SO explica cómo integrar SDK 6.1 en Xcode 5).

Como no puedo continuar con la migración, mi solución por el momento es mantener mis pruebas de unidad basadas en SenTestingKit / OCUnit, hasta que encuentre el momento de actualizar mi aplicación a iOS 7. Esto es lo que tenía que hacer para poder para ejecutar las pruebas unitarias:

  1. Elimine la fase de compilación "Ejecutar secuencia de comandos" del objetivo de prueba de la unidad. Esto es todo lo que se requiere para permitir que Xcode ejecute pruebas unitarias a través de la acción "Prueba" ( + U ) mientras se selecciona el objetivo de prueba de la unidad .
  2. Esto no es ideal, sin embargo, porque no quiero cambiar los objetivos solo para ejecutar pruebas unitarias. En cambio, quiero ejecutar pruebas unitarias mientras el objetivo principal está seleccionado . El segundo paso, por lo tanto, es modificar el esquema Xcode del objetivo principal para que cuando ejecute la acción "Prueba", las pruebas del objetivo de prueba unitario se ejecuten en su lugar.

La solución final no es tan buena como en Xcode 4.x donde las pruebas unitarias se ejecutaron automáticamente cada vez que ejecuté la acción "Ejecutar" o "Construir" del objetivo principal. Desafortunadamente, parece que no puedo hacer que esto funcione sin una fase de compilación "Ejecutar script".