web-dev-qa-db-fra.com

Projet Xcode comment détecter une cible par programme ou comment utiliser env vars

Je souhaite effectuer un test d’application qui analyse certains JSON, les enregistre dans des données de base et lit certains objets.

Comment mon code peut-il savoir s'il est exécuté dans le cadre d'un test ou d'une exécution normale? Juste un moyen de savoir "sommes-nous en cible de test"? Parce que l'application, lorsqu'elle démarre, déclenche une série de requêtes pour renseigner mon coredata avec les informations du serveur. Je ne veux pas que cela se produise lors de mes tests. Je veux lancer l'application, lire HARDCODED json à partir d'un fichier et le stocker en utilisant les mêmes méthodes que dans COREDATA, et vérifier les résultats.

Si quelqu'un pouvait expliquer comment transmettre des paires clé-valeur spécifiques cible par cible pouvant être lues à partir de l'application, je serais encore plus ravi.

28
jpswain

Peu importe ... compris que c'est dans "Schémas" que vous définissez ceci.

Par exemple, si vous souhaitez que TARGET = TEST soit disponible pendant le test et que TARGET = RUN soit affiché pendant l'exécution, définissez-le simplement dans votre modèle> variables d'environnement> nom/valeur.

Ensuite, depuis votre application, vous pouvez faire:

[[[NSProcessInfo processInfo] environment] objectForKey:@"TARGET"]

Utilisation des paramètres de construction avec les macros du préprocesseur DID NE fonctionne PAS parce que ma cible de test (pour les tests d'application/d'intégration) dépend de ma cible principale (non testée). La cible principale est donc créée en premier. ce qui est exécuté et vous vous retrouvez avec les macros du préprocesseur cible même si vous suivez celles définies dans la cible que vous avez exécutée. Si quelque chose me manque ici, n'hésitez pas à expliquer.

34
jpswain

Si, par "cible de test", vous entendez vos tests unitaires (c.-à-d. Product > Test ou ⌘U), vous pouvez ajouter une macro de préprocesseur à la cible et rechercher cette macro dans votre code. Cela permet quelque chose comme ce qui suit:

#ifdef TEST
  // Load the hard-coded data.
#else
  // Load data from the server.
#endif

Pour ce faire, cliquez sur votre fichier de projet dans le navigateur de projet, sélectionnez votre cible de test, cliquez sur l'onglet Build Settings, recherchez "macros", double-cliquez sur l'option Preprocessor Macros et ajoutez-en une!

10
Chris Doble

Il y a deux situations à traiter:

  1. Exécutez du code si une certaine cible telle que Tests est sélectionnée, et
  2. #import conditionnellement certains fichiers pour une cible donnée telle que Tests.

Code de cible pour la cible de test:

Créez une macro dans votre fichier ProjectName-Prefix.pch comme suit:

#define IsTestTarget [[[[NSProcessInfo processInfo] environment][@"XCInjectBundle"] pathExtension] isEqualToString:@"xctest"]

puis appelez-le n'importe où dans l'application:

if (IsTestTarget) {
    //Do something specific for test target;
} else {
    //Otherwise do something else
}

Conditionnel #import:

Pour #import certains fichiers lorsque la cible Tests est sélectionnée, vous devez ajouter un Preprocessor Macro à votre cible Test et l'utiliser comme suit:

#ifdef APPTESTS
    #import "TestSpecificFile.h"
#else
    #import "SomeOtherFile.h"
#endif 

Voici comment vous pouvez ajouter un Preprocessor Macro:

enter image description here

6
Yas T.

Vous pouvez utiliser la fonction ci-dessous.

+(BOOL)  isRunningTests
{
    NSDictionary* environment = [[NSProcessInfo processInfo] environment];
    NSString* injectBundle = environment[@"XCInjectBundle"];
    return [[injectBundle pathExtension] isEqualToString:@"xctest"];
}
5
muzz

Habituellement, dans Unit Test, les programmeurs utilisent des classes et des fonctionnalités moqueuses. Vous pouvez créer une classe avec une appartenance à la cible only pour la cible de test.

@interface MockClass : NSObject

@end

 Target Membership Screenshot

Ensuite, dans le code de l'application, vous pouvez vérifier si la classe existe en utilisant la fonction NSClassFromString (qui retournera Nil pour la cible non incluse dans l'appartenance à la cible de la classe, dans ce cas-ci, cible non testée.

if (NSClassFromString(@"MockClass")) {
    //Test Target
} else {
    //App Target
}

Et vous pouvez bien sûr le faire fonctionner

BOOL isUnitTest(){
    return NSClassFromString(@"MockClass") != Nil;
}
0
Benny Davidovitz