Tests unitaires

Author: Unknown

Date: 13/11/2024

J'ai franchement plutôt envie d'exploiter mon objet Config pour commencer à parcourir les dossiers de notes, et commencer à lire les fichiers .md pour en faire des objets Note avec des étiquettes, et avoir une liste d'étiquettes, et pour chaque étiquette, une liste ordonnée des Note qui mentionne chaque étiquette.

Mais....

Il faut faire les tests unitaires dès le début d'un projet, sinon, c'est la chienlit! Et puis, cela me permettra ensuite de lister plusieurs cas différents de note à parser.

Pas de bol, cela veut dire potasser le sujet.

Ou y aller en mode bourrin, et comprendre ce que je fais, et l'améliorer.

Allez go pour cette option !

Implémentation naïve avec chatgpt

En reprenant l'historique de la conversation précédente: moi: Si je veux implémenter des tests pour vérifier que mon code lit correctement mon fichier de config, je fais comment ? GPT-4o: Pour tester que votre code lit correctement le fichier de configuration, vous pouvez utiliser JUnit, qui est la bibliothèque de test la plus couramment utilisée en Java. Voici comment vous pouvez mettre en place des tests unitaires pour votre code de configuration :

Étape 1 : Ajouter JUnit à votre projet

Assurez-vous que JUnit est inclus en tant que dépendance dans votre pom.xml. Voici comment l'ajouter :

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

Étape 2 : Créer des tests unitaires

  1. Créez un fichier de test dans src/test/java. Assurez-vous que votre structure de répertoires de test est similaire à celle de vos sources principales. Par exemple : src/test/java/noteblogger/ConfigLoaderTest.java
  2. Écrivez les tests unitaires avec JUnit.
package noteblogger;

import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;

import java.io.IOException;

public class ConfigLoaderTest {

    private Config config;

    @Before
    public void setUp() throws IOException {
        ConfigLoader loader = new ConfigLoader();
        config = loader.loadConfig("config.json");
    }

    @Test
    public void testGetDirectories() {
        assertNotNull("Directories should not be null", config.getDirectories());
        assertFalse("Directories should not be empty", config.getDirectories().isEmpty());
    }

    @Test
    public void testGetFiles() {
        assertNotNull("Files should not be null", config.getFiles());
        assertFalse("Files should not be empty", config.getFiles().isEmpty());
    }

    @Test
    public void testGetOutputDirectory() {
        assertNotNull("Output directory should not be null", config.getOutputDirectory());
        assertFalse("Output directory should not be empty", config.getOutputDirectory().isEmpty());
    }

    @Test
    public void testConfigDetails() {
        String details = config.getConfigDetails();
        assertNotNull("Config details should not be null", details);
        assertTrue("Config details should contain expected information", details.contains("Directories:"));
    }
}

Étape 3 : Exécuter les tests

  • Depuis IntelliJ IDEA : Cliquez droit sur le fichier ConfigLoaderTest.java ou le répertoire de test et sélectionnez Run 'ConfigLoaderTest'.
  • Par Maven : Utilisez la commande mvn test pour exécuter tous les tests.

Explications

  • @Before : Annotation pour la méthode setUp() qui initialise les objets nécessaires avant chaque test.
  • Assertions : assertNotNullassertFalse, et assertTrue vérifient les conditions attendues.

Bonnes Pratiques

  • Mock des dépendances si nécessaire : Utilisez des concepts de mocking pour tester des composants en isolation.
  • Tester divers scénarios : Créez des tests pour les cas de succès et les cas d'erreur (par exemple, gérer un fichier de config manquant ou mal formé). Avec ces tests unitaires, vous assurez la fiabilité de votre code de configuration !

Résolution des problèmes

Dependency 'junit:junit:4.13.2' not found

Bon, problème, IntelliJ me dit Dependency 'junit:junit:4.13.2' not found. Si je cherche un peu sur le net, déjà je trouve qu'il y JUnit5 et jUnit4. Et quand je regarde les différences, aucun intérêt de rester sur du JUnit4. Et dans ce cas, il faut plutôt mettre

<dependency>
	<groupId>org.junit.jupiter</groupId>
	<artifactId>junit-jupiter-engine</artifactId>
	<version>5.2.0</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.junit.platform</groupId>
	<artifactId>junit-platform-runner</artifactId>
	<version>1.2.0</version>
	<scope>test</scope>
</dependency>

Mouais, pas mieux dans IntelliJ en fait. Un peu de recherche sur le net.... Ah, OK, faut rechercher maven. Dans IntelliJ, c'est clic droit sur le pom.xml, puis l'entrée Maven et enfin l'entrée "Reload project".

Premier test

Je corrige le code fourni par chatgpt qui ne reflète/reprends pas les choix et modification que j'ai fait à la main. Je lance le test en le lançant à la main. Et, après petite rectification, ca passe.

Faire comprendre à IntelliJ qu'on est en JUnit 5 et JUnit 4

IntelliJ ne semble pas comprendre

@Test  
@DisplayName("Config file does not exist")

Bien que le pom.xml pointe vers JUnit5. => il faut rajouter un import org.junit.jupiter.api.DisplayName;

Ajouter un autre test

J'aimerais faire des tests en maitrisant, dans le cadre de mon test, le contenu du fichier config, pour faire exprès d'avoir des fichiers de config vérolés par exemple. Pour cela, je rajoute des fichiers de config, mais dans l'arborescence de test:

src/test/resources/
├── valid-config.json
├── missing-fields-config.json
└── malformed-config.json

J'ai bien des tests qui foirent. Mais du coup, je lance des Exceptions au cas par cas à la lecture du fichier de configuration. Cela nécessite d'exploser le morceau de code

try (InputStream is =getClass().getClassLoader().getResourceAsStream(filePath);  
     JsonReader reader = Json.createReader(is)) {  
    JsonObject config = reader.readObject();

en

InputStream is=null;  
try {  
    is = getClass().getClassLoader().getResourceAsStream(resource);  
    if (is == null)  
        throw new IllegalArgumentException("Config file does not exist:" + resource);  
    JsonReader reader = Json.createReader(is);  
    JsonObject json = reader.readObject();
    ...
} catch(javax.json.stream.JsonParsingException e) {  
    throw new IllegalArgumentException("Config file exists but is not a valid JSON File " + resource +":"+e.getMessage(),e);  
} finally {  
    if (is!=null)  
        try {  
            is.close();  
        } catch(IOException e) {  
            throw new RuntimeException(e);  
        }  
}    

Ce qui m'oblige à rajouter un bloc finally à la fin. Cela me parait old school comme morceau de code, du coup, non ?

Exécuter plusieurs tests d'un coup

J'aimerais plutôt qu'il y ait quelque part un "run tests", par exemple après un clic droit sur le pom.xml. Mais non.

Tags: computing back2code