31 votes

Exécutez des tests logiques dans Xcode 4 sans lancer le simulateur

Je veux exécuter les tests dans Xcode 4 à l'aide de OCUnit sans lancer le simulateur. S'il vous plaît, n'essayez pas de me convaincre, je suis en train de faire les tests unitaires mal ou quelque chose comme ça. J'aime bien faire du TDD de la manière habituelle: écrire l'API de la classe dans les tests, puis faire la classe à passer les tests. Je vais écrire des tests distincts qui sont de bout en bout qui s'exécutent dans le simulateur.

Si il n'y a aucun moyen de le faire, alors s'il vous plaît quelqu'un peut me dire comment faire pour que le harnais de test n'instancier l'ensemble de l'application? Mon application est régie par les événements, et il envoie un tas d'événements lorsqu'il démarre, ce désordre à mes tests.

28voto

Jon Reid Points 9726

Svp quelqu'un peut me dire comment faire pour que le harnais de test n'instancier l'ensemble de l'application? Mon application est régie par les événements, et il envoie un tas d'événements lorsqu'il démarre, ce désordre à mes tests.

J'utilise Xcode 4 est intégré dans le test. Application de l'instanciation peut sembler comme une douleur, mais comme je l'ai écris sur Xcode Test Unitaire avantages et Inconvénients, il permet d'écrire des tests sans faire de distinction entre la logique des tests et des examens. Plus précisément, il me permet d'écrire des tests unitaires pour afficher les contrôleurs.

Voici ce que j'ai à faire pour éviter tout mon séquence de démarrage:

Modifier le régime

  • Sélectionnez l'action de Test
  • Dans "Essai", sélectionnez l'onglet Arguments
  • Désactiver "Utiliser le terme de l'action options"
  • Ajouter une variable d'environnement, paramètre runningTests de YES

Modifier votre délégué d'application

  • Ajoutez ce qui suit à l' -application:didFinishLaunchingWithOptions: dès qu'il fait sens pour:

    #if DEBUG
        if (getenv("runningTests"))
            return YES;
    #endif
    
  • Faire de même pour -applicationDidBecomeActive: mais simplement return.

6voto

Igor Fedorchuk Points 2936

Dans la dernière version de xcode (5.0.2), vous pouvez le faire de manière très simple. Choisissez votre cible de test, onglet "Général". Définissez "Aucun" dans le champ "Cible". Appuyez ensuite sur l'onglet "Phases de construction" et supprimez votre cible principale de "Dépendances cibles".

3voto

dtuckernet Points 5372

Dans votre situation, je suis en supposant que vous avez un Logique des Tests et des examens de la cible (si ce n'est pas nécessaire). Dans vos schémas de configuration vous définissez les objectifs sont construits pour le "Test" schéma. Si votre application tests ne sont pas en cours d'exécution, le simulateur ne se lance pas.

Je soupçonne que vous tentez peut-être d'exécuter la logique des tests' dans une 'Application des tests de cible (comme celui créé par défaut par Xcode). Voir plus au sujet de cette différence ici (et comment mettre en ut jusqu').

2voto

Praveen Kumar Points 788

Il a été souligné dans une précédente réponse à cette logique tests sont la bonne chose à faire pour ce scénario. J'ai eu des temps difficiles pour en arriver la logique des tests de travailler avec XCode Version 4.3.2 (4E2002). En regardant d'Apple de l'échantillon de test de l'unité de projet m'a aidé à comprendre comment faire cela avec une séparation claire. Dans cet exemple, la logique de tests tests de fichiers à partir de la bibliothèque de la cible, pas l'application cible. Le modèle a été encapsulé dans une bibliothèque qui a ensuite été lié à la cible principale et de la logique des tests de cible. L'application cible ne contenait que les vues et les contrôleurs.

Basé sur ce modèle, c'est ce que j'ai fait pour obtenir ma logique, tests de fonctionner correctement. Créer une nouvelle cible (Cocoa Touch Bibliothèque Statique) et déplacer tous les fichiers à la logique testé (généralement tous les modèles) pour cette nouvelle cible. En vertu de "Phases de construction" paramètres d'ajouter cette nouvelle bibliothèque "Lien Binaire Avec les Bibliothèques" de votre application cible et de la logique des tests de cible.

Je peux imaginer que ces instructions sont peu déroutant. Si vous disséquer l'exemple de projet qui est mentionné ci-dessus, vous obtiendrez une meilleure idée.

2voto

mxcl Points 5921

Remarque, non testé sur Xcode 5.

J'ai utilisé @jon-reid réponse, mais a constaté que Xcode ajoute de l'environnement des variables à l'xcuserstated partie de XcodeProjects, et ceux-ci sont propres à l'utilisateur et généralement pas engagés dans le référentiel. Donc je swizzle mon AppDelegate afin de remplacer son chargement:

@implementation MyAppDelegate (Testing)

+ (void)initialize {
    SEL new = @selector(application:didFinishLaunchingWithOptions:);
    SEL orig = @selector(swizzled_application:didFinishLaunchingWithOptions:);
    Class c = [self class];
    Method origMethod = class_getInstanceMethod(c, orig);
    Method newMethod = class_getInstanceMethod(c, new);

    if (class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
        class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    } else {
        method_exchangeImplementations(origMethod, newMethod);
    }
}

- (BOOL)swizzled_application:(id)app didFinishLaunchingWithOptions:(id)opts {
    return YES;
}

@end

Notez que la suivante est plus simple et fonctionne toujours, même si je ne suis pas sûr qu'il est fiable:

@implementation MyAppDelegate (Testing)

- (BOOL)application:(id)app didFinishLaunchingWithOptions:(id)opts {
    return YES;
}

@end

Cela fonctionne parce que les catégories de méthodes de charger dynamiquement des composants (comme le test de bundle), l'emportent. Swizzling se sent plus sûr de bien.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X