Aller au contenu

Automatisation avec JUnit

Référence du test dans Squash TM

Pour lier un cas de test Squash TM à un test automatisé JUnit, le champ Référence du test automatisé du bloc Automatisation du cas de test doit avoir la forme suivante :

[dépôt]/[projet]/[classe_test]#[méthode_test]
ou
[dépôt]/[classe_test]#[méthode_test]
ou
[dépôt]/[projet]/[classe_test]
ou
[dépôt]/[classe_test]
(La référence contient zéro ou un caractère #.)

avec :

  • [dĂ©pĂ´t] : Nom du dĂ©pĂ´t Git.

  • [projet] : Chemin vers le projet JUnit (c'est-Ă -dire le dossier contenant le fichier pom.xml).
    Ce paramètre est optionnel, c'est-à-dire que si le fichier pom.xml est à la racine du dépôt, ce chemin sera absent.

  • [classe_test] : Nom qualifiĂ© de la classe de test.

  • [mĂ©thode_test] : Nom de la mĂ©thode Ă  tester dans la classe de test.
    Ce paramètre est optionnel, c'est-à-dire qu'il peut être absent.

Tests Nested

Dans le cas de l'utilisation de classes @Nested, la référence du test doit avoir la forme suivante :

[dépôt]/[projet]/[classe_test]*
ou
[dépôt]/[classe_test]*
ou
[dépôt]/[projet]/[classe_test]$[classe_imbriquée]*
ou
[dépôt]/[classe_test]$[classe_imbriquée]*
ou
[dépôt]/[classe_test]$[classe_imbriquée]#[méthode_test]

Il peut y avoir une classe imbriquée à n'importe quel niveau, par exemple [dépôt]/[classe_test]$[classe_imbriquée]$[classe_sous_imbriquée]$[classe_sous_sous_imbriquée]* ou [dépôt]/[classe_test]$[classe_imbriquée]$[classe_sous_imbriquée]#[méthode_test].

Le métacaractère *

Le métacaractère * est nécessaire pour exécuter des tests dans toutes les classes imbriquées.
Il ne doit pas être utilisé si une méthode de test est ciblée.

avec :

  • [dĂ©pĂ´t] : Nom du dĂ©pĂ´t Git.

  • [projet] : Chemin vers le projet JUnit (c'est-Ă -dire le dossier contenant le fichier pom.xml).
    Ce paramètre est optionnel, c'est-à-dire que si le fichier pom.xml est à la racine du dépôt, ce chemin sera absent.

  • [classe_test] : Nom qualifiĂ© de la classe de test.

  • [classe_imbriquĂ©e]: Nom de la classe imbriquĂ©e.

  • [mĂ©thode_test] : Nom de la mĂ©thode Ă  tester dans la classe imbriquĂ©e.
    Ce paramètre est optionnel, c'est-à-dire qu'il peut être absent.

Version de Surefire et JUnit

Une version 3.0.0-M6 ou supérieure de Surefire est nécessaire pour exécuter des tests Nested.
@Nested a été testé en utilisant JUnit version 5.5.2 et des versions ultérieures, car nous avons rencontré des problèmes avec les versions antérieures.

Détermination du résultat du cas de test

Si une méthode [méthode_test] n'est pas spécifiée ou si elle est exécutée plusieurs fois (par exemple @RepeatedTest), le résultat du cas de test Squash TM est calculé en prenant en compte les résultats individuels de chaque test :

  • Si au moins un test est en statut Error (dans le cas d'un problème technique), l'exĂ©cution sera en statut Blocked.
  • Si au moins un test a Ă©chouĂ© fonctionnellement et qu'aucun test n'est en statut Error, l'exĂ©cution sera en statut Failed.
  • Si tous les tests ont rĂ©ussi, l'exĂ©cution sera en statut Success.

Ci-dessous un exemple de classe de test JUnit et l'automatisation du cas de test Squash TM associé :

Exemple JUnit

Exemple JUnit

JUnit 5

JUnit 5 est un framework de test très riche et offre une importante combinatoire de configurations possibles.
Squash Orchestrator utilise mvn test -Dtest=testclass#testmethod pour lancer chaque test.
Si vous utilisez la plateforme JUnit 5 de façon simple, cette ligne de commande fonctionne.

Exemple 1 :
Fichier pom.xml pour lancer des tests Ă©crits en JUnit 5 :

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>…</groupId>
    <artifactId>…</artifactId>
    <version>…</version>
    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
        </plugins>
    </build>
</project>

Exemple 2 :
Fichier pom.xml pour lancer des tests Ă©crits en JUnit 4 (dans un environnement JUnit 5) :

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>…</groupId>
    <artifactId>…</artifactId>
    <version>…</version>
    <dependencies>
        <dependency>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Si vous utilisez une configuration plus complexe, par exemple avec junit-platform-surefire-provider ou avec junit-platform-runner, veuillez vérifier que mvn test -Dtest=testclass#testmethod fonctionne.

Types de test JUnit 5 supportés

Les types de test suivants sont supportés :

Le support des noms d'affichage personnalisés @DisplayName n'est pas encore assuré.

Bug Surefire 3.0.0-M4/3.0.0-M5

Les versions 3.0.0-M4 et 3.0.0-M5 de Surefire contiennent un bug (SUREFIRE-1857) ayant pour effet que le rapport Surefire ne contient pas les messages d'erreur. En conséquence, les rapports Allure générés, de même, ne contiendront pas les messages d'erreur. Il est donc conseillé de ne pas utiliser ces versions.

Nature des paramètres Squash TM exploitables

Les paramètres Squash TM exploitables vont différer suivant si vous utilisez les composants Community/Premium ou Ultimate de Squash.

Voici le tableau des paramètres exploitables (ces paramètres sont transmis en tant que paramètres de test, voir ci-dessous, Squash TM ne génère pas de paramètres globaux) :

Nature Clé Community/Premium Ultimate
Nom du jeu de données DSNAME ✅ ✅
Paramètre d'un jeu de données DS_[nom] ✅ ✅
ID d'exécution TC_EXECUTION_ID ❌ ✅
Référence du cas de test TC_REFERENCE ✅ ✅
UUID interne du cas de test TC_UUID âś… âś…
Champ personnalisé du cas de test TC_CUF_[code] ✅ ✅
Champ personnalisé de l'itération IT_CUF_[code] ❌ ✅
Champ personnalisé de la campagne CPG_CUF_[code] ❌ ✅
Champ personnalisé de la suite de tests TS_CUF_[code] ❌ ✅

LĂ©gende :

  • [code] : valeur renseignĂ©e dans le champ “Code” d'un champ personnalisĂ©
  • [nom] : nom du paramètre tel que renseignĂ© dans Squash TM

Disponibilité de l'ID d'exécution

TC_EXECUTION_ID est disponible uniquement avec Squash TM 8.0 ou une version ultérieure.

Comme indiqué, Squash TM ajoute un préfixe au code du champ personnalisé transmis. Assurez-vous de le prendre en compte.

Voir la documentation de Squash TM pour plus d'information sur les champs personnalisés.

Utilisation de paramètres

Il est possible lors de l'exécution d'un test JUnit d'exploiter des paramètres au sein de celui-ci. Un paramètre peut être un paramètre de test ou un paramètre global. Squash TM ne transmet que des paramètres de test. Des paramètres de test et des paramètres globaux peuvent être utilisés dans le cas d'un lancement à partir d'un pipeline CI/CD avec l'action junit/params.

Pour cela, il faut suivre les Ă©tapes suivantes :

  • Importer la libraire opentestfactory-java-param-library dans le projet Maven contenant les tests Ă  exĂ©cuter en ajoutant au fichier pom.xml :

    • le dĂ©pĂ´t Maven suivant :
    <repositories>
        <repository>
            <id>org.squashtest.repo.release</id>
            <name>Squashtest repository for releases</name>
            <url>https://nexus.squashtest.org/nexus/repository/maven-squashtest-public-releases/</url>
        </repository>
    </repositories>
    
    • la dĂ©pendance Maven suivante :
    <dependencies>
        <dependency>
            <groupId>org.opentestfactory.util</groupId>
            <artifactId>opentestfactory-java-param-library</artifactId>
            <version>1.1.0</version>
        </dependency>
    </dependencies>
    
  • Vous pouvez ensuite rĂ©cupĂ©rer la valeur d'un paramètre du type souhaitĂ© en utilisant la syntaxe suivante :

    ParameterService.INSTANCE.getString("paramName");
    ParameterService.INSTANCE.getInt("paramName");
    ParameterService.INSTANCE.getFloat("paramName");
    ParameterService.INSTANCE.getDouble("paramName");
    ParameterService.INSTANCE.getBoolean("paramName");
    

    Les méthodes ci-dessus recherchent le paramètre souhaité dans les paramètres de tests ; si elles ne le trouvent pas, elles le cherchent ensuite dans les paramètres globaux.
    Ces méthodes propagent une ParameterNotFoundException si le paramètre n'est pas trouvé. Si le paramètre est trouvé mais ne peut être converti dans le type souhaité, une ParameterFormatException est propagée. Pensez à gérer ces exceptions dans vos classes de tests.
    Attention : la conversion de données booléennes renvoie true lorsque la chaîne de caractères à convertir est égale à "true" (quelqu'en soit la casse), false dans tous les autres cas ; mais elle ne propage jamais d'exception.

  • Il est aussi possible de dĂ©finir une valeur par dĂ©faut dans le cas oĂą le paramètre n'est pas trouvĂ© en utilisant la syntaxe suivante :

    ParameterService.INSTANCE.getString("paramName", defaultValue);
    ParameterService.INSTANCE.getInt("paramName", defaultValue);
    ParameterService.INSTANCE.getFloat("paramName", defaultValue);
    ParameterService.INSTANCE.getDouble("paramName", defaultValue);
    ParameterService.INSTANCE.getBoolean("paramName", defaultValue);
    

    Les méthodes ci-dessus ne propagent donc pas de ParameterNotFoundException quand le paramètre recherché n'est pas trouvé mais propagent une ParameterFormatException si le paramètre est bien trouvé, mais ne peut être converti dans le type souhaité.

  • Il est Ă©galement possible de cibler un paramètre de test ou un paramètre global avec des mĂ©thodes spĂ©cifiques. Comme pour les mĂ©thodes prĂ©cĂ©dentes, elles sont disponibles dans des versions avec et sans valeur par dĂ©faut. En voici quelques exemples :

    ParameterService.INSTANCE.getTestString("paramName");
    ParameterService.INSTANCE.getGlobalInt("paramName");
    ParameterService.INSTANCE.getTestFloat("paramName", defaultValue);
    ParameterService.INSTANCE.getGlobalBoolean("paramName", defaultValue);
    

Exemple

Ci-dessous un exemple de fichier de test JUnit et l'automatisation du cas de test Squash TM associé :

package squash.tfauto;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.opentestfactory.exception.ParameterException;
import org.opentestfactory.exception.ParameterFormatException;
import org.opentestfactory.util.ParameterService;

public class ParameterTest {

  @Test
  public void sub() throws ParameterException {
    int var1 = ParameterService.INSTANCE.getInt("DS_VAR1");
    int var2 = ParameterService.INSTANCE.getTestInt("DS_VAR2");
    int res = ParameterService.INSTANCE.getTestInt("DS_RES");
    Assertions.assertEquals(res, var1 - var2, "Wrong calculation result");
  }

  @Test
  public void add() throws ParameterFormatException {
    float var1 = ParameterService.INSTANCE.getFloat("DS_FAKE_VAR1", 42.21f);
    float var2 = ParameterService.INSTANCE.getTestFloat("DS_FAKE_VAR2", 15.23f);
    float res = ParameterService.INSTANCE.getTestFloat("DS_FAKE_RES", 57.44f);
    Assertions.assertEquals(res, var1 + var2, "Wrong calculation result");
  }

  @Test
  public void displayLabel() throws ParameterException {
    Boolean isDisplay = ParameterService.INSTANCE.getBoolean("DS_DISPLAY");
    String label = "default";
    if (isDisplay) {
      label = ParameterService.INSTANCE.getString("TC_CUF_LABEL");
    }
    Assertions.assertEquals("Squash", label, "Wrong label displayed");
  }
}

Exemple paramètres JUnit

Exemple paramètres JUnit

Ajout de paramètres sur la ligne de commande de lancement d'un test

Il est possible de passer des paramètres supplémentaires à la commande mvn test en utilisant la variable d'environnement JUNIT_EXTRA_OPTIONS. La définition d'une variable d'environnement dans Squash TM et son association à l'orchestrateur sont exemplifiées ici.

Certains paramètres sont déjà définis dans la commande mvn test utilisée pour lancer un test :

mvn test \
  -f "{POM_path}" -Dtest={test_name} \
  -Dmaven.test.failure.ignore=true -DfailIfNoTests=true \
  --log-file {junit_run_log_path} $JUNIT_EXTRA_OPTIONS

Il faut éviter de passer, via la variable d'environnement JUNIT_EXTRA_OPTIONS, des paramètres sur la ligne de commande qui sont en conflit avec ceux déjà utilisés ou qui impactent la création ou la localisation des rapports attendus par l'orchestrateur (voir leur liste ici).

Non support du caractère espace sur Linux

Squash Orchestrator ne supporte aujourd'hui pas le caractère espace () dans la variable d'environnement JUNIT_EXTRA_OPTIONS pour les tests exécutés dans un environnement d'exécution Linux.

Amélioration des performances

Il est possible d'utiliser Maven Daemon, un wrapper de Maven, pour accélérer les exécutions des tests JUnit : voir les détails techniques. Maven Daemon est utile dans le cas où les tests exécutés sont courts et nombreux. Pour les tests qui durent, chacun, au-delà de quelques minutes, il n'a pas d'intérêt réel.

Versions supportées

Squash a été validé avec

  • JUnit 4.12, toute version plus rĂ©cente de JUnit 4 devrait fonctionner
  • JUnit 5.3.2, toute version de JUnit 5 devrait fonctionner

De plus, il est recommandé d'utiliser Surefire 2.19.1 ou supérieur (mais pas 3.0.0-M4/3.0.0-M5, voir ci-dessus).