Langage Python : comprendre le test-driven développement
Dans ce tutoriel, nous vous parlons du test-driven en python.
Le développement piloté par les tests (TDD) est basé sur une idée simple:
vous écrivez les tests avant d’écrire le code. Mais le test échouera-t-il pas si le code n’a pas encore été écrit ? Oui, si c’est un bon test. Et si ça passe ?
Ensuite, soit vous avez terminé (peu probable), soit il y a un problème avec votre test.
Ecrire des tests vous oblige d’abord à faire deux choses :
- Décidez comment vous voulez pouvoir utiliser certaines fonctions. Qu’est-ce que doit
les paramètres être? Que doit-il retourner ? - N’écrivez que le code dont vous avez besoin. S’il y a un code qui ne prend pas en charge
certains comportements souhaités avec des tests, alors vous n’avez pas besoin de l’écrire.
Le mantra TDD est Red-Green-Refactor. Il fait référence à trois phases de
le processus de test.
• Rouge : Les tests échouent. Ils font mieux ! Vous n’avez pas encore écrit le code !
• Vert : Vous faites passer les tests en modifiant le code.
• Refactor : vous nettoyez le code, supprimant la duplication.
Les termes rouge et vert font référence à de nombreux travaux de test qui montrent tests échoués en rouge et tests réussis en vert.
Le refactoring est le processus de nettoyage du code, se référant le plus souvent le processus de suppression des doublons. Duplication dans le code, qu’elle provienne du copier-coller ou simplement répéter la logique peut être une source de nombreuses erreurs.
Si vous dupliquez du code avec un bogue, vous avez maintenant deux bogues. Si vous trouvez le bug, vous devrez le trouver deux fois.
Voici un exemple simple de code refactorisé
Code d’origine avec duplication mineure :
avg1 = sum(L1)/len(L1)
avg2 = sum(L2)/len(L2)
Ensuite, on observe qu’il devrait y avoir un comportement par défaut pour vide répertorie donc (un test est ajouté et) le code est mis à jour comme suit.
Code mis à jour avant la refactorisation :
if len(L1) == 0:
avg1 = 0
else:
avg1 = sum(L1) / len(L1)
if len(L2) == 0:
avg2 = 0
else:
avg2 = sum(L2) / len(L2)
Code refactorisé :
def avg(L):
if len(L) == 0:
return 0
else:
return sum(L) / len(L)
avg1 = avg(L1)
avg2 = avg(L2)
Dans le code refactorisé, les détails de la fonction avg ne sont pas dupliqués.
Si nous voulons modifier ultérieurement la manière dont le code gère les listes vides, nous ne ferons que
avoir à le changer en un seul endroit.
Le code refactorisé est également plus facile à lire.
Éloignez-vous de l’ordinateur. Pensez au problème que vous essayez de résoudre
résoudre. Pensez aux méthodes que vous écrivez. Demandez-vous ce que vous devriez
arriver quand j’exécute ce code?. Demandez-vous également, comment est-ce que je veux utiliser ce
code?
• Rédigez des tests qui utilisent le code comme il se doit.
• Ensuite, écrivez des tests qui utilisent le code de manière incorrecte pour tester que votre code
échoue gracieusement. Donne-t-il des messages d’erreur clairs ?
• Testez les cas extrêmes, ces cas délicats qui peuvent rarement survenir. Essayer
pour casser votre propre code.
Transformez les bugs en tests. Un bug ou un comportement incorrect peut être répété
après l’avoir réparé. Vous voulez l’attraper quand il le fait. Parfois tu
remarquer un bogue lorsqu’un test différent échoue. Rédigez un test spécifique pour révéler
le bogue, puis corrigez-le.
• Testez l’interface publique. Habituellement, vous n’avez pas besoin ou ne voulez pas tester le
méthodes privées d’une classe. Vous devez traiter le code de test comme un utilisateur de
la classe et il ne devrait faire aucune hypothèse sur les attributs privés.
De cette façon, si un privé est renommé ou refactorisé, vous n’avez pas à changer les épreuves.
Test et conception orientée objet (avec python)
Dans la conception orientée objet, nous divisons le code en classes. Ces cours ont
Certaines relations parfois induites par héritage ou composition. Les classes ont des méthodes publiques. Nous appelons ces méthodes publiques l’interface pour la classe.
Pour commencer une conception, nous examinons le problème et identifions les noms (classes) et les verbes (méthodes). Dans notre description, nous exprimons ce qui devrait arriver.
Souvent, ces attentes sont exprimées dans un langage si… alors, c’est-à-dire si j’appelle
cette méthode avec ces paramètres, alors cela se produira. Un test unitaire va
encoder cette attente. Il vérifiera que le comportement réel du code correspond au comportement attendu.
Lors de la rédaction d’un cours, cela aide à concentrer notre attention et à réduire le nombre
de choses à penser si nous supposons que chaque classe fonctionne comme elle est supposée pour. Nous essayons de rendre cela vrai en testant chaque classe individuellement. Puis quand nous composons des classes en classes plus complexes, nous pouvons avoir plus de confiance que toutes les erreurs que nous trouvons sont dans la nouvelle classe et ne se cachent pas quelque part les classes écrites précédemment.
Au début, cela peut sembler une perte de temps de tester minutieusement votre code.
Cependant, toute petite économie de temps que vous pourriez récolter tôt en sautant des tests sera très vite passé dans les maux de tête d’innombrables heures de débugage code non testé. Lorsque vous avez beaucoup de code non testé, chaque fois qu’il y a un comportement inattendu, l’erreur peut être n’importe où. Le processus de débugage.
peut pratiquement s’arrêter. Si et quand cela vous arrive : Arrêtez. Prendre une pièce. Essaye-le. Répéter. Être prudent et systématique vous amènera globalement moins de temps. Il est plus rapide d’aller lentement.