TestNG, nouveau framework de tests unitaires Java
Exemple de tests avec passage de paramètres
Dans ce test nous allons pouvoir voir comment fonctionne le passage de paramètres de manière statique mais aussi de manière dynamique grâce au @DataProvider
Principes généraux du test
Dans cet exemple nous utilisons les deux mêmes objets métier que précédemmment, à savoir l'Apprentice et la Stream.
Cette fois les différents objets auront leurs propriétés stockées dans une base de données. J'ai utilisé une base de type MySQL, que j'ai rempli de quatre apprentis et plusieurs filières dont un apprenti sans filière.
Vous pouvez trouver le fichier concernant de la base Xpose. Cette base sera réutilisée par la suite dans l'exemple de généralisation des tests par une @Factory.
Dans ce test, nous allons utiliser le passage de paramètres statique pour spécifier les paramètres concernant la base de données, à savoir :
- L'URL de la base de données
- Le login d'accès à la base
- Le password du compte
Par ailleurs, nous utiliserons un passage de paramètres dynamique (avec un DataProvider) pour effectuer un test sur chaque apprenti de la base. Ce test utilise les données que lui fourni le DataProvider. Le test vérifie que tous les attributs de l'objet Apprentice sont non nuls.
Mise en oeuvre des tests : TestNGParameters.java
Les méthodes de tests
Dans cette classe, nous avons 4 méthodes utilisées par TestNG :
- void setUpData(String url, String user, String password) qui permet d'ouvrir la connection à la base de données via JDBC.
- void tearDownData() qui clôt la connection à la base de données.
- void verifyAllApprentice(Apprentice apprentice) qui effectuera la vérification des attibuts de l'apprenti passé en paramètres.
C'est cette méthode qui spécifiera qu'elle attend des paramètres provenant d'un DataProvider nommé listAll. - Iterator<Object[]> giveData() qui sera la méthode excerçant la fonction de DataProvider.
Elle permet de récupérer tous les apprentis de la base ainsi que leur filière.
Passage de paramètres de manière statique
Pour passer des paramètres de manière statique, nous allons utiliser l'annotation @Parameters pour spécifier une attente de paramètres venant du fichier testng.xml.
Voici le code de la méthode setUpData() utilisant cette technique :
/**
* Passage de paramètres via le fichier XML pour des infos générales (Base de données)
* @param url url de la base
* @param user le login de la base
* @param password le password de la base
*/
@Configuration(beforeTestClass = true)
/* On spécifie que l'on attend trois paramètres */
/* et les noms donnés sont les noms des paramètres écrits dans le fichier testng.xml */
@Parameters({ "url", "user", "password" })
public void setUpData(String url, String user, String password) {
try {
Class.forName("com.mysql.jdbc.Driver");
jdbcConnection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
Le fichier testng.xml associé
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Parameters" verbose="5" >
<test name="Parameters">
<!-- Définition des paramètres et de leur valeurs -->
<parameter name="url" value="jdbc:mysql://localhost:3306/Xpose"/>
<parameter name="user" value="root"/>
<parameter name="password" value=""/>
<classes>
<class name="parameters.TestNGParameters"/>
</classes>
</test>
</suite>
Nous venons de spécifier 3 paramètres statique pour notre méthode citée ci-dessus. Ils sont reconnus par leur nom dans l'annotation @Parameters. Bien entendu, l'ordre des paramètres est important.
Passage de paramètres de manière dynamique
Nous allons maintenant voir comment utiliser les DataProvider afin de récupérer dynamiquement des données, qui seront ensuite utilisées par la méthode de test utilisant ce DataProvider.
Code de la méthode utilisant le DataProvider :
/**
* Test les paramètres du DataProvider
* @param apprentice l'apprenti testé
*/
/* Spécification du DataProvider qui nous donnera les Apprentice attendus en paramètres */
@Test(dataProvider = "listAll", groups = "parameters")
public void verifyAllApprentice(Apprentice apprentice){
/* Vérification des données de l'apprenti reçu en paramètre. */
assertNotNull(apprentice.getName(), "Name should not be null");
assertNotNull(apprentice.getFirstName(), "First name of <"+apprentice.getName()+"> should not be null");
assertNotNull(apprentice.getStream(), "Stream of <"+apprentice.getName()+"> should not be null");
}
Ici nous attendrons que le DataProvider listAll nous fournisse des Apprentice.
Le code de la méthode du DataProvider ne fait que récupérer les informations de la base de données
en les plaçant dans une liste. Cette méthode renverra un Iterator sur cette même liste d'Object.
/**
* Permet de servir de source de données
* @return l iterateur des objets créés
*/
/* Définition du DataProvider de nom listAll. */
@DataProvider(name = "listAll")
public Iterator
Exécution des tests
Grâce à Ant, nous allons exécuter le test et analyser le résultat.
# Une seule méthode de tests a été trouvée.
# La méthode fournissant les données n'est pas comptée.
[testng] TESTCLASS: parameters.TestNGParameters
[testng] [TestClass] BeforeClass : parameters.TestNGParameters.setUpData(java.lang.String, java.lang.String, java.lang.String)
[testng] [TestClass] Test : parameters.TestNGParameters.verifyAllApprentice(parameters.Apprentice)
[testng] [TestClass] AfterClass : parameters.TestNGParameters.tearDownData()
[testng] [TestClass]
...
# Lancement des tests.
# Nous voyons bien que la méthode est appelée 4 fois, ce qui correspond bien au nombre d'apprentis dans la base.
[testng] [TestRunner] Found 1 applicable methods
[testng] [Invoker 5383406] Invoking parameters.TestNGParameters.setUpData(java.lang.String, java.lang.String, java.lang.String)
[testng] [Invoker 5383406] Invoking parameters.TestNGParameters.verifyAllApprentice
[testng] [Invoker 5383406] Invoking parameters.TestNGParameters.verifyAllApprentice
[testng] [Invoker 5383406] Invoking parameters.TestNGParameters.verifyAllApprentice
[testng] [Invoker 5383406] Invoking parameters.TestNGParameters.verifyAllApprentice
[testng] [Invoker 5383406] Invoking parameters.TestNGParameters.tearDownData()
[testng] *********** INVOKED METHODS
# Ici nous voyons les paramètres passés aux méthodes, que ce soit en statique ou dynamique.
# Le password pour la méthode setUpData() est vide d'où le fait que l'on ne le voit pas.
[testng] parameters.TestNGParameters.setUpData(java.lang.String, java.lang.String, java.lang.String)jdbc:mysql://localhost:3306/Xpose root 30971263
[testng] parameters.TestNGParameters.verifyAllApprentice(parameters.Apprentice)parameters.Apprentice@3ee284 30971263
[testng] parameters.TestNGParameters.verifyAllApprentice(parameters.Apprentice)parameters.Apprentice@8965fb 30971263
[testng] parameters.TestNGParameters.verifyAllApprentice(parameters.Apprentice)parameters.Apprentice@867e89 30971263
[testng] parameters.TestNGParameters.verifyAllApprentice(parameters.Apprentice)parameters.Apprentice@1dd7056 30971263
[testng] parameters.TestNGParameters.tearDownData() 30971263
# Résultats des tests
[testng] ***********
[testng] PASSED: verifyAllApprentice
[testng] PASSED: verifyAllApprentice
[testng] PASSED: verifyAllApprentice
# Un des apprentis ne passaient pas le test car il n'a pas de filière.
[testng] FAILED: parameters.TestNGParameters.verifyAllApprentice(parameters.Apprentice)
[testng] java.lang.AssertionError: Stream of <Apprenti2> should not be null expected:<true> but was:<false>
[testng] at org.testng.Assert.fail(Assert.java:73)
...
# Résumé, création des rapports
[testng] ===============================================
[testng] Parameters
[testng] Tests run: 4, Failures: 1, Skips: 0
[testng] ===============================================
[testng] Creating E:\workspace\Xpose_TestNG\reports\testng\parameters\testng-failures.xml
[testng] Creating E:\workspace\Xpose_TestNG\reports\testng\parameters\toc.html
[testng] Creating E:\workspace\Xpose_TestNG\reports\testng\parameters\Parameters.properties
[testng] Creating E:\workspace\Xpose_TestNG\reports\testng\parameters\index.html
[testng] Creating E:\workspace\Xpose_TestNG\reports\testng\parameters\main.html
[testng] Creating E:\workspace\Xpose_TestNG\reports\testng\parameters\groups.html
[testng] Creating E:\workspace\Xpose_TestNG\reports\testng\parameters\methods.html
[testng] Creating E:\workspace\Xpose_TestNG\reports\testng\parameters\classes.html
[testng] ===============================================
[testng] Parameters
[testng] Total tests run: 4, Failures: 1, Skips: 0
[testng] ===============================================
Ce test a permis de montrer comment utiliser les paramètres. C'est très utile car les tests sont plus dynamiques dès lors que l'on utilise des DataProvider et donc d'automatiser les tests. Cela permet aussi d'utiliser des paramètres de type complexe.
Il faut bien comprendre l'esprit du DataProvider : c'est une méthode particulière de test qui sera exécutée autant de fois
que de données fournies.
Il faut bien distinguer ce cas de celui de la Factory où c'est toute une classe qui est appelée autant de fois que de données fournies
Les sources de ce test
Les sources du test sont disponibles ici.