Tester votre code est agaçant, mais ne pas le faire peut avoir des conséquences beaucoup plus graves! Dans cet article, nous utiliserons le développement piloté par les tests pour écrire et tester notre code plus efficacement..
Depuis le début de l'ère informatique, les programmeurs et les bugs se sont battus pour la suprématie. C'est un événement inévitable. Même les plus grands programmeurs sont en proie à ces anomalies. Aucun code n'est sécurisé. C'est pourquoi nous faisons des tests. Les programmeurs, au moins sains d'esprit, testent leur code en l'exécutant sur des machines de développement pour s'assurer qu'il fait ce qu'il est supposé faire..
Développement piloté par les tests est une technique de programmation qui nécessite l’écriture simultanée du code réel et du code de test automatisé. Cela garantit que vous testez votre code et vous permet de retester votre code rapidement et facilement, car il est automatisé..
Le développement piloté par les tests, ou TDD comme nous l'appellerons désormais, s'articule autour d'un cycle de développement itératif court qui ressemble à ceci:
Avez-vous déjà délibérément omis de tester un programme pour les raisons suivantes:
La plupart du temps, rien ne se passe et vous réussissez à passer votre code à la production sans aucun problème. Mais parfois, une fois que vous êtes passé à la production, tout va mal. Vous êtes coincé à réparer une centaine de trous dans un bateau en train de couler, et de plus en plus apparaissent chaque minute. Tu fais ne pas vouloir te retrouver dans cette situation.
TDD était censé éliminer nos excuses. Lorsqu'un programme utilisant TDD a été développé, il nous permet d'apporter des modifications et de tester rapidement et efficacement. Tout ce que nous avons à faire est de lancer les tests automatisés, et le tour est joué! Si tous les tests automatisés réussissent, nous pouvons continuer, sinon, cela signifie simplement que nous avons rompu quelque chose avec les modifications. En sachant quelles parties exactes du test ont échoué, cela nous permet également de déterminer facilement quelle partie des modifications il a rompues, ce qui facilite la correction des bogues.
Il existe une multitude de cadres de tests automatisés PHP que nous pouvons utiliser. PHPUnit est l’un des frameworks de test les plus utilisés..
PHPUnit est un excellent framework de test, qui peut facilement être intégré dans vos propres projets, ou d'autres projets construits sur des frameworks PHP populaires..
Pour nos besoins cependant, nous n’aurons pas besoin de la multitude de fonctions offertes par PHPUnit. Au lieu de cela, nous choisirons de créer nos tests en utilisant un framework de test beaucoup plus simple, appelé SimpleTest..
Dans les étapes suivantes, supposons que nous développons une application de livre d'or où tout utilisateur peut ajouter et afficher des entrées de livre d'or. Supposons que le balisage est terminé et que nous créons simplement une classe qui contient le logique d'application du livre d'or, à l'endroit où l'application insère et lit dans la base de données. La partie lecture de cette classe est ce que nous allons développer et tester.
C'est sans doute l'étape la plus facile de toutes. Même ce gars pourrait le faire:
Téléchargez SimpleTest ici et extrayez-le dans un dossier de votre choix - de préférence le dossier dans lequel vous allez développer votre code, ou votre chemin include_path PHP pour un accès facile.
Pour ce tutoriel, j'ai configuré le dossier comme suit:
Index.php lancera guestbook.php, invoquera la méthode view et affichera les entrées. Dans le dossier classes, nous placerons la classe guestbook.php, et dans le dossier test, nous placerons la bibliothèque la plus simple..
La deuxième étape, qui est en fait la plus importante, consiste à créer vos tests. Pour cela, vous devez vraiment planifier et réfléchir à ce que votre fonction fera, aux entrées possibles qu’elle obtiendra et aux sorties correspondantes qu’elle enverra. Cette étape ressemble à une partie d'échecs. Vous devez tout savoir sur votre adversaire (le programme), y compris toutes ses faiblesses (erreurs possibles) et ses forces (que se passe-t-il si le programme fonctionne correctement).
Donc, pour notre application guestbook, établissons les schémas suivants:
Array ([0] => Array (['name'] = "Bob" ['message'] = "Bonjour, je suis Bob.") [1] => Array (['name'] = "Tom" ['message'] = "Bonjour, je suis Tom."))
Maintenant, nous pouvons écrire notre premier test. Commençons par créer un fichier appelé guestbook_test.php dans le dossier de test.
Ensuite, convertissons ce que nous avons déterminé à l'étape deux,.
ajouter ("Bob", "Bonjour, je suis Bob."); $ guestbook-> add ("Tom", "Bonjour, je suis Tom."); $ entry = $ guestbook-> viewAll (); $ count_is_greater_than_zero = (count ($ entrées)> 0); $ this-> assertTrue ($ count_is_greater_than_zero); $ this-> assertIsA ($ entrées, 'tableau'); foreach ($ entrées en tant que $ entry) $ this-> assertIsA ($ entry, 'array'); $ this-> assertTrue (isset ($ entry ['name']))); $ this-> assertTrue (isset ($ entry ['message']))); function testViewGuestbookWithNoEntries () $ guestbook = new Guestbook (); $ guestbook-> deleteAll (); // Supprime d'abord toutes les entrées pour que nous sachions qu'il s'agit d'une table vide $ entries = $ guestbook-> viewAll (); $ this-> assertEqual ($ entrées, array ());Les assertions permettent de s’assurer qu’une certaine chose est ce qu’elle est supposée être. En gros, elle garantit que le retour est ce que vous attendez. Par exemple, si une fonction est supposée retourner vrai si elle réussit, alors dans notre test, nous devrions affirmer que la valeur de retour est égale à true.
Comme vous pouvez le voir ici, nous testons l'affichage du livre d'or avec des entrées et sans. Nous vérifions si ces deux scénarios satisfont nos critères de la deuxième étape. Vous avez probablement aussi remarqué que chacune de nos fonctions de test commence par le mot «test». Nous l'avons fait parce que, lorsque SimpleTest exécute cette classe, toutes les fonctions commençant par le mot 'test' seront recherchées et exécutées..
Dans notre classe de test, nous avons également utilisé certaines méthodes d'assertion, telles que assertTrue, assertIsA et assertEquals. La fonction assertTrue vérifie si une valeur est vraie ou non. AssertIsA vérifie si une variable est d'un certain type ou d'une certaine classe. Et enfin, assertEquals vérifie si une variable est totalement égale à une certaine valeur.
Il existe d'autres méthodes d'assertion fournies par SimpleTest, à savoir:
assertTrue ($ x) | Échec si $ x est faux |
assertFalse ($ x) | Échec si $ x est vrai |
assertNull ($ x) | Échec si $ x est défini |
assertNotNull ($ x) | Échec si $ x n'est pas défini |
assertIsA ($ x, $ t) | Echec si $ x n'est pas la classe ou le type $ t |
assertNotA ($ x, $ t) | Échec si $ x appartient à la classe ou au type $ t |
assertEqual ($ x, $ y) | Échec si $ x == $ y est faux |
assertNotEqual ($ x, $ y) | Échec si $ x == $ y est vrai |
assertWithinMargin ($ x, $ y, $ m) | Échec si abs ($ x - $ y) < $m is false |
assertOutsideMargin ($ x, $ y, $ m) | Échec si abs ($ x - $ y) < $m is true |
assertIdentical ($ x, $ y) | Échec si $ x == $ y est faux ou si le type ne correspond pas |
assertNotIdentical ($ x, $ y) | Échec si $ x == $ y est vrai et que les types correspondent |
assertReference ($ x, $ y) | Échec sauf si $ x et $ y sont la même variable |
assertClone ($ x, $ y) | Échec sauf si $ x et $ y sont des copies identiques |
assertPattern ($ p, $ x) | Échec sauf si la regex $ p correspond à $ x |
assertNoPattern ($ p, $ x) | Échec si la regex $ p correspond à $ x |
expectError ($ x) | Avale toute erreur de correspondance à venir |
affirmer ($ e) | Échec sur l'objet d'attente attendu échoué $ e |
La liste des méthodes d'assertion est une gracieuseté de http://www.simpletest.org/en/unit_test_documentation.html
Une fois que vous avez fini d'écrire le code, vous devriez lancer le test. La première fois que vous exécutez le test, il Doit échouer. Si ce n'est pas le cas, cela signifie que votre test ne teste rien.
Pour lancer votre test, lancez simplement guestbook_test.php dans votre navigateur. Vous devriez voir ceci en premier:
Ceci est dû au fait que nous n’avons pas encore créé notre cours de livre d’or. Pour ce faire, créez guestbook.php dans votre dossier de classes. La classe devrait contenir les méthodes que nous prévoyons d’utiliser, mais ne devrait encore rien contenir au début. Rappelez-vous, nous écrivons les tests d'abord avant écrire n'importe quel code.
Lorsque vous relancez le test, il devrait ressembler à ceci:
Comme nous pouvons le voir ici, notre test gagne maintenant en échouant. Cela signifie que notre test est maintenant prêt à recevoir une "réponse".
Image reproduite avec l'aimable autorisation de http://www.gamercastnetwork.com/forums
Étape 5. Répondez à votre test en écrivant du code
À un moment donné, nous avons tous ressenti cela lorsque nous programmons.
Image reproduite avec l'aimable autorisation de http://fermentation.typepad.com/fermentationMaintenant que le test automatisé fonctionne, nous pouvons commencer à écrire du code. Ouvrez votre guestbook.php classe et commence à créer la réponse à ton test.
'Kirk', 'message' => 'Bonjour, je suis Kirk.' ), array ('name' => 'Ted', 'message' => 'Bonjour, je suis Ted.')); public function viewAll () // Ici, nous devrions récupérer tous les enregistrements de la base de données. // Ceci est simulé en retournant le tableau $ _entries return self :: $ _ entrées; public function add ($ name, $ message) // Ici, nous simulons une insertion dans la base de données en ajoutant un nouvel enregistrement dans le tableau $ _entries // Voici comment procéder: self :: $ _ entrées [] = array ('name' => $ name, 'message' => $ message); self :: $ _ entries [] = array ('notname' => $ name, 'notmessage' => $ message); // oups, il y a un bug ici quelque part return true; public function deleteAll () // Nous venons de définir le tableau $ _entries pour simuler self :: $ _ entries = array (); retourne vrai;Cette classe guestbook.php a volontairement des bugs, nous pouvons donc voir à quoi ça ressemble si notre test échoue.
Une fois notre test effectué, nous devrions voir quelque chose comme ceci:
La sortie de test nous montre dans quel test et dans quelle assertion notre code a échoué. De là, on peut facilement identifier les lignes 16 et 17 était l’affirmation qui a jeté l’erreur.
assertTrue (isset ($ entry ['nom']])); $ this-> assertTrue (isset ($ entry ['message']))) ;?Cela nous indique clairement que le tableau d'entrées renvoyé n'avait pas la clé de tableau correcte. Sur cette base, nous saurons facilement quelle partie de notre code a mal tourné.
$ name, 'message' => $ message); //fixé! retourne vrai; ?Maintenant, quand nous relancerons notre test, il devrait nous montrer:
Étape 6. Refactoriser et affiner votre code
Images reproduites avec l'aimable autorisation de http://www.osborneink.com et http://phuketnews.phuketindex.comComme le code que nous testons ici est assez simple, nos tests et la correction des bogues n'ont pas duré très longtemps. Mais s'il s'agissait d'une application plus complexe, vous auriez dû apporter plusieurs modifications à votre code, le rendre plus propre afin qu'il soit plus facile à gérer, et bien d'autres choses encore. Le problème avec ceci, cependant, est que le changement introduit généralement des bogues supplémentaires. C'est là qu'intervient notre test automatisé. Une fois les modifications apportées, nous pouvons simplement les réexécuter. Si ça passe toujours, alors ça veut dire qu'on n'a rien cassé. Si cela échoue, nous savons que nous avons commis une erreur. Cela nous indique également où se trouve le problème et, espérons-le, comment nous pourrons le résoudre..
Étape 7. Rincer et répéter
Image reproduite avec l'aimable autorisation de http://www.philstockworld.comFinalement, lorsque votre programme nécessite de nouvelles fonctionnalités, vous devrez écrire de nouveaux tests. C'est facile! Rincez et répétez les procédures à partir de l'étape 2 (car vos fichiers SimpleTest doivent déjà être configurés) et recommencez le cycle..
Conclusion
Il y a beaucoup plus d'articles de développement fondés sur les tests et beaucoup plus de fonctionnalités dans SimpleTest que ce qui était affiché dans cet article, comme des objets fictifs, des stubs, qui facilitent la création de tests. Si vous souhaitez en savoir plus, la page de développement pilotée par les tests de Wikipedia devrait vous mettre sur la bonne voie. Si vous souhaitez utiliser SimpleTest comme infrastructure de test, parcourez la documentation en ligne et assurez-vous de revoir ses autres fonctionnalités..
Les tests font partie intégrante du cycle de développement, cependant, il est trop souvent la première chose à couper lorsque les délais sont imminents. J'espère qu'après avoir lu cet article, vous comprendrez à quel point il est utile d'investir dans un développement piloté par des tests..
Quelles sont vos pensées sur le développement piloté par les tests? Est-ce quelque chose que vous souhaitez mettre en œuvre ou pensez-vous que c'est une perte de temps? Faites-moi savoir dans les commentaires!