Pourquoi utiliser JUnit pour les tests?

131

Peut-être que ma question est une question débutante, mais je ne peux pas vraiment comprendre les circonstances dans lesquelles j'utiliserais ?

Que j'écris des applications simples ou des applications plus volumineuses, je les teste avec les System.outdéclarations et cela me semble assez facile.

Pourquoi créer des classes de test avec JUnit, des dossiers inutiles dans le projet si nous devons encore appeler les mêmes méthodes, vérifier ce qu'elles renvoient et nous avons alors une surcharge de tout annoter?

Pourquoi ne pas écrire une classe et la tester à la fois avec System.outmais pas créer des classes de test?

PS. Je n'ai jamais travaillé sur de grands projets que j'apprends juste.

Alors quel est le but?

Artem Moskalev
la source
1
Lire L'art des tests unitaires
rgeorge
7
Vous savez que chaque fois que vous changez quoi que ce soit dans votre programme, tout votre travail antérieur d'examen manuel des sorties est invalidé et vous devez les refaire depuis le début?
Thorbjørn Ravn Andersen
Non seulement les «tests», mais aussi les «tests intelligents» sont très importants. En voici un bel exemple: wp.me/prMeE-11
akcasoy

Réponses:

139

Ce n'est pas un test, c'est "regarder manuellement la sortie" (connu dans le commerce sous le nom de LMAO). Plus formellement, on parle de "recherche manuelle des sorties anormales" (LMFAO). (Voir note ci-dessous)

Chaque fois que vous changez de code, vous devez exécuter l'application et LMFAO pour tout le code affecté par ces modifications. Même dans les petits projets, cela est problématique et sujet aux erreurs.

Passez maintenant à 50k, 250k, 1m LOC ou plus et LMFAO chaque fois que vous modifiez un code. Non seulement c'est désagréable, mais c'est impossible: vous avez augmenté les combinaisons d'entrées, de sorties, de drapeaux, de conditions et il est difficile d'exercer toutes les branches possibles.

Pire encore, LMFAO peut signifier visiter des pages sur des pages d'application Web, exécuter des rapports, parcourir des millions de lignes de journal sur des dizaines de fichiers et de machines, lire des e-mails générés et livrés, vérifier les messages texte, vérifier le chemin d'un robot, remplir une bouteille de soda, agréger les données d'une centaine de services web, vérifier la piste d'audit d'une transaction financière ... vous voyez l'idée. «Sortie» ne signifie pas quelques lignes de texte, «sortie» signifie le comportement global du système.

Enfin, les tests unitaires et comportementaux définissent le comportement du système. Les tests peuvent être exécutés par un serveur d'intégration continue et vérifiés pour leur exactitude. Bien sûr, il en va de même System.out, mais le serveur CI ne saura pas si l'un d'entre eux est erroné - et si c'est le cas, ce sont des tests unitaires, et vous pouvez aussi bien utiliser un framework.

Peu importe à quel point nous pensons être bons, les humains ne sont pas de bons cadres de test unitaires ou de bons serveurs CI.


Note: LMAO est à l' essai, mais dans un très sens limité. Il n'est pas reproductible de manière significative dans tout un projet ou dans le cadre d'un processus. Cela s'apparente au développement incrémentiel dans une REPL, mais jamais à la formalisation de ces tests incrémentiels.

Dave Newton
la source
3
-1 pour la première phrase, ce qui est complètement et totalement faux.
Michael Borgwardt
50

Nous écrivons des tests pour vérifier l'exactitude du comportement d'un programme.

Vérifier l'exactitude du comportement d'un programme en inspectant le contenu des instructions de sortie à l'aide de votre yeux est un processus manuel , ou plus spécifiquement visuel .

Tu pourrais dire que

l'inspection visuelle fonctionne , je vérifie que le code fait ce qu'il est censé faire, pour ces scénarios et une fois que je peux voir que c'est correct, nous sommes prêts à partir.

Maintenant, tout d'abord, c'est formidable de savoir si le code fonctionne correctement ou non. C'est une bonne chose. Vous êtes en avance sur la courbe! Malheureusement, cette approche pose des problèmes.

Le premier problème avec l'inspection visuelle est que vous êtes un grave accident de soudage loin de ne plus jamais pouvoir vérifier l'exactitude de votre code.

Le deuxième problème est que la paire d'yeux utilisée est étroitement liée au cerveau du propriétaire des yeux. Si l'auteur du code possède également les yeux utilisés dans le processus d'inspection visuelle, le processus de vérification de l'exactitude dépend de la connaissance du programme internalisée dans le cerveau de l'inspecteur visuel.

Il est difficile pour une nouvelle paire d'yeux d'entrer et de vérifier l'exactitude du code simplement parce qu'elle n'est pas associée au cerveau du codeur d'origine. Le propriétaire de la deuxième paire d'yeux devra s'entretenir avec l'auteur original du code afin de bien comprendre le code en question. La conversation comme moyen de partage des connaissances est notoirement peu fiable. Un point qui est discutable si le codeur d'origine n'est pas disponible pour la nouvelle paire d'yeux. Dans ce cas, la nouvelle paire d'yeux doit lire le code d'origine.

La lecture du code d'autres personnes qui n'est pas couvert par les tests unitaires est plus difficile que la lecture du code auquel sont associés des tests unitaires. Au mieux, lire le code des autres est un travail délicat, au pire c'est la tâche la plus compliquée du génie logiciel. Il y a une raison pour laquelle les employeurs, lorsqu'ils publient des offres d'emploi, soulignent qu'un projet est un projet nouveau (ou tout nouveau). Écrire du code à partir de zéro est plus facile que de modifier le code existant et rend ainsi l'emploi annoncé plus attrayant pour les employés potentiels.

Avec les tests unitaires, nous divisons le code en ses composants. Pour chaque composant, nous avons ensuite établi notre stand en indiquant comment le programme devrait se comporter . Chaque test unitaire raconte comment cette partie du programme doit agir dans un scénario spécifique. Chaque test unitaire est comme une clause dans un contrat qui décrit ce qui doit se passer du point de vue du code client.

Cela signifie alors qu'une nouvelle paire d'yeux a deux brins de documentation en direct et précise sur le code en question.

Tout d'abord, ils ont le code lui-même, l'implémentation, comment le code a été fait ; deuxièmement, ils ont toutes les connaissances que le codeur d'origine a décrites dans un ensemble d'instructions formelles qui racontent l'histoire de la façon dont ce code est censé se comporter.

Les tests unitaires capturent et décrivent formellement les connaissances que l'auteur original possédait lors de la mise en œuvre de la classe. Ils fournissent une description du comportement de cette classe lorsqu'elle est utilisée par un client.

Vous avez raison de remettre en question l'utilité de faire cela car il est possible d'écrire des tests unitaires qui sont inutiles, ne couvrent pas tout le code en question, deviennent périmés ou obsolètes, etc. Comment pouvons-nous nous assurer que les tests unitaires non seulement imitent mais améliorent le processus d'un auteur compétent et consciencieux qui inspecte visuellement les instructions de sortie de son code au moment de l'exécution? Écrivez d'abord le test unitaire, puis écrivez le code pour que ce test réussisse. Lorsque vous avez terminé, laissez les ordinateurs exécuter les tests, ils sont rapides, ils sont parfaits pour effectuer des tâches répétitives, ils sont parfaitement adaptés au travail.

Assurez la qualité des tests en les examinant à chaque fois que vous touchez le code qu'ils testent et exécutez les tests pour chaque build. Si un test échoue, corrigez-le immédiatement.

Nous automatisons le processus d'exécution des tests afin qu'ils soient exécutés à chaque fois que nous faisons une compilation du projet. Nous automatisons également la génération de rapports de couverture de code qui détaille le pourcentage de code couvert et exercé par les tests. Nous visons des pourcentages élevés. Certaines entreprises empêcheront l'archivage des modifications de code dans le contrôle du code source si elles n'ont pas suffisamment de tests unitaires écrits pour décrire tout changement de comportement du code. En règle générale, une deuxième paire d'yeux examinera les modifications du code en collaboration avec l'auteur des modifications. Le réviseur passera en revue les changements pour s'assurer que les changements sont compréhensibles et suffisamment couverts par des tests. Le processus d'examen est donc manuel, mais lorsque les tests (tests unitaires et d'intégration et éventuellement tests d'acceptation des utilisateurs) réussissent ce processus de révision manuelle, ils font partie du processus de construction automatique. Ceux-ci sont exécutés chaque fois qu'une modification est enregistrée. Le serveur exécute cette tâche dans le cadre du processus de construction.

Les tests qui sont automatiquement exécutés, maintiennent l'intégrité du comportement du code et aident à empêcher les futures modifications de la base de code de casser le code .

Enfin, fournir des tests vous permet de re-factoriser le code de manière agressive, car vous pouvez apporter des améliorations importantes au code en sachant que vos modifications ne cassent pas les tests existants.

Il y a une mise en garde concernant le développement piloté par les tests , à savoir que vous devez écrire du code en vue de le rendre testable. Cela implique le codage des interfaces et l'utilisation de techniques telles que l'injection de dépendances pour instancier des objets collaboratifs. Découvrez le travail de Kent Beck qui décrit très bien le TDD. Rechercher le codage des interfaces et étudier

Rob Kielty
la source
13

Lorsque vous testez en utilisant quelque chose comme System.out, vous ne testez qu'un petit sous-ensemble de cas d'utilisation possibles. Ce n'est pas très complet lorsque vous avez affaire à des systèmes qui pourraient accepter une quantité presque infinie d'entrées différentes.

Les tests unitaires sont conçus pour vous permettre d'exécuter rapidement des tests sur votre application en utilisant un ensemble très large et diversifié d'entrées de données différentes. De plus, les meilleurs tests unitaires tiennent également compte des cas limites, tels que les entrées de données qui se trouvent juste à la limite de ce qui est considéré comme valide.

Pour un être humain, tester toutes ces différentes entrées peut prendre des semaines alors que cela peut prendre quelques minutes pour une machine.

Pensez-y comme ceci: vous ne «testez» pas non plus quelque chose qui sera statique. Votre application est probablement en train de subir des changements constants. Par conséquent, ces tests unitaires sont conçus pour s'exécuter à différents moments du cycle de compilation ou de déploiement. Le plus gros avantage est peut-être le suivant:

Si vous cassez quelque chose dans votre code, vous saurez à ce sujet en ce moment , pas après vous avez déployé, pas quand un testeur QA attrape un bug, pas quand vos clients ont annulé. Vous aurez également une meilleure chance de résoudre le problème immédiatement , car il est clair que la chose qui a cassé la partie du code en question s'est probablement produite depuis votre dernière compilation. Ainsi, la quantité de travail d'enquête nécessaire pour résoudre le problème est considérablement réduite.

jmort253
la source
9

J'ai ajouté un autre System.out ne peut pas faire:

  • Rendre chaque cas de test indépendant (c'est important)

    JUnit peut le faire: à chaque fois, une nouvelle instance de cas de test sera créée et @Beforeappelée.

  • Code de test séparé de la source

    JUnit peut le faire.

  • Intégration avec CI

    JUnit peut le faire avec Ant et Maven.

  • Organisez et combinez facilement les cas de test

    JUnit peut faire @Ignoreet tester la suite.

  • Résultat facile à vérifier

    JUnit propose de nombreuses méthodes Assert ( assertEquals, assertSame...)

  • Mock et stub vous permettent de vous concentrer sur le module de test.

    JUnit peut faire: L'utilisation de la simulation et du stub vous permet de configurer le bon appareil et de vous concentrer sur la logique du module de test.

卢 声 远 Shengyuan Lu
la source
9

Les tests unitaires garantissent que le code fonctionne comme prévu. Ils sont également très utiles pour s'assurer que le code fonctionne toujours comme prévu au cas où vous deviez le modifier plus tard pour créer de nouvelles fonctionnalités afin de corriger un bogue. Avoir une couverture de test élevée de votre code vous permet de continuer à développer des fonctionnalités sans avoir à effectuer de nombreux tests manuels.

Votre approche manuelle System.outest bonne mais pas la meilleure. C'est un test ponctuel que vous effectuez. Dans le monde réel, les exigences ne cessent de changer et la plupart du temps, vous apportez de nombreuses modifications aux fonctions et classes existantes. Donc… pas à chaque fois que vous testez le morceau de code déjà écrit.

il y a aussi des fonctionnalités plus avancées dans JUnit comme

Affirmer des déclarations

JUnit fournit des méthodes pour tester certaines conditions, ces méthodes commencent généralement par des assertions et vous permettent de spécifier le message d'erreur, le résultat attendu et réel

Certaines de ces méthodes sont

  1. fail([message])- Laisse le test échouer. Peut être utilisé pour vérifier qu'une certaine partie du code n'est pas atteinte. Ou d'avoir un test qui échoue avant que le code de test ne soit implémenté.
  2. assertTrue(true)/ assertTrue(false)- Sera toujours vrai / faux. Peut être utilisé pour prédéfinir un résultat de test, si le test n'est pas encore implémenté.
  3. assertTrue([message,] condition)- Vérifie que le booléen conditionest vrai.
  4. assertEquals([message,] expected, actual)- Teste si deux valeurs sont égales (selon la equalsméthode si implémentée, sinon en utilisant la ==comparaison de référence). Remarque: pour les tableaux, c'est la référence qui est vérifiée, et non le contenu, à utiliser assertArrayEquals([message,] expected, actual)pour cela.
  5. assertEquals([message,] expected, actual, delta)- Teste si deux valeurs flottantes ou doubles sont à une certaine distance l'une de l'autre, contrôlée par la deltavaleur.
  6. assertNull([message,] object) - Vérifie que l'objet est nul

etc. Voir le Javadoc complet pour tous les exemples ici .

Suites

Avec les suites de tests, vous pouvez en un sens combiner plusieurs classes de test en une seule unité afin de pouvoir toutes les exécuter en même temps. Un exemple simple, combinant les classes de test MyClassTestet MySecondClassTesten une seule suite appelée AllTests:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({ MyClassTest.class, MySecondClassTest.class })
public class AllTests { } 
Arvind
la source
6

Le principal avantage de JUnit est qu'il est automatisé plutôt que de devoir vérifier manuellement vos impressions. Chaque test que vous écrivez reste avec votre système. Cela signifie que si vous apportez une modification qui a un effet secondaire inattendu, votre test l'attrapera et échouera plutôt que de devoir vous rappeler de tout tester manuellement après chaque modification.

n00begon
la source
4

JUnit est un cadre de test unitaire pour le langage de programmation Java. Il est important dans le développement piloté par les tests et fait partie d'une famille de frameworks de tests unitaires appelés collectivement xUnit.

JUnit promeut l'idée de «tester d'abord puis de coder», qui met l'accent sur la configuration des données de test pour un morceau de code qui peut être testé en premier et peut ensuite être implémenté. Cette approche est comme "tester un peu, coder un peu, tester un peu, coder un peu ..." qui augmente la productivité du programmeur et la stabilité du code du programme, ce qui réduit le stress du programmeur et le temps consacré au débogage.

Caractéristiques JUnit est un framework open source qui est utilisé pour écrire et exécuter des tests.

Fournit une annotation pour identifier les méthodes de test.

Fournit des assertions pour tester les résultats attendus.

Fournit des lanceurs de test pour exécuter des tests.

Les tests JUnit vous permettent d'écrire du code plus rapidement, ce qui augmente la qualité

JUnit est d'une simplicité élégante. C'est moins complexe et prend moins de temps.

Les tests JUnit peuvent être exécutés automatiquement et ils vérifient leurs propres résultats et fournissent une rétroaction immédiate. Il n'est pas nécessaire de parcourir manuellement un rapport des résultats de test.

Les tests JUnit peuvent être organisés en suites de tests contenant des cas de test et même d'autres suites de tests.

Junit affiche la progression du test dans une barre verte si le test se déroule correctement et devient rouge lorsqu'un test échoue.

AKKI
la source
2

J'ai une perspective légèrement différente de la raison pour laquelle JUnit est nécessaire.

Vous pouvez en fait écrire tous les cas de test vous-même, mais c'est fastidieux. Voici les problèmes:

  1. Au lieu de cela, System.outnous pouvons ajouter if(value1.equals(value2))et renvoyer 0 ou -1 ou un message d'erreur. Dans ce cas, nous avons besoin d'une classe de test "principale" qui exécute toutes ces méthodes et vérifie les résultats et maintient quels cas de test ont échoué et lesquels sont réussis.

  2. Si vous voulez ajouter d'autres tests, vous devez également les ajouter à cette classe de test "principale". Modifications du code existant. Si vous souhaitez détecter automatiquement les cas de test à partir des classes de test, vous devez utiliser la réflexion.

  3. Tous vos tests et votre classe principale pour exécuter des tests ne sont pas détectés par eclipse et vous devez écrire des configurations de débogage / exécution personnalisées pour exécuter ces tests. Cependant, vous ne voyez toujours pas ces jolies sorties de couleur verte / rouge.

Voici ce que fait JUnit:

  1. Il a des assertXXX()méthodes qui sont utiles pour imprimer des messages d'erreur utiles à partir des conditions et communiquer les résultats à la classe "principale".

  2. La classe "main" est appelée runner qui est fournie par JUnit, nous n'avons donc pas besoin d'en écrire. Et il détecte automatiquement les méthodes de test par réflexion. Si vous ajoutez de nouveaux tests avec @Testannotation, ils sont automatiquement détectés.

  3. JUnit a également une intégration eclipse et une intégration maven / gradle, il est donc facile d'exécuter des tests et vous n'aurez pas à écrire de configurations d'exécution personnalisées.

Je ne suis pas un expert de JUnit, c'est donc ce que j'ai compris à partir de maintenant, j'ajouterai plus à l'avenir.

Sreekar
la source
Je suppose que dans la première partie, vous avez écrit ce que nous aurions fait si JUnit n'était pas là pour rendre les tests unitaires un peu meilleurs que les instructions system.out.println. Peut-être que JUnit est le résultat de telles tentatives de la part de certains programmeurs et ils ont ressenti le besoin d'écrire un cadre de test séparé pour effectuer cette automatisation, ainsi JUnit est né, peut-être.
Saurabh Patil
1

Vous ne pouvez pas écrire de cas de test sans utiliser le framework de test ou bien vous devrez écrire votre framewok de test pour rendre justice à vos cas de test. Voici quelques informations sur JUnit Framework en dehors du fait que vous pouvez utiliser le framework TestNG.

Qu'est-ce que Junit?

Junit est un cadre de test largement utilisé avec le langage de programmation Java. Vous pouvez utiliser ce framework d'automatisation pour les tests unitaires et les tests d'interface utilisateur.Il nous aide à définir le flux d'exécution de notre code avec différentes annotations. Junit est construit sur l'idée de "premier test puis de codage" qui nous aide à augmenter la productivité des cas de test et la stabilité du code.

Fonctionnalités importantes de Junit Testing -

  1. Il s'agit d'un cadre de test open source permettant aux utilisateurs d'écrire et d'exécuter des cas de test efficacement.
  2. Fournit divers types d'annotations pour identifier les méthodes de test.
  3. Fournit différents types d'assertions pour vérifier les résultats de l'exécution du scénario de test.
  4. Il donne également aux coureurs de test pour exécuter des tests efficacement.
  5. C'est très simple et donc un gain de temps.
  6. Il fournit des moyens d'organiser vos cas de test sous forme de combinaisons de test.
  7. Il donne des résultats de cas de test de manière simple et élégante.
  8. Vous pouvez intégrer jUnit avec Eclipse, Android Studio, Maven & Ant, Gradle et Jenkins
anuja jain
la source
0

JUNIT est la méthode généralement acceptée par les développeurs Java. Lorsqu'ils peuvent fournir une entrée attendue similaire à la fonction et décider en conséquence que le code écrit est parfaitement écrit ou si le cas de test échoue, une approche différente peut également être mise en œuvre. JUNIT accélérera le développement et assurera les 0 défauts de la fonction.

mohit sarsar
la source
0

JUNIT: OBSERVER ET AJUSTER

Voici mon point de vue sur JUNIT.

JUNIT peut être utilisé pour,
1) Observer un comportement du système lorsqu'une nouvelle unité est ajoutée dans ce système.
2) Faites des ajustements dans le système pour accueillir la "nouvelle" unité dans le système.
Quoi? Exactement.

La vraie vie par exemple.

Lorsque votre parent visite votre chambre d'auberge universitaire,
1) Vous prétendez être plus responsable.
2) Vous garderez toutes choses là où elles devraient être, comme les chaussures dans un étagère à chaussures et non sur une chaise, les vêtements dans une armoire pas sur une chaise.
3) Vous vous débarrasserez de toute la contrebande.
4) vous lancerez le nettoyage sur chaque appareil que vous possédez.

En termes de programmation

Système: Votre code
UNIT: nouvelle fonctionnalité.
Comme le framework JUNIT est utilisé pour le langage JAVA, JUNIT = JAVA UNIT (peut-être).

Supposons que vous ayez déjà un code à l'épreuve des balles, mais qu'une nouvelle exigence est venue et que vous devez ajouter la nouvelle exigence dans votre code. Cette nouvelle exigence peut casser votre code pour certaines entrées (cas de test).

Un moyen simple d'adapter ce changement consiste à utiliser les tests unitaires (JUNIT).
Pour cela, vous devez écrire plusieurs cas de test pour votre code lorsque vous créez votre base de code. Et chaque fois qu'une nouvelle exigence survient, il vous suffit d'exécuter tous les cas de test pour voir si un cas de test échoue. Si non, vous êtes un artiste BadA ** et vous êtes prêt à déployer le nouveau code.
Si l'une des cas de test échoue, vous modifiez votre code et exécutez à nouveau des cas de test jusqu'à ce que vous obteniez le statut vert.

Rohit Singh
la source