Découvrez les nouveautés de MISRA C:2012 AMD3 et comment obtenir la couverture la PLUS ÉTENDUE avec C/C++test 2022.2 ! Regarder à la demande >>

Tutoriel JUnit: Configuration, écriture et exécution de tests unitaires Java

Par Nathan Jakubiak

6 décembre 2022

8  min lire

Comprenez les bases et faites évoluer votre pratique de test unitaire comme un pro avec ce didacticiel.

Voulez-vous ignorer les bases et voir comment automatiser la génération de tests unitaires pour atteindre une couverture de code de plus de 60 % en moins de 5 minutes ? Découvrez Jtest >>

Qu'est-ce que le test unitaire?

Parlons d'abord un peu de c'est quoi les tests unitaires et pourquoi c'est important en général.

Les tests unitaires sont une forme de test boîte blanche dans laquelle les cas de test sont basés sur la structure interne. Le testeur choisit des entrées pour tester des chemins particuliers dans le code et configure des assertions qui valident la sortie. Le but des tests unitaires est d'examiner les composants individuels ou des éléments de méthodes/classes pour vérifier la fonctionnalité, en s'assurant que le comportement est comme prévu.

La portée exacte d'une "unité" est souvent laissée à l'interprétation, mais une bonne règle empirique consiste à définir une unité comme la moindre quantité de code nécessaire pour effectuer une tâche autonome, par exemple, une méthode ou une classe unique.

Il y a une bonne raison pour laquelle nous limitons la portée lors des tests unitaires : si nous construisons un test qui valide une large partie d'un projet, nous nous concentrons de la fonctionnalité d'une seule méthode sur les interactions entre différentes parties du code. Si le test échoue, nous ne savons pas pourquoi il a échoué. Nous nous demandons si le point de défaillance se situe dans la méthode qui nous intéresse ou dans les dépendances associées à cette méthode.

Principes de base de JUnit: Prise en main de JUnit et utilisation de l'automatisation pour créer des tests unitaires

Qu'est-ce que JUnit?

JUnit est le framework de test unitaire Java le plus populaire. Un framework open-source, il est utilisé pour écrire et exécuter des tests automatisés reproductibles.

Comme pour toute autre chose, le framework de test JUnit a évolué au fil du temps. JUnit 4.0 est sorti en 2006 et 5.0 en 2017. Au moment d'écrire ces lignes, la dernière version est la 5.9.1. JUnit 5.x a résolu bon nombre des limitations antérieures de JUnit et est devenu le framework de test unitaire Java le plus robuste.

Ce billet de blog couvrira l'utilisation de JUnit 4 et 5.

Comment configurer les tests JUnit

Alors allons-y. Voici les étapes à suivre pour configurer JUnit.

Les IDE les plus courants, tels qu'Eclipse et IntelliJ, auront déjà l'intégration de test JUnit installée par défaut. Si vous n'utilisez pas d'IDE et que vous comptez peut-être uniquement sur un système de construction tel que Maven ou Gradle, l'installation de JUnit 4/5 est gérée via le fichier pom.xml ou build.gradle, respectivement.

Il est important de noter que JUnit 5 a été divisé en 3 modules, l'un d'entre eux étant un module vintage qui prend en charge l'annotation/syntaxe de JUnit 4 et 3. L'utilisation de JUnit 3 est très faible à ce stade et n'est généralement visible que dans des projets beaucoup plus anciens.

Unité 5

En raison de la manière modulaire de JUnit 5, une nomenclature est utilisée pour importer tous les modules et dépendances de JUnit. Si seuls des modules spécifiques sont nécessaires, des groupes ou des artefacts individuels peuvent être spécifiés à la place.

Pour ajouter JUnit 5 à Maven, ajoutez ce qui suit à pom.xml:

<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>

Pour Gradle, ajoutez ce qui suit au fichier build.gradle :

apply plugin: 'java'

dependencies {
implementation 'org.junit:junit-bom:5.9.1'
}

Unité 4

Pour ajouter JUnit 4 à Maven, ajoutez ce qui suit à pom.xml.

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>

Pour Gradle, ajoutez ce qui suit au build.gradle:

apply plugin: 'java'

dependencies {
testCompile 'junit:junit:4.13'
}

Si vous devez ajouter manuellement JUnit au chemin de classe pour les tests JUnit, vous devez référencer directement le(s) fichier(s) jar brut(s), bien que cela ne soit généralement pas nécessaire. JUnit 4 a le pot disponible en téléchargement direct. Junit 5 (au moment où j'écris ceci) n'a pas actuellement le fichier jar préconstruit, mais vous pouvez facilement compiler le code et générer les jars. JUnit 4 a le pot disponible en téléchargement direct.

Améliorer les tests unitaires pour Java avec l'automatisation: les meilleures pratiques pour les développeurs Java

Ecrire des tests unitaires: l'anatomie d'une JUnit

Maintenant que nous avons parlé un peu de la configuration de JUnit, passons à la construction et à l'exécution réelles de ces tests. Pour mieux illustrer la création de JUnits, nous allons commencer par quelque chose de basique. Dans l'exemple de test JUnit ci-dessous, nous avons une méthode simple (à gauche) qui convertit Fahrenheit en Celsius et un test JUnit (droit) écrit pour tester notre méthode. J'ai numéroté les parties clés du test JUnit et discuterai de chaque partie en détail ci-dessous.

Parties 1 et 2

Il s'agit d'importations pour les classes et packages JUnit utilisés par le test unitaire. Les importations peuvent être spécifiées en tant que classes individuelles, mais sont généralement spécifiées en tant que packages entiers à l'aide d'astérisques. Dans les deux cas, le niveau de granularité des importations est une question de préférence.

Partie 3

Cela définit le début de notre classe de test. La chose importante à prendre en compte ici est la convention de dénomination utilisée pour la classe, qui est NomClasseTest. Cette convention de dénomination n'est pas obligatoire, mais c'est la manière la plus courante de nommer les classes JUnit, car le nom décrit succinctement l'objectif de la classe de test unitaire et la classe qu'elle teste.

Partie 4

Ici, nous voyons notre première syntaxe spécifique à JUnit : l'annotation @Test. Les annotations sont extrêmement importantes lors de la création de JUnits. C'est ainsi que le framework JUnit identifie les parties importantes du test unitaire. Dans notre exemple, l'annotation @Test indique à JUnit que la méthode publique void à laquelle elle est attachée peut être exécutée comme cas de test.

Il existe de nombreuses autres annotations, mais certaines des plus courantes sont les suivantes.

  • @Before identifie une méthode qui doit être exécutée avant chaque méthode de test de la classe. Il est généralement utilisé pour mettre à jour ou réinitialiser l'état nécessaire au bon fonctionnement des méthodes de test.
  • @After identifie une méthode qui doit être exécutée après chaque méthode de test de la classe. Il peut être utilisé pour réinitialiser des variables, supprimer des fichiers temporaires, etc.
  • @Ignore spécifie qu'une méthode de test ne doit pas être exécutée.
  • @BeforeClass identifie une méthode qui doit être exécutée une fois avant l'exécution de toute méthode de test.
  • @AfterClass identifie une méthode qui doit être exécutée une fois après l'exécution de toutes les méthodes de test.

Partie 5

Encore une fois, notez la convention de dénomination testMethodNametestMethodName, Où methodName est le nom de la méthode testée dans la classe testée.

Partie 6

Dans le Donné section du test, nous construisons une nouvelle instance de la classe testée et l'initialisons comme il convient. Ceci est nécessaire car la méthode de test doit appeler la méthode testée pour la tester. Dans notre exemple, aucune autre initialisation n'est nécessaire au-delà de l'instanciation de la classe, mais dans de nombreux cas, une configuration supplémentaire peut être nécessaire, comme l'initialisation d'objets à transmettre au constructeur ou l'appel de méthodes qui configurent l'état de la classe testée.

Partie 7

, Quand La section du test comprend l'initialisation des variables qui doivent être transmises lors de l'appel de la méthode testée, puis de l'appel de la méthode de test (partie 8). Les variables doivent recevoir des valeurs significatives qui amènent le test à exercer les parties de la méthode de test qui nous intéressent. Notez que si une variable est un objet, elle peut être instanciée ou simulée.

Partie 8

Si la méthode testée renvoie une valeur, elle doit être capturée dans une variable afin que sa valeur puisse être affirmée.

Partie 9

Les tests unitaires ne sont utiles que s'ils incluent des assertions qui valident que la méthode testée renvoie la bonne valeur et/ou ajuste l'état des autres objets comme prévu. Sans assertions, vous n'avez aucune vérification, et votre test est au mieux un test de fumée qui ne donne un retour que lorsqu'une exception est levée.

Les méthodes d'assertion JUnit, qui sont incluses dans la classe org.junit.jupiter.api.Assertions dans JUnit 5 et dans la classe org.junit.Assert dans JUnit 4, sont couramment utilisées pour déterminer l'état réussite/échec des scénarios de test. Seules les assertions ayant échoué sont signalées par le framework JUnit. Comme pour les annotations, il existe de nombreuses options d'assertion.

Dans notre exemple JUnit ci-dessus, nous utilisons la méthode assertEquals (expected, actual, delta). Le premier argument est :

  • , résultat attendu, que l'auteur du test définit.
  • , sortie réelle, qui est la valeur de retour de la méthode appelée
  • , delta, ce qui permet un écart acceptable entre les valeurs attendues et réelles. Ce delta est spécifique au fait que nous validons la valeur d'un type double.
Découvrez Parasoft Jtest en action !

Comment exécuter un JUnit

Choisissez votre propre aventure! Ici, nous allons examiner trois façons d'exécuter JUnits: directement à partir de la ligne de commande, à partir de l'EDI (Eclipse et IntelliJ), et en utilisant des systèmes de construction (Maven et Gradle).

Comment exécuter un JUnit à partir de la ligne de commande

Pour exécuter une JUnit directement depuis la ligne de commande, vous avez besoin de quelques éléments :

  • JDK sur votre chemin
  • Le(s) fichier(s) jar JUnit
  • Les cas de test

La commande est la suivante. Cet exemple concerne JUnit 4.

java -cp /path/to/junit.jar org.junit.runner.JUnitCore <test class name>

Remarque : l'exécution d'un test à partir de la ligne de commande est le plus souvent effectuée à partir d'un processus CI/CD s'exécutant dans un système de génération tel que Jenkins ou Azure DevOps.

Comment exécuter un JUnit à partir de l'EDI

L'Éclipse

Dans l'Explorateur de packages, localisez votre test JUnit. Cliquez avec le bouton droit et sélectionnez Exécuter en tant que > Test JUnit. Cela exécutera votre test et rapportera les résultats dans la vue JUnit Eclipse.

IntelliJ

L'exécution d'un test dans IntelliJ est similaire à Eclipse. Dans la fenêtre Projet, localisez votre test, cliquez avec le bouton droit de la souris et sélectionnez Exécuter 'testName'. Comme Eclipse, une fenêtre JUnit s'ouvrira avec les résultats du test.

Comment exécuter un JUnit à l'aide de systèmes de construction

Maven

Maven a simplifié l'exécution des tests unitaires. Assurez-vous que vous êtes au bon endroit à partir de votre ligne de commande et que le projet pom.xml est correctement configuré. Ensuite, vous pouvez exécuter ce qui suit pour exécuter vos JUnits.

Pour exécuter l'intégralité de la suite de tests :

mvn test

Pour exécuter un ou plusieurs tests uniques/spécifiques :

mvn -Dtest=TestName test

gradle

Gradle, comme maven, a simplifié l'exécution des tests.

Pour exécuter l'intégralité de la suite de tests :

gradlew test

Pour exécuter un ou plusieurs tests uniques/spécifiques :

gradlew -Dtest.single=testName test

Remarque : Maven et Gradle sont leurs propres bêtes. Ce qui est montré ici est minimal pour couvrir les bases. Consultez leur documentation si vous voulez en savoir plus.

Poursuivre les tests unitaires

Notre exemple a parcouru un test unitaire simple, et bien sûr, ce n'est que le début des tests unitaires. Des méthodes plus complexes qui doivent être testées peuvent appeler des méthodes dans des classes dépendantes ou se connecter à des systèmes externes comme une base de données. Dans ce genre de cas, il peut être souhaitable d'isoler le code par railleur.

La moquerie aide à isoler les unités de code afin que nos tests unitaires puissent se concentrer uniquement sur la classe/méthode spécifique testée. Le framework le plus couramment utilisé pour se moquer dans les tests JUnit est Mockito.

Pour en savoir plus sur les moqueries, lisez le post de mon collègue : Comment automatiser un test unitaire Java, y compris les simulations et les assertions.

Donc, si les tests unitaires sont si importants, pourquoi tout le monde ne le fait-il pas de manière cohérente ? Eh bien, les tests unitaires ne sont pas faciles à mettre en œuvre. Il faut aussi beaucoup de compétences en développement. Les développeurs ont tendance à ne pas beaucoup apprécier les tests unitaires. Il faut de l'engagement et du temps pour maintenir les suites de tests.

Mais les avantages des tests unitaires sont clairs.

Il est nécessaire de s'assurer que le code précédemment écrit continue de fonctionner à mesure que le code évolue et que de nouvelles fonctionnalités sont ajoutées à l'application. Les tests unitaires s'exécutent généralement rapidement et sont efficaces pour détecter les régressions introduites dans le code. Les tests unitaires sont une exigence générale pour s'assurer que les applications continuent de fonctionner comme prévu. C'est un moyen rapide d'obtenir des commentaires sur les changements de code avant de les intégrer dans l'application.

Il est donc utile de déployer de puissants outils de test unitaire comme Jtest Parasoft qui peuvent résoudre de nombreux défis associés aux tests JUnit et faire gagner un temps précieux aux développeurs.

Alimenté par l'IA de Parasoft Jtest Assistant de test unitaire permet aux utilisateurs de générer rapidement des suites de tests qui couvrent 60 % ou plus de leur code d'application en une seule action. Lorsque la création de tests atteint les limites de ce qui peut être entièrement automatisé, l'assistant de test unitaire propose des flux de travail et des recommandations qui aident les utilisateurs à créer manuellement des tests plus efficacement.

De plus, le module d'analyse d'impact des tests accélère le temps d'exécution des tests unitaires dans les processus CI/CD ou l'IDE en identifiant et en exécutant uniquement le sous-ensemble de la suite de tests unitaires nécessaire pour valider les modifications récentes du code.

Découvrez par vous-même comment automatiser la génération de tests unitaires pour atteindre une couverture de code de plus de 60 % en moins de 5 minutes.

Par Nathan Jakubiak

Nathan est directeur principal du développement chez Parasoft. Lui et ses équipes développent des capacités de produits dans les domaines des tests d'API (SOAtest), de la virtualisation des services (Virtualize), de la gestion de l'environnement de test (CTP), des tests d'interface utilisateur (Selenic), de l'analyse statique et des tests unitaires (Jtest et C++test) . Nathan travaille chez Parasoft depuis 2000 et détient plusieurs brevets liés aux tests de logiciels. Il supervise l'architecture des produits et dirige plusieurs équipes de développement distribuées en utilisant la méthodologie agile scrum. Nathan dirige ses équipes pour créer des solutions logicielles de haute qualité et bien architecturées avec des processus de développement qui ont du sens.

Recevez les dernières nouvelles et ressources sur les tests de logiciels dans votre boîte de réception.