Permettez-moi de commencer par brancher les sources - Test d'unité pragmatique en Java avec JUnit (Il existe une version avec C # -Nunit aussi .. mais j'ai celui-ci .. son agnostique pour la plupart. Recommandé.)
Les bons tests devraient être UN VOYAGE (l'acronyme n'est pas assez collant - j'ai une impression de la feuille de triche dans le livre que j'ai dû retirer pour m'assurer d'avoir bien compris ..)
- Automatique : l'appel des tests ainsi que la vérification des résultats pour PASS / FAIL doivent être automatiques
- Complet : couverture; Bien que les bogues aient tendance à se regrouper autour de certaines régions du code, assurez-vous de tester tous les chemins et scénarios clés. Utilisez des outils si vous devez connaître les régions non testées
- Répétable : les tests doivent produire les mêmes résultats à chaque fois ... à chaque fois. Les tests ne doivent pas reposer sur des paramètres incontrôlables.
- Indépendant : très important.
- Les tests ne doivent tester qu'une seule chose à la fois. Les assertions multiples sont acceptables tant qu'elles testent toutes une fonctionnalité / un comportement. Lorsqu'un test échoue, il doit identifier l'emplacement du problème.
- Les tests ne doivent pas s'appuyer les uns sur les autres - Isolés. Aucune hypothèse sur l'ordre d'exécution des tests. Assurez-vous de `` nettoyer la table '' avant chaque test en utilisant correctement la configuration / le démontage
Professionnel : à long terme, vous aurez autant de code de test que de production (sinon plus), donc suivez le même standard de bonne conception pour votre code de test. Méthodes-classes bien factorisées avec des noms révélateurs d'intention, pas de duplication, des tests avec de bons noms, etc.
Les bons tests fonctionnent également rapidement . tout test qui prend plus d'une demi-seconde à exécuter .. doit être travaillé. Plus la suite de tests prend du temps pour une exécution ... moins elle sera exécutée fréquemment. Plus le développeur essaiera de faire de changements entre les exécutions ... si quelque chose casse ... il faudra plus de temps pour déterminer quel changement est à l'origine.
Mise à jour 2010-08:
- Lisible : cela peut être considéré comme faisant partie de Professional - mais on ne saurait trop le souligner. Un test d'acide serait de trouver quelqu'un qui ne fait pas partie de votre équipe et de lui demander de comprendre le comportement testé en quelques minutes. Les tests doivent être maintenus tout comme le code de production - rendez-le donc facile à lire même si cela demande plus d'efforts. Les tests doivent être symétriques (suivre un modèle) et concis (tester un comportement à la fois). Utilisez une convention de dénomination cohérente (par exemple, le style TestDox). Évitez d'encombrer le test avec des «détails accessoires» .. devenez minimaliste.
En dehors de ceux-ci, la plupart des autres sont des directives qui réduisent le travail à faible bénéfice: par exemple, «Ne testez pas le code que vous ne possédez pas» (par exemple les DLL tierces). Ne testez pas les getters et les setters. Gardez un œil sur le rapport coût-bénéfice ou la probabilité de défaut.
la source
La plupart des réponses ici semblent aborder les meilleures pratiques des tests unitaires en général (quand, où, pourquoi et quoi), plutôt que d'écrire les tests eux-mêmes (comment). Comme la question me paraissait assez précise sur la partie «comment», j'ai pensé poster ceci, tiré d'une présentation «sac marron» que j'avais menée dans mon entreprise.
Les 5 lois de rédaction des tests de Womp:
1. Utilisez des noms de méthode de test longs et descriptifs.
2. Écrivez vos tests dans un style Arrange / Act / Assert .
3. Fournissez toujours un message d'échec avec vos assertions.
4. Commentez la raison du test - quelle est l'hypothèse commerciale?
5. Chaque test doit toujours rétablir l'état de toute ressource qu'il touche
la source
Gardez ces objectifs à l'esprit (adapté du livre xUnit Test Patterns de Meszaros)
Quelques choses pour vous faciliter la tâche:
N'oubliez pas que vous pouvez également faire des tests d'intégration avec votre framework xUnit, mais gardez les tests d'intégration et les tests unitaires séparés
la source
Les tests doivent être isolés. Un test ne doit pas dépendre d'un autre. De plus, un test ne doit pas s'appuyer sur des systèmes externes. En d'autres termes, testez votre code, pas le code dont dépend votre code. Vous pouvez tester ces interactions dans le cadre de votre intégration ou de vos tests fonctionnels.
la source
Quelques propriétés de bons tests unitaires:
Lorsqu'un test échoue, il devrait être immédiatement évident où se situe le problème. Si vous devez utiliser le débogueur pour localiser le problème, vos tests ne sont pas assez granulaires. Avoir exactement une assertion par test aide ici.
Lorsque vous refactorisez, aucun test ne doit échouer.
Les tests doivent être exécutés si vite que vous n’hésitez jamais à les exécuter.
Tous les tests doivent toujours réussir; pas de résultats non déterministes.
Les tests unitaires doivent être bien pris en compte, tout comme votre code de production.
@Alotor: Si vous suggérez qu'une bibliothèque ne devrait avoir que des tests unitaires sur son API externe, je ne suis pas d'accord. Je veux des tests unitaires pour chaque classe, y compris des classes que je n'expose pas aux appelants externes. (Cependant, si je ressens le besoin d'écrire des tests pour des méthodes privées, alors je dois refactoriser. )
EDIT: Il y avait un commentaire sur la duplication causée par "une assertion par test". Plus précisément, si vous avez du code pour configurer un scénario et que vous souhaitez ensuite faire plusieurs affirmations à ce sujet, mais que vous n'avez qu'une seule assertion par test, vous pouvez dupliquer la configuration sur plusieurs tests.
Je n'adopte pas cette approche. Au lieu de cela, j'utilise des montages de test par scénario . Voici un exemple approximatif:
la source
Ce que vous recherchez, c'est la délimitation des comportements de la classe testée.
L'intention de base est d'augmenter votre confiance dans le comportement de la classe.
Ceci est particulièrement utile lorsque vous envisagez de refactoriser votre code. Martin Fowler a un intéressant article concernant les tests sur son site Web.
HTH.
à votre santé,
Rob
la source
Le test devrait initialement échouer. Ensuite, vous devez écrire le code qui les fait passer, sinon vous courez le risque d'écrire un test qui est bogué et qui réussit toujours.
la source
J'aime l'acronyme Right BICEP du livre Pragmatic Unit Testing susmentionné :
Personnellement, je pense que vous pouvez aller assez loin en vérifiant que vous obtenez les bons résultats (1 + 1 devrait renvoyer 2 dans une fonction d'addition), en essayant toutes les conditions aux limites auxquelles vous pouvez penser (comme utiliser deux nombres dont la somme est supérieur à la valeur maximale de l'entier dans la fonction d'ajout) et forçant des conditions d'erreur telles que des pannes de réseau.
la source
Les bons tests doivent être maintenables.
Je n'ai pas tout à fait compris comment faire cela pour des environnements complexes.
Tous les manuels commencent à se décoller alors que votre base de code commence à atteindre des centaines de milliers ou des millions de lignes de code.
Une bonne architecture peut contrôler une partie de l'explosion des interactions, mais inévitablement, à mesure que les systèmes deviennent plus complexes, le système de test automatisé évolue avec elle.
C'est là que vous commencez à devoir faire des compromis:
Vous devez également décider:
où stockez-vous les cas de test dans votre base de code?
Je pourrais continuer indéfiniment, mais mon argument est que:
Les tests doivent être maintenables.
la source
J'ai couvert ces principes il y a quelque temps dans cet article de MSDN Magazine que je pense qu'il est important pour tout développeur de le lire.
La façon dont je définis les "bons" tests unitaires est de savoir s'ils possèdent les trois propriétés suivantes:
la source
la source
Jay Fields a beaucoup de bons conseils sur l'écriture de tests unitaires et il y a un article où il résume les conseils les plus importants . Vous y lirez que vous devez réfléchir de manière critique à votre contexte et juger si les conseils vous valent. Vous obtenez une tonne de réponses étonnantes ici, mais c'est à vous de décider ce qui convient le mieux à votre contexte. Essayez-les et refactorisez-les si cela sent mauvais pour vous.
Sincères amitiés
la source
Ne supposez jamais qu'une méthode triviale de 2 lignes fonctionnera. L'écriture d'un test unitaire rapide est le seul moyen d'éviter que le test nul manquant, le signe moins égaré et / ou une erreur de portée subtile ne vous mordent, inévitablement lorsque vous avez encore moins de temps que maintenant.
la source
J'appuie la réponse "A TRIP", sauf que les tests DEVRAIENT s'appuyer les uns sur les autres !!!
Pourquoi?
DRY - Ne vous répétez pas - s'applique également aux tests! Les dépendances de test peuvent aider 1) à gagner du temps de configuration, 2) à économiser les ressources de l'appareil et 3) à identifier les échecs. Bien sûr, seulement étant donné que votre framework de test prend en charge les dépendances de première classe. Sinon, je l'avoue, ils sont mauvais.
Suivi http://www.iam.unibe.ch/~scg/Research/JExample/
la source
Les tests unitaires sont souvent basés sur des objets ou des données factices. J'aime écrire trois types de tests unitaires:
Le but est d'éviter de tout rejouer pour pouvoir tester toutes les fonctions.
la source
Pensez aux 2 types de tests et traitez-les différemment: les tests fonctionnels et les tests de performance.
Utilisez des entrées et des métriques différentes pour chacun. Vous devrez peut-être utiliser un logiciel différent pour chaque type de test.
la source
J'utilise une convention de dénomination de test cohérente décrite par les normes de dénomination de test unitaire de Roy Osherove Chaque méthode dans une classe de cas de test donnée a le style de dénomination MethodUnderTest_Scenario_ExpectedResult suivant.
La première section de nom de test est le nom de la méthode dans le système testé.
Vient ensuite le scénario spécifique qui est testé.
Enfin, les résultats de ce scénario.
Chaque section utilise Upper Camel Case et est délimitée par un sous-score.
J'ai trouvé cela utile lorsque j'exécute le test, les tests sont regroupés par le nom de la méthode testée. Et avoir une convention permet aux autres développeurs de comprendre l'intention du test.
J'ajoute également des paramètres au nom de la méthode si la méthode testée a été surchargée.
la source