Tests unitaires
Tests unitaires
Avant-propos
Cette documentation décrit des tests unitaires effectués avec JUnit 5. Un lien vers les fichiers source est fourni ici ou en bas de page.
Préparation de l’environnement
Il faut commencer par créer un dossier source qui contiendra les différentes classes nécessaires au fonctionnement des tests.
Pour cela, il faut cliquer droit sur le projet puis “New” -> “Source Folder”. Il est coutume de nommer ce dossier “srctest” si aucune directive n’est donnée quant au nom de ce dossier.
Cliquer sur “Finish”.
Ensuite, il faut créer un package avec un nom adapté tel que “com.entreprise.nomPlugin.test”.
Construction d’un point d’entrée
Avant la construction des tests, il est nécessaire de créer un point d’entrée vers un Yellowbox fictif. Pour cela, il va falloir créer une classe qui implémentera l’interface com.yellowbox.plugin.v3.YellowboxEntryPoint
que l’on peut nommer “TestYellowboxEntryPoint” par exemple.
Ensuite, il faudra implémenter toutes les méthodes proposées par cette interface qui seront utilisées (Nous décrirons l’implémentation de getServices()
plus bas). Il suffit de laisser les autres vides ou retourner null
.
package com.dimosoftware.devplugin.tests;
import com.yellowbox.plugin.log.ILog;
import com.yellowbox.plugin.notification.INotifUser;
import com.yellowbox.plugin.service.YellowboxService;
import com.yellowbox.plugin.v3.YellowboxEntryPoint;
public class TestYellowboxEntryPoint implements YellowboxEntryPoint {
public TestYellowboxEntryPoint() {}
public Object get(String val) {
return null;
}
public String getCheminDocjoint() {
return null;
}
public String getIdTable() {
return null;
}
public String getIdUtilisateur() {
return null;
}
public String getLangue() {
return null;
}
public ILog getLog() {
return null;
}
public INotifUser getNotification() {
return null;
}
public YellowboxService getServices() {
return null;
}
}
Mock-up des services
Pour ce qui concerne la méthode getServices()
, il va être nécessaire de créer une classe qui implémente l’interface com.yellowbox.plugin.service.YellowboxService
en amont, nommée “TestYellowboxService” par exemple.
Ensuite, il faudra définir un attribut YellowboxService
dans notre classe TestYellowboxEntryPoint
. Il sera initialisé dans le constructeur et pourra être retourné par la méthode getServices()
.
private YellowboxService service;
public TestYellowboxEntryPoint(YellowboxService service) {
this.service = service;
}
public YellowboxService getServices() {
return service;
}
L’interface com.yellowbox.plugin.service.YellowboxService
permet l’accès à différents services qui correspondent à différentes classes à créer et qui sont définies sous cette forme : com.yellowbox.plugin.service.IMonService
. Dans cette documentation, nous développerons le cas de l’interface com.yellowbox.plugin.service.IRecordService
en créant une classe “TestRecordService” qui l’implémente.
package com.dimosoftware.devplugin.tests;
import com.yellowbox.plugin.service.IRecordService;
import com.yellowbox.ws.beans.ImportRecord;
import com.yellowbox.ws.beans.Page;
import com.yellowbox.ws.beans.Pageable;
import com.yellowbox.ws.beans.Record;
import com.yellowbox.ws.beans.SearchValues;
public class TestRecordService implements IRecordService {
public TestRecordService() {}
public String createOrUpdate(Record record) {
return null;
}
public String createOrUpdateV2(ImportRecord importRecord) {
return null;
}
public void deleteRecord(String idRecord) {}
public List<Record> executeSearch(String idSearch) {
return null;
}
public List<Record> executeSearch(String idSearch, String varReffiche) {
return null;
}
public Page<Record> executeSearch(String idSearch, Pageable pageable, String varReffiche) {
return null;
}
public List<Record> executeSearchByValues(SearchValues searchValues) {
return null;
}
public Page<Record> executeSearchByValues(SearchValues searchValues, Pageable pageable) {
return null;
}
public Record getOneRecordTableLinked(String idElement, String idTableElement, String idTableLink) {
return null;
}
public Record getRecordByFieldId(String fieldId, Record record) {
return null;
}
public Record getRecordFromId(String idRecord) {
return null;
}
public List<Record> getRecordsByTableLinkedToElement(String idElement, String idTableElement, String idTableLink) {
return null;
}
public Page<Record> getRecordsByTableLinkedToElement(String idElement, String idTableElement, String idTableLink, Pageable pageable) {
return null;
}
}
Ensuite, il faudra définir un attribut IRecordService
dans notre classe TestYellowboxService
. Il sera initialisé dans le constructeur et pourra être retourné par la méthode getTableService()
.
private IRecordService recordService;
public TestYellowboxService(IRecordService recordService) {
this.recordService = recordService;
}
public IRecordService getRecordService() {
return recordService;
}
Il suffit maintenant de définir les attributs et d’implémenter les méthodes de notre classe TestRecordService
qui sont utilisées par le plugin en développement. Les autres peuvent être laissées vides ou retourner null
.
package com.dimosoftware.devplugin.tests;
import java.util.ArrayList;
import java.util.List;
import com.yellowbox.plugin.service.IRecordService;
import com.yellowbox.ws.beans.ImportRecord;
import com.yellowbox.ws.beans.Page;
import com.yellowbox.ws.beans.Pageable;
import com.yellowbox.ws.beans.Record;
import com.yellowbox.ws.beans.SearchValues;
public class TestRecordService implements IRecordService {
List<Record> records = new ArrayList<>();
public TestRecordService(List<Record> records) {
this.records = records;
}
public String createOrUpdate(Record record) {
return null;
}
public String createOrUpdateV2(ImportRecord importRecord) {
boolean updated = false;
for(Record record : records) {
if(record.getId().equals(importRecord.getRecord().getId())) {
for(Value value : importRecord.getRecord().getValues()) {
boolean isPresent = false;
for(Value newVal : record.getValues()) {
if(newVal.getField().getId().equals(value.getField().getId())) {
isPresent = true;
if(!newVal.getValue().equals(value.getValue())) {
newVal.setValue(value.getValue());
}
break;
}
}
if(!isPresent) {
record.getValues().add(value);
}
}
updated = true;
break;
}
}
boolean created = updated ? false : records.add(importRecord.getRecord());
String result = "";
if(updated) {
result = "UPDATE";
} else if(created) {
result = "CREATE";
} else {
result = "FAIL";
}
return result;
}
public void deleteRecord(String idRecord) {}
public List<Record> executeSearch(String idSearch) {
return null;
}
public List<Record> executeSearch(String idSearch, String varReffiche) {
return null;
}
public Page<Record> executeSearch(String idSearch, Pageable pageable, String varReffiche) {
return null;
}
public List<Record> executeSearchByValues(SearchValues searchValues) {
return null;
}
public Page<Record> executeSearchByValues(SearchValues searchValues, Pageable pageable) {
return null;
}
public Record getOneRecordTableLinked(String idElement, String idTableElement, String idTableLink) {
return null;
}
public Record getRecordByFieldId(String fieldId, Record record) {
return null;
}
public Record getRecordFromId(String idRecord) {
Record record = new Record();
for(Record recordTemp : records) {
if(recordTemp.getId().equals(idRecord)) {
record = recordTemp;
break;
}
}
return record;
}
public List<Record> getRecordsByTableLinkedToElement(String idElement, String idTableElement, String idTableLink) {
return null;
}
public Page<Record> getRecordsByTableLinkedToElement(String idElement, String idTableElement, String idTableLink, Pageable pageable) {
return null;
}
}
Pour les tests, ce sont les différents services du YellowboxEntryPoint qui contiennent la base de donnée. Ainsi, on définira la base de données lors de l’écriture des tests.
Implémentation d’un test
Création d’un test
Nous allons d’abord créer un Test Case. Pour cela, il faut cliquer droit sur le package de test créé auparavant (dans l’exemple, com.dimosoftware.devplugin.tests
) puis “New” -> “Other”, taper “JUnit” et sélectionner “JUnit Test Case” et cliquer sur “Next”.
Ensuite, il faut donner un nom à notre test. Ici, nous proposerons de tester la fonction du plugin CalculSuperficie
et nous nommerons donc notre test “TestCalculSuperficie”.
Cocher les méthodes setUp()
et tearDown()
à créer.
Cliquer sur “Browse” pour rechercher la classe à tester. Sélectionner la classe CalculSuperficie
. Cliquer sur “Ok”.
Cliquer ensuite sur “Next”. Sélectionner les méthodes à tester. Nous choisirons de ne tester que la méthode call()
de notre plugin.
Ainsi, vous devriez obtenir le résultat suivant :
package com.dimosoftware.devplugin.tests;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class TestCalculSuperficie {
@BeforeEach
void setUp() throws Exception {
}
@AfterEach
void tearDown() throws Exception {
}
@Test
void testCall() {
fail("Not yet implemented");
}
}
Strucutre globale du test
Nous allons tout d’abord définir trois attributs pour notre classe TestCalculSuperficie
qui correspondent respectivement à :
- une instance du plugin à tester,
- un entier qui correspond à la superficie à calculer,
- un entier qui correspond au prix à calculer
Les deux derniers attributs seront utilisés pour vérifier que le plugin a correctement effectué son calcul.
private static CalculSuperficie plugin;
private static int superficie;
private static int prix;
La méthode setUp()
initialisera le plugin avant chaque test.
@BeforeEach
void setUp() throws Exception {
plugin = new CalculSuperficie();
}
La méthode tearDown()
réinitialisera les attributs après chaque test.
@AfterEach
void tearDown() throws Exception {
plugin = null;
superficie = 0;
prix = 0;
}
Maintenant, nous allons définir une méthode qui viendra créer notre base de données et qui créera le point d’entrée. En même temps, nous définirons les paramètres d’entrée du plugin.
static Stream<Arguments> validArgumentsProvider() {
return null;
}
Nous utiliserons ensuite cette méthode pour implémenter un test paramétré au lieu d’un test classique. Les paramètres reçus par la méthode testCall()
seront le point d’entrée et les ParamValues
du plugin.
@ParameterizedTest
@MethodSource("validArgumentsProvider")
void testCall(TestYellowboxEntryPoint yep, ParamValues pv) {
fail("Not yet implemented");
}
Implémentation de la méthode de paramétrisation du test
Concentrons nous sur la méthode validArgumentsProvider()
. Pour commencer, nous allons définir tous les IDs dont nous avons besoin.
// Définition des IDs
String idElement = "terr0";
String idFieldLongueur = "fLong";
String idFieldLargeur = "fLarg";
String idFieldPrixMetreCarre = "fPriMetCar";
String idFieldPrix = "fPrix";
String idFieldSuperficie = "fSup";
Ensuite, nous définirons la valeur des champs qu’a besoin le plugin. Ces valeurs peuvent être changées à votre bon vouloir.
// Définition des valeurs
int longueur = 5;
int largeur = 5;
int prixMetreCarre = 5;
Nous initialiserons ici les valeurs de nos attributs de vérification.
// Définition des valeurs à vérifier
superficie = longueur * largeur;
prix = superficie * prixMetreCarre;
Une fois les valeurs définies, nous créerons les Fields de notre futur Terrain
.
// Définition des Fields
Field fieldLongueur = new Field(idFieldLongueur, "Longueur", "");
Field fieldLargeur = new Field(idFieldLargeur, "Largeur", "");
Field fieldPrixMetreCarre = new Field(idFieldPrixMetreCarre, "Prix au mètre carré", "");
Field fieldPrix = new Field(idFieldPrix, "Prix", "");
Field fieldSuperficie = new Field(idFieldSuperficie, "Superficie", "");
Maintenant, nous pouvons créer les Values qui seront attribuées à notre Terrain
dans une liste. Nous ferons attention à bien laisser les champs “Superficie” et “Prix” avec une Value vide.
// Définition des Values
Value valueLongueur = new Value(fieldLongueur, String.valueOf(longueur));
Value valueLargeur = new Value(fieldLargeur, String.valueOf(largeur));
Value valuePrixMetreCarre = new Value(fieldPrixMetreCarre, String.valueOf(prixMetreCarre));
Value valueSuperficie = new Value(fieldSuperficie, "");
Value valuePrix = new Value(fieldPrix, "");
List<Value> values = new ArrayList<>();
values.add(valueLongueur);
values.add(valueLargeur);
values.add(valuePrixMetreCarre);
values.add(valueSuperficie);
values.add(valuePrix);
Enfin, nous créerons un Record qui représentera notre Terrain
et qui contiendra la liste de Values précédemment créée. Le Record sera ajouté à une liste pour constituer la base de données du point d’entrée.
// Définition d'un Record
Record terrain = new Record();
terrain.setId(idElement);
terrain.setValues(values);
List<Record> records = new ArrayList<>();
records.add(terrain);
Nous pouvons finalement créer notre point d’entrée.
// Définition du point d'entrée qui contient la base
TestYellowboxEntryPoint entryPoint = new TestYellowboxEntryPoint(
new TestYellowboxService(
new TestRecordService(records)
)
);
Nous n’oublierons pas de définir les paramètres du plugin également.
// Définition des paramètres pour le plugin
ParamValues listePV = new ParamValues();
listePV.addStringValue(CalculSuperficie.PARAMVALIDELEMENT, idElement);
listePV.addStringValue(CalculSuperficie.PARAMIDFIELDLONGUEUR, idFieldLongueur);
listePV.addStringValue(CalculSuperficie.PARAMIDFIELDLARGEUR, idFieldLargeur);
listePV.addStringValue(CalculSuperficie.PARAMIDFIELDPRIXMETRECARRE, idFieldPrixMetreCarre);
listePV.addStringValue(CalculSuperficie.PARAMIDFIELDPRIX, idFieldPrix);
listePV.addStringValue(CalculSuperficie.PARAMIDFIELDSUPERFICIE, idFieldSuperficie);
Il ne reste plus qu’à retourner le point d’entrée et les paramètres du plugin.
return Stream.of(Arguments.of(entryPoint, listePV));
Implémentation du test paramétré
Nous détaillerons ici l’implémentation de la méthode testCall()
. Pour commencer, nous allons initialiser le plugin avec les paramètres fournis par la méthode validArgumentsprovider()
.
// Initialisation du plugin
plugin.setYellowboxEntryPoint(yep);
plugin.setParamValues(pv);
Ensuite, nous lancerons la méthode à tester.
// Lancement de la fonction
plugin.call();
Enfin, nous viendrons vérifier le resultat attendu avec nos attributs calculés en amont dans la méthode validArgumentsProvider()
.
// Vérification du résultat
String idElement = plugin.getParamValues().getStringValue(CalculSuperficie.PARAMVALIDELEMENT);
String idFieldSuperficie = plugin.getParamValues().getStringValue(CalculSuperficie.PARAMIDFIELDSUPERFICIE);
String idFieldPrix = plugin.getParamValues().getStringValue(CalculSuperficie.PARAMIDFIELDPRIX);
Record result = yep.getServices().getRecordService().getRecordFromId(idElement);
boolean superficieOK = false, prixOK = false;
for(Value val : result.getValues()) {
if(val.getField().getId().equals(idFieldSuperficie)) {
superficieOK = true;
assertTrue(val.getValue().equals(String.valueOf(superficie)),
"Superficie: " + val.getValue() + " == " + superficie);
}
if(val.getField().getId().equals(idFieldPrix)) {
prixOK = true;
assertTrue(val.getValue().equals(String.valueOf(prix)),
"Prix: " + val.getValue() + " == " + prix);
}
}
assertTrue(superficieOK, "Le champ superficie est absent");
assertTrue(prixOK, "Le champ prix est absent");
Si le test n’a pas trouvé d’erreur, alors vous devriez avoir le retour suivant :
Au contraire, si une erreur est détectée, alors vous aurez le retour suivant :
Vous pouvez alors afficher l’erreur dans la console.
Code source
Le code source est disponible ici sous la forme d’une archive, importable dans l’IDE Eclipse.