Introduction aux tests sur iOS

Personne ne veut expédier un logiciel buggy. S'assurer que vous publiez une application mobile de la plus haute qualité nécessite beaucoup plus qu'un processus d'assurance qualité manuel piloté par l'homme. De nouveaux appareils et systèmes d'exploitation sont mis à la disposition du public chaque année. Cela signifie qu'il existe une combinaison en constante expansion de tailles d'écran et de versions de systèmes d'exploitation sur laquelle vous devez tester votre application mobile. Non seulement cela prendrait beaucoup de temps, mais essayer de tester votre application iOS par des tests manuels néglige tout un élément du processus de génie logiciel moderne, les tests d'assurance qualité automatisés..

Dans le monde actuel, il existe de nombreux outils disponibles qui peuvent être utilisés pour tester automatiquement le logiciel que vous écrivez. Certains de ces outils sont gérés via un modèle open source, mais il existe également un ensemble de base fourni par Apple. À chaque nouvelle version du SDK iOS, Apple a continué à manifester son engagement à améliorer les outils disponibles permettant aux développeurs de tester le code écrit. Pour les développeurs iOS débutant dans les tests automatisés et souhaitant se lancer, les outils Apple constituent un bon point de départ..

1. Apple fournit des outils utiles

Ce tutoriel va fournir des instructions pour utiliser un outil fourni par Apple pour les tests automatisés, XCTest. XCTest est la structure de test unitaire d'Apple. Le test unitaire est le type de test automatisé qui vérifie le code au niveau le plus bas. Vous écrivez du code Objective-C qui appelle des méthodes à partir de votre code "de production" et vérifiez que le code testé teste réellement ce qu'il est censé faire. Les variables sont-elles correctement définies? La valeur de retour est-elle correcte??

Les tests écrits avec la structure XCTest peuvent être exécutés de manière répétée sur le code de votre application pour vous aider à savoir avec certitude que vous créez un produit exempt de bogues, car les nouvelles modifications de code ne violent pas les fonctionnalités existantes..
Par défaut, chaque nouveau projet Xcode est créé avec un bon point de départ pour l'écriture de tests unitaires. Cela comprend trois choses:

  • une cible séparée pour vos tests
  • un groupe pour vos cours de test
  • un exemple de test


Explorons la structure d'un test d'unité iOS. Un test unitaire individuel est représenté comme une méthode unique dans toute sous-classe de XCTestCase où la méthode retourne vide, ne prend aucun paramètre et le nom de la méthode commence par tester.

- (void) testQuelque chose 

Heureusement, Xcode facilite la création de scénarios de test. Avec les nouveaux projets Xcode, un scénario de test initial est créé pour vous dans un groupe de fichiers distinct dont le nom est suffixé par le mot. Des tests.

2. Création de votre premier test unitaire iOS

J'ai créé un exemple de projet qui peut être utilisé comme référence pour les exemples fournis dans ce tutoriel. Téléchargez le projet depuis GitHub et ouvrez-le dans Xcode.

Étape 1: Créer la classe de cas de test

Dans le projet exemple, vous pouvez trouver le groupe de tests dans le dossier nommé JumblifyTests.

Pour créer votre premier cas de test, cliquez avec le bouton droit sur le groupe de fichiers., JumblifyTests, et sélectionnez Nouveau fichier. Choisir Classe de cas de test du iOS> Source section et donnez un nom à la nouvelle sous-classe.

La convention de dénomination typique consiste à nommer le scénario de test de sorte qu'il s'agisse du nom de la classe correspondante testée, suffixé de Des tests. Puisque nous allons tester le JumblifyViewController classe, nommez le XCTestCase sous-classe JumblifyViewControllerTests.

Étape 2: Supprimer le code de la plaque chauffante

Dans le tout nouveau XCTestCase sous-classe, vous verrez quatre méthodes. Deux d'entre eux sont des tests eux-mêmes. Pouvez-vous identifier qui ils sont? Rappelez-vous que les noms des méthodes de test commencent par le mot "test".

Si vous ne le comprenez pas, les méthodes de test créées par défaut sont testExample et testPerformanceExample.

Supprimez les deux tests, car nous allons écrire le nôtre à partir de zéro. Les deux autres méthodes, installer et abattre, sont remplacés par la superclasse, XCTestCase. Ils sont uniques en ce que installer et abattre sont appelés avant et après chaque méthode de test est appelée respectivement. Ce sont des emplacements utiles pour centraliser le code à exécuter avant ou après l'appel de chaque méthode de test. Les tâches telles que l'initialisation ou le nettoyage commun vont ici.

Étape 3: Connectez votre test à votre classe sous test

Importer le fichier d'en-tête du JumblifyViewController class et ajouter une propriété de type JumblifyViewController au XCTestCase sous-classe.

@property (nonatomic) JumblifyViewController * vcToTest;

dans le installer méthode, initialisez la propriété comme indiqué ci-dessous.

- (void) setUp [super setUp]; self.vcToTest = [[JumblifyViewController alloc] init]; 

Étape 4: écrivez un test

Nous allons maintenant écrire un test pour tester la reverseString: méthode du JumblifyViewController classe.

Créer une méthode de test qui utilise la méthode instanciée vcToTest objet pour tester le reverseString: méthode. Dans cette méthode de test, nous créons un NSString objet et le passer à celui du contrôleur de vue reverseString: méthode. Il est de pratique courante de donner à votre test un nom explicite pour indiquer clairement ce que le test teste..

- (void) testReverseString NSString * originalString = @ "himynameisandy"; NSString * reverseString = [self.vcToTest reverseString: originalString]; 

À ce stade, nous n’avons encore rien fait d’utile, car nous n’avons pas testé la reverseString: méthode pour le moment. Ce que nous devons faire, c’est comparer la sortie du reverseString: méthode avec ce que nous nous attendons à la sortie.

le XCTAssertEqualObjects function fait partie du framework XCTest. Le framework XCTest fournit de nombreuses autres méthodes pour formuler des assertions sur l'état de l'application, telles que l'égalité des variables ou les résultats de l'expression booléenne. Dans ce cas, nous avons indiqué que deux objets doivent être égaux. S'ils le sont, le test réussit et s'ils ne le sont pas, le test échoue. Consultez la documentation d'Apple pour obtenir une liste complète des assertions fournies par le framework XCTest..

- (void) testReverseString NSString * originalString = @ "himynameisandy"; NSString * reverseString = [self.vcToTest reverseString: originalString]; NSString * attendueReversedString = @ "ydnasiemanymih"; XCTAssertEqualObjects (attenduReversedString, reverseString, @ "La chaîne inversée ne correspond pas à l'inverse attendu");

Si vous essayez de compiler le code à ce stade, vous remarquerez un avertissement lorsque vous essayez d'appeler reverseString: du cas de test. le reverseString: méthode est une méthode privée du JumblifyViewController classe. Cela signifie que les autres objets ne peuvent pas appeler cette méthode car elle n’est pas définie dans le fichier d’en-tête du fichier. JumblifyViewController classe.

Bien que l'écriture de code testable soit la devise de nombreux développeurs, nous ne souhaitons pas modifier inutilement notre code sous test. Mais comment appelle-t-on le privé reverseString: méthode du JumblifyViewController classe dans nos tests? Nous pourrions ajouter une définition publique de la reverseString: méthode au fichier d'en-tête du JumblifyViewController classe, mais cela casse le motif d'encapsulation.

Étape 5: Ajout d'une catégorie privée

Une solution consiste à ajouter une catégorie privée sur le JumblifyViewController classe pour exposer le reverseString: méthode. Nous ajoutons cette catégorie au XCTestCase sous-classe, ce qui signifie qu'il est uniquement disponible dans cette classe. En ajoutant cette catégorie, le scénario de test sera compilé sans avertissements ni erreurs..

@interface JumblifyViewController (Test) - (NSString *) reverseString: (NSString *) stringToReverse; @fin

Étape 6: Lancer le test

Lançons nos tests pour s'assurer qu'ils passent. Il existe plusieurs manières d'exécuter des tests unitaires pour une application iOS. Je suis un junkie au raccourci clavier; ma technique la plus utilisée pour exécuter mes tests unitaires pour mon application consiste à appuyer sur Command-U. Ce raccourci clavier exécutera tous les tests pour votre application. Vous pouvez également effectuer la même action en sélectionnant Tester du Produit menu.

Au fur et à mesure que votre suite de tests s'agrandit, ou si vous souhaitez implémenter un développement piloté par les tests, vous constaterez que l'exécution de votre suite de tests peut prendre trop de temps. Ou cela pourrait gêner votre flux de travail. Une commande très utile, enfouie dans le menu de Xcode, dont je suis tombé amoureux est Commande-Option-Contrôle-U. Ce raccourci déclenche une commande qui exécute le test de votre curseur. Une fois votre suite de tests étoffée et finalisée, vous devez toujours exécuter la suite de tests complète. L'exécution d'un test individuel est utile lorsque vous écrivez un nouveau test ou que vous déboguez un test en échec..

La commande pour exécuter un test est complétée par Commande-Option-Contrôle-G, qui relance le dernier test. Cela peut être la suite de tests complète ou uniquement le test le plus récent sur lequel vous travaillez. C'est également utile si vous avez quitté le test sur lequel vous travaillez et que vous êtes toujours en train de le déboguer..

Étape 7: Examen des résultats

Vous pouvez voir les résultats de votre test à quelques endroits. Un de ces endroits est le Test Navigator sur la droite.

Une autre option est de regarder la gouttière du Éditeur de source.

Dans l'un ou l'autre de ces deux endroits, un clic sur le losange vert avec une coche blanche relancera ce test particulier. En cas d'échec du test, vous verrez un losange rouge avec une croix blanche au centre. En cliquant dessus, vous pourrez également réexécuter ce test particulier..

3. Nouveau dans Xcode 6

Xcode 6 a introduit deux nouveaux ajouts intéressants aux tests unitaires sur iOS et OS X, testant la fonctionnalité asynchrone et mesurant les performances d'un code spécifique.

Test Asynchrone

Avant Xcode 6, il n'existait aucun moyen efficace de tester le code asynchrone. Si votre test unitaire a appelé une méthode contenant une logique asynchrone, vous ne pouvez pas vérifier la logique asynchrone. Le test se terminerait avant l'exécution de la logique asynchrone dans la méthode sous test.

Pour tester le code asynchrone, Apple a mis en place une API permettant aux développeurs de définir une attente à remplir pour que le test se termine avec succès. Le flux est le suivant: définissez une attente, attendez que l'attente soit remplie et remplissez-la lorsque le code asynchrone a fini de s'exécuter. Regardez l'exemple ci-dessous pour plus de précisions..

- (void) testDoSomethingThatTakesSomeTime XCTestExpectation * completionExpectation = [self expectationWithDescription: @ "Méthode longue"]; [self.vcToTest doSomethingThatTakesSimeTimesWithCompletionBlock: ^ (résultat * NSString) XCTAssertEqualObjects (@ "résultat", résultat, @ "Le résultat n'était pas correct!"); [completionExpectation remplir]; ]; [self waitForExpectationsWithTimeout: 5.0 gestionnaire: nil]; 

Dans cet exemple, nous testons la faire quelque chosequi prend quelquefois fois avecAchèvementBloc méthode. Nous voulons articuler le succès ou l'échec de notre test sur la valeur renvoyée dans le bloc d'achèvement appelé par la méthode testée..

Pour ce faire, nous définissons une attente au début de la méthode de test. À la fin de la méthode de test, nous attendons que les attentes soient satisfaites. Comme vous pouvez le constater, nous pouvons également passer un paramètre de délai d'attente.

L'assertion réelle du test est faite à l'intérieur du bloc de complétion de la méthode à tester dans laquelle nous remplissons également l'attente que nous avons définie précédemment. Par conséquent, lorsque le test est exécuté, il attend que l'attente soit remplie ou échoue si le délai d'attente expire et si l'attente n'est pas remplie..

Test de performance

Un autre ajout aux tests unitaires dans Xcode 6 est la possibilité de mesurer les performances d'un morceau de code. Cela permet aux développeurs de mieux comprendre les informations de minutage spécifiques du code en cours de test..

Avec les tests de performance, vous pouvez répondre à la question "Quel est le temps moyen d’exécution de ce morceau de code?" Si une section est particulièrement sensible aux changements en termes de temps d'exécution, vous pouvez utiliser des tests de performances pour mesurer le temps nécessaire à son exécution..

Vous pouvez également définir une heure d'exécution de base. Cela signifie que si le code testé diffère considérablement de cette base, le test échoue. Xcode exécutera à plusieurs reprises le code en cours de test et mesurera son temps d'exécution. Pour mesurer les performances d’un morceau de code, utilisez la commande mesureBloc: API comme indiqué ci-dessous.

- (void) testPerformanceReverseString NSString * originalString = @ "himynameisandy"; [self measureBlock: ^ [self.vcToTest reverseString: originalString]; ]; 

Cliquez sur le message d'information qui apparaît.

Définir ou modifier le temps d'exécution de base pour le test de performance.

Conclusion

Dans ce tutoriel, vous avez appris à utiliser Xcode pour créer des tests unitaires afin de vérifier une application iOS de manière programmatique et automatisée. Essayez-le, sur une base de code existante ou quelque chose de nouveau. Que vous vous engagiez pleinement dans les tests unitaires ou que vous ajoutiez quelques tests ici et là, vous n’ajoutez de la valeur à votre projet qu’en écrivant des logiciels plus vérifiés et moins enclins à rompre avec les modifications futures. Les tests unitaires ne sont que le début des tests logiciels automatisés. Il existe plusieurs couches de tests supplémentaires que vous pouvez ajouter à une application iOS..