Le développement piloté par les tests est une méthode efficace pour garantir un code bien testé et refactorisable. L'idée de base est que vous commencez le développement en écrivant des tests. Ces tests documentent clairement les attentes et créent une rubrique pour une mise en œuvre réussie. Lorsque cela est fait correctement, vous pouvez définir clairement l'entrée/sortie attendue d'une fonction avant d'écrire un code. Cela présente quelques avantages immédiats :
Maintenant que vous êtes convaincu des avantages, vous pouvez vous lancer dans le développement piloté par les tests (TDD) en suivant ces étapes :
Ces étapes sont suivies dans un cycle, vous ajoutez donc toujours plus de tests pour contester la mise en œuvre actuelle.
La dernière étape, qui spécifie l'écriture de la quantité minimale de code, est celle où les choses peuvent devenir fastidieuses si elles sont suivies de manière rigide. Il est important de comprendre pourquoi cette règle existe avant de pouvoir déterminer quand il convient de s'en écarter.
Vous êtes chargé d'implémenter la fonction Add(x, y int) int. Avant de passer à l’implémentation et de renvoyer simplement x + y, écrivez le test le plus simple : 1 + 1 == 2. Ensuite, quelle est l’implémentation la plus simple qui réussirait le test ? C'est juste le retour 2. Maintenant vos tests réussissent !
À ce stade, vous réalisez que vous avez besoin de plus de tests, alors vous accélérez le rythme et en ajoutez quelques autres :
Maintenant, vos tests échouent, vous devez donc corriger l'implémentation. Vous ne pouvez pas simplement renvoyer 3 ou renvoyer 105 cette fois, vous devez donc trouver une solution qui fonctionne pour tous les tests. Cela conduit à l'implémentation : return x + y.
Bien que cela semble trop fastidieux dans l'exemple trivial, le strict respect de cette méthode vous a amené à écrire plusieurs tests au lieu de simplement faire confiance à votre implémentation. Bien sûr, votre idée initiale de renvoyer x + y aurait fonctionné, mais le but est de vous recycler pour vous fier aux tests plutôt qu'à votre propre compréhension du code. Dans le monde réel, vous n'êtes pas le seul à travailler sur ce morceau de code et vous oublierez inévitablement les détails d'implémentation. Ce processus vous oblige à écrire plus de tests et à réfléchir à davantage de façons de rompre avec une implémentation simple.
Au final, vous acquerrez de l'expérience et apprendrez à trouver l'équilibre qui fonctionne dans les différents scénarios que vous rencontrez. Vous reviendrez à la mise en œuvre à pleine vitesse des fonctionnalités, constaterez que vous avez moins de bogues et écrirez du code plus maintenable.
Entrons dans un exemple plus compliqué utilisant TDD pour une API HTTP REST. Ce guide étape par étape utilise mon framework Go, babyapi, mais les concepts peuvent être appliqués n'importe où.
babyapi utilise des génériques pour créer une API CRUD complète autour des structures Go, ce qui rend très facile la création d'une API REST complète et d'une CLI client. En plus de cela, le package babytest fournit des outils pour créer des tests de tables API de bout en bout. L'utilisation de TDD au niveau de l'API permet de tester entièrement les couches HTTP et de stockage d'une nouvelle API ou fonctionnalité en même temps.
Avertissement : étant donné que babyapi gère la majeure partie de l'implémentation et est également utilisé pour générer un passe-partout de test, nous ne commençons pas techniquement par TDD. Cependant, nous verrons à quel point cela est bénéfique lors de l'ajout du support des requêtes PATCH à notre API.
Créer un nouveau projet Go
Créez le main.go initial en utilisant l'exemple simple de babyapi
Exécutez les tests et voyez s'ils réussissent !
This test fails since babyapi doesn't support PATCH by default. We can fix it by implementing Patch for the TODO struct. Since we defined our feature with two tests, our simplest implementation isn't just setting Completed = true and we have to use the value from the request
Now we can change the Completed status of a TODO, but we still cannot use PATCH to modify other fields as show by this new set of tests
Update Patch to set the remaining fields
Our tests still fail since we always update the TODO with the request fields, even if they're empty. Fix this by updating the implementation to check for empty values
The new UpdateWithPatch test passes, but our previous tests fail. Since we changed Completed to be *bool, TODOs created with an empty value will show as null
Implement Render for TODO so we can treat nil as false
Implementing the PATCH feature with test-driven development resulted in a robust set of tests and a well-implemented feature. Since we started by defining the expected input and output of a PATCH request in tests, it was easy to see the issues caused by not checking for empty values in the request. Also, our pre-existing tests were able to protect from breaking changes when changing the type of Completed to *bool.
Test-driven development is an effective approach for creating fully tested and correct code. By starting with tests in mind, we can ensure that every piece of code is designed to be testable instead of letting tests be an afterthought.
If you're hesitant about adopting TDD, here are a few ideas to get started:
Even if TDD isn't a good fit for the way you write code, it's still a powerful tool to have in your belt. I encourage you to at least commit some time to trying it out and see how it affects your development process.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!