xcode unit-testing debugging buildconfiguration

Xcode: PRUEBA frente a las macros del preprocesador DEBUG



unit-testing debugging (10)

Decidí agregar un cheque para una variable de entorno en el código en sí, en lugar de usar la sugerencia de isRunningTests () que Robert hizo.

  1. Edite el Esquema actual (Esquema de producto / esquema / edición) o Comando + <
  2. Haga clic en la configuración de prueba
  3. Haga clic en Argumentos Desmarque "Utilizar los argumentos y las variables de entorno de la acción Ejecutar
  4. Expanda la sección Variable de entorno y agregue la variable PRUEBA con el valor SÍ
  5. Agregue esto a su código en alguna parte y llame cuando lo necesite:

+ (BOOL) isTesting { NSDictionary* environment = [[NSProcessInfo processInfo] environment]; return [environment objectForKey:@"TESTING"] != nil; }

La pantalla debería verse así cuando haya terminado.

El código anterior encontrará la variable de entorno PRUEBA cuando se ejecuta en modo de prueba o modo de aplicación. Este código va en su aplicación, no en los archivos de prueba de la unidad. Puedes usar

#ifdef DEBUG ... #endif

Para evitar que el código se ejecute en producción.

Al crear un nuevo proyecto con pruebas unitarias, Xcode establece la configuración de compilación en Debug para el esquema de prueba (lo mismo para el esquema de ejecución).

¿Debería diferenciar entre los esquemas de Ejecutar (Comando-R) y Probar (Comando-U)?

Es decir, ¿debería crear una nueva configuración de compilación llamada Test, agregarle una macro de preprocesador TEST = 1 y utilizarla como la configuración de compilación para el esquema de prueba? O, ¿debería mantener Run & Test como Debug?

Vengo de un entorno de Ruby / Rails, donde generalmente tiene entornos de prueba, desarrollo y producción. Me parece que Debug es como desarrollo y Release es como producción, pero nos falta una prueba, y es por eso que creo que podría tener sentido agregar Test.

¿Comentarios? Opiniones? Sugerencias?

Específicamente pregunto esto porque quiero compilar algo para Test con:

#ifdef TEST // Do something when I test. #endif

No creo que importe si también compilo esto para Debug. Entonces, realmente podría hacer:

#ifdef DEBUG // Do something when I run or test. #endif

Pero, en realidad, solo tengo la intención de hacerlo para las pruebas por ahora. Entonces, es por eso que estoy pensando que debería diferenciar entre depuración y prueba, pero me pregunto por qué Xcode no hace eso por usted de manera predeterminada. ¿Apple piensa que no deberías diferenciar entre ellos?


En iOS, [UIApplication sharedApplication] devolverá nil cuando se esté ejecutando una prueba de unidad.


En lugar de crear una configuración de compilación de prueba, I:

  1. creado un archivo Tests-Prefix.pch :

    #define TEST 1 #import <SenTestingKit/SenTestingKit.h> #import "CocoaPlant-Prefix.pch"

  2. ingresó a su ruta en el campo Encabezado de prefijo de la configuración de compilación del objetivo de Pruebas.

  3. MyAppDefines.h el siguiente código a la parte superior de un archivo que creé llamado MyAppDefines.h , importado en MyApp-Prefix.pch :

    #ifdef TEST #define TEST_CLASS NSClassFromString(@"AppDelegateTests") // any test class #define BUNDLE [NSBundle bundleForClass:TEST_CLASS] #define APP_NAME @"Tests" #else #define BUNDLE [NSBundle mainBundle] #define APP_NAME [[BUNDLE infoDictionary] objectForKey:(NSString *)kCFBundleNameKey] #endif

Esto me permite usar BUNDLE donde quiera decir [NSBundle mainBundle] y también hacer que funcione cuando ejecuto Tests.

La importación de SenTestingKit en Tests-Prefix.pch también acelera la compilación de SenTestingKit Framework y me permite omitir #import <SenTestingKit/SenTestingKit.h> desde la parte superior de todos los archivos de prueba.


La respuesta de Robert en SWIFT 3.0:

func isRunningTests() -> Bool { let environment = ProcessInfo().environment return (environment["XCInjectBundleInto"] != nil); }


Las macros de preprocesador no funcionarán, debe verificar el entorno en tiempo de ejecución.

static BOOL isRunningTests(void) { NSDictionary* environment = [[NSProcessInfo processInfo] environment]; return (environment[@"XCInjectBundleInto"] != nil); }

(Actualizado para Xcode 7.3)


Mire las variables de entorno para ver si se están ejecutando pruebas unitarias. Similar a la respuesta de Robert, pero solo reviso una vez por el bien del rendimiento.

+ (BOOL)isRunningTests { static BOOL runningTests; static dispatch_once_t onceToken; // Only check once dispatch_once(&onceToken, ^{ NSDictionary* environment = [[NSProcessInfo processInfo] environment]; NSString* injectBundle = environment[@"XCInjectBundle"]; NSString* pathExtension = [injectBundle pathExtension]; runningTests = ([pathExtension isEqualToString:@"octest"] || [pathExtension isEqualToString:@"xctest"]); }); return runningTests; }


Pruebo mucho tiempo, encontré un resultado:

No solo agrega la macro preprocesador a su objetivo de prueba unitaria (puede tener muchos métodos que usan variables solo para pruebas unitarias y seguir los métodos @MattDiPasquale),

pero también debe agregar el archivo de condición de conformidad en su objetivo de prueba. debemos recompilar este archivo, porque tiene una nueva macro de preprocesador para este archivo, pero este archivo ha incorporado el destino de la aplicación esa vez que no se configuró la macro del preprocesador.

Espero que esto te ayude


Puede considerar agregar una nueva configuración de compilación.

En xcode 4, haga clic en su proyecto en el navegador de la izquierda.

En la ventana principal, haga clic en su proyecto y luego seleccione la pestaña "información".

Haga clic en el botón "+" para agregar una nueva configuración (puede llamar a la suya "prueba" si lo desea ").

Ahora, haz clic en tu objetivo y ve a la pestaña de configuración de construcción.

Buscar "macros de preprocesador"

Aquí puede agregar macros de preprocesador para su nueva configuración de compilación.

Simplemente haga doble clic en su nueva configuración de "prueba" y agregue TESTING = 1.

Finalmente, edite su esquema de compilación. Seleccione las opciones de prueba para su esquema. Debe haber un menú desplegable de "Configuración de compilación". Seleccione su configuración de "prueba".


Si crea una configuración de compilación de prueba y luego establece la propiedad "Otras banderas rápidas" de su objetivo para "-DESTAR", definirá una macro de PRUEBA que funcionará en su código rápido. Asegúrese de configurarlo en la configuración de compilación de su destino de la aplicación para que pueda usarlo en el código Swift de su aplicación.

Luego, con este conjunto, puedes probar tu código así:

func testMacro() { #if !TEST // skipping over this block of code for unit tests #endif }


Versión modificada de la respuesta de Kev que funciona para mí en Xcode 8.3.2

+(BOOL)isUnitTest { static BOOL runningTests; static dispatch_once_t onceToken; // Only check once dispatch_once(&onceToken, ^{ NSDictionary* environment = [[NSProcessInfo processInfo] environment]; if (environment[@"XCTestConfigurationFilePath"] != nil && ((NSString *)environment[@"XCTestConfigurationFilePath"]).length > 0) { runningTests = true; } else { runningTests = false; } }); return runningTests; }