« Tester, c’est douter ! », oui mais souvent, douter évite de grosses boulettes !!
C’est pour cela que j’ai décidé de publier une série de tutoriels sur les tests unitaires en programmation Swift.
Mais voyons en premier ce qu’est un test unitaire et quel est son but !
Donc, un test unitaire permet de contrôler le bon fonctionnement d’une portion de votre programme : classe, structure, méthode….
Cela permet d’éviter une régression fonctionnelle du code lorsque l’on fait des updates, des upgrades ou simplement lors d’un refactoring.
Les tests unitaires peuvent également servir à tester l’interface graphique (UITests), Xcode permet de le faire très simplement, cela fera l’objet d’un autre tuto.
Enfin, et cela n’est pas la moindre de leurs utilités, les tests unitaires servent aussi pour trouver et corriger des bugs !
Donc, écrire des tests n’est sans doute pas la partie la plus glamour du développement d’une application mobile, mais c’est un très bon investissement pour se simplifier la vie lors du développement et de la maintenance !
Convaincus ? Alors on va démarrer en douceur…
Créons donc une nouvelle application, que j’ai nommé « UnitTestsTuto1 ». Pour y inclure d’office les tests unitaires, il faut cocher les cases « Include Unit Tests » et « Include UI Tests ».
Nota : si vous désirez inclure des tests unitaires à un programme existant, cela se fait sous XCode à partir du menu « File » -> « New » -> « Target » -> « IOS UI Testing Bundle » ou « IOS Unit Testing Bundle ».
Ensuite, nous il faut quelque chose à tester… J’ai donc créé une structure « Dog », dans laquelle un chien peut avoir les propriétés suivantes : un nom, une date de naissance, un sexe, mais pas forcément un pedigree ou une caractéristique particulière :
Et maintenant, si l’on regarde le projet « UnitTestsTuto1 », on constate que XCode à créé 2 dossiers « UnitTestsTuto1Tests » et « UnitTestsTuto1UITests ».
Dans cette introduction aux tests unitaires, nous ne nous occuperons que du premier.
Ouvrez donc le fichier « UnitTestsTuto1Tests.swift » situé dans le dossier « UnitTestsTuto1Tests » :
Dans ce template, nous voyons que le framework « XCTest » est importé. Cela est obligatoire pour réaliser des tests.
Nous importons également le projet grâce à la ligne « @testable import UnitTeststTuto1 ». Cela est obligatoire pour accéder à l’AppDelegate et à l’ensemble des classes et méthodes de l’application à tester (sauf celles qui sont déclarées comme « Private »).
Ensuite, plusieurs méthode sont créés :
- setUp(), qui est appelée avant l’invocation de chaque méthode de test de la classe.
- tearDown(), qui est appelée après l’invocation de chaque méthode de test de la classe.
- testExample(), c’est un exemple de test. Attention, chaque méthode de test doit être préfixée par « test ».
- testPerformanceExample(), permet de faire des tests de performance du code. Je ferai sans doute un autre tuto la dessus.
Il est conseillé de décomposer un tests en 3 parties, selon le schéma « AAA » : « Arrange, Act, Assert » (Arranger, Agir, Auditer) :
- Arrange : on définit les variables, objets… nécessaires au bon déroulement du tests.
- Act : on exécute l’action que l’on souhaite tester (en général, c’est là que l’on exécute la méthode à tester).
- Assert : on vérifie que le résultat est conforme à ce qui est attentdu.
Enfin, un test doit également être « FIRST » : « Fast, Independent/Isolated, Repeatable, Self-validating, timely » :
- Fast : un test doit être rapide, sinon personne ne l’exécute.
- Independent : les tests doivent êtres indépendants les uns des autres.
- Repeatable : On doit obtenir le même résultat à chaque fois que l’on exécute le test.
- Timely : idéalement, les tests doivent êtres écrits avant le code de production qu’ils sont censés tester.
Allez, fini le baratin, place au code ! Voici donc notre premier test unitaire sur notre structure Dog :
Pour ce simple test, j’ai fusionné les étapes « Arrange et Act » lors de la définition d’une constante « dog ».
Ensuite, grâce à l’instruction « XCTAssertEqual », je vérifie que ma variable à été correctement initialisée.
Pour lancer le test unitaire, il suffit de cliquer sur le petit losange en face de la classe :
Si le test passe, le losange devient vert.
Par contre, si je change par exemple le nom du chien, le test échoue :
Lorsque l’on veut lancer plusieurs tests à la fois, on peut le faire depuis le navigateur de tests (Command-6) :
Voilà, notre premier test unitaire est fait !
Mais comment savoir si tout le code est testé ? C’est le moment de parler de la couverture du code !
Si vous éditez les Scheme du projet, vous pouvez cocher la case « Code Coverage » (pour toutes les cibles) :
Ensuite, relancez tous les tests… et ouvrez le navigateur de rapports (Command-8) :
Ici, nous avons testé le code à 80 %… et oui, l’UI n’est pas testée 😦 .