Text Size
Mercredi 3 septembre 2014
                        
J'ai intégré il y a quelques semaines easyb/Selenium dans un projet Java/Apache Maven pour réaliser des tests d'acceptation. Ayant rencontré quelques écueils, je vous fais profiter des solutions que j'ai pu trouver :)

Qu'est-ce qu'Easyb ?

Easyb est un framework de BDD : Behavior Driven Development. Pour décrire ça simplement, imaginez faire du Test Driven Development en vous focalisant sur la vérification des comportements attendus de votre logiciel, en décrivant les cas de test dans un langage naturel, compréhensible par tous (et notamment les non-développeurs).
Easyb peut donc servir à faire du test unitaire, mais il est également tout indiqué pour les tests d'acceptation (vérification que les exigences représentées par les spécifications du logiciel sont respectées), par exemple dans le cadre de votre sprint Agile, pour vérifier que la user story est finie.
Easyb permet d'écrire des tests facilement et rapidement, grâce à son langage dédié (DSL : Domain-Specific Language) qui autorise des constructions comme shouldBeEqual, shouldBeAn, ensureThrows, isAString, contains, etc. Mais pour moi, ce qui vous fera peut-être l'adopter dans le cadre des tests d'acceptation, c'est sa capacité à être compréhensible pour les développeurs comme pour les chefs de produit ; les stories sont rédigées avec la construction "given... when... then...", les rapports générés sont donc compréhensibles par tous, et le test est de lui-même entièrement documenté. Easyb vous incite à décrire ce que fait votre test précisément.

Intégration

Vous trouverez un exemple d'intégration easyb / java / maven / selenium ici : https://github.com/Nephtys/easyb-sample

Première étape, intégrer easyb via Maven

Il suffit pour cela d'ajouter le plugin maven-easyb-plugin :


<plugin>
 <groupId>org.easyb</groupId> 
 <artifactId>maven-easyb-plugin</artifactId> 
 <version>1.3</version> 
 <executions> 
 <execution> 
 <goals> 
 <goal>test</goal> 
 </goals> 
 </execution> 
 </executions> 
</plugin>

Ensuite, on peut générer les rapports en lançant :


mvn test

pour lancer tous les tests y compris ceux easyb


mvn easyb:test

pour lancer uniquement les tests easyb
On peut également générer un rapport HTML ou XML (par défaut, c'est un rapport TXT), ne lancer que les tests marqués avec un tag spécifique : http://www.easyb.org/maven-easyb-plugin/usage.html

Seconde étape, lancer chaque fichier de test indépendamment dans Eclipse

Il suffit pour cela d'installer le plugin easyb pour Eclipse.
Attention ! Si vous n'avez pas le plugin Groovy installé, installez le plugin Groovy d'abord ! Lors de l'installation du plugin easyb, vous n'êtes pas prévenu... cela m'a valu un Eclipse qui se lance et s'auto-kill en boucle :)
Le plugin easyb s'installe via le site de mise à jour :
Le plugin Groovy s'installe avec le site :
Sélectionner les items :
  • Groovy-Eclipse (Required)
  • m2e Configurator for Groovy-Eclipse (Optional)

Troisième étape, lancer les tests easyb via JUnit

Pour cela :
Récupérer le jar à cet endroit
Si vous voulez pouvoir l'utiliser avec Maven, installez-le dans votre repo local (ou distant si vous en avez la possibilité)


mvn  install:install-file -Dfile=easyb-junit-0.5.3.jar -DgroupId=org.easyb  -DartifactId=easyb-junit -Dversion=0.5.3 -DgeneratePom=true  -Dpackaging=jar

A cause d'incompatibilités de versions, si vous lancez les tests JUnit avec Maven, vous devrez changer la version du plugin easyb pour la version 0.9.7-1.
Puis vous pourrez ajouter la dépendance au fichier pom.xml :



<dependency>
<groupId>org.easyb</groupId>
<artifactId>easyb-junit</artifactId>
<version>0.5.3</version>
<scope>test</scope>
</dependency>

Ce jar ne contient pas les dépendances (donc il n'est pas vraiment adapté), si vous ne souhaitez pas le regénérer, ajoutez la dépendance à easyb en plus dans votre pom.xml :



<dependency>
<groupId>org.easyb</groupId>
<artifactId>easyb</artifactId>
<version>0.9.7</version>
<scope>test</scope>
</dependency>

La classe Launcher suivante vous permettra de lancer les tests easyb dans la vue JUnit :


package fr.duprey.easyb;

import java.io.File;

import org.easyb.junit.EasybSuite;

/**
 * Lauches all easyb stories and specifications with JUnit
 */
public class EasybTestSuiteLauncher extends EasybSuite {

 @Override
 protected File baseDir() {
 return new File("src/test/easyb");
 }

 @Override
 protected String description() {
 return "Easyb Test Suite";
 }

}

Le résultat se présentera ainsi :
Easyb avec JUnit

Quatrième étape, utiliser Selenium dans les tests easyb

Pour cela, ajoutez la dépendance suivante :



<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
<version>2.5.0</version>
<scope>test</scope>
</dependency>

Puis, j'ai choisi de créer une story qui proposera le comportement "start selenium" et "stop selenium" aux autres stories, pour factoriser le code :


package fr.duprey.easyb.sample.utils

import org.openqa.selenium.server.SeleniumServer
import com.thoughtworks.selenium.DefaultSelenium

shared_behavior "start selenium", {
 given "selenium is up and running", {
 server = new SeleniumServer();
 server.start();
 selenium = new DefaultSelenium("localhost",
 4444, "*firefox", "http://you.base.url")
 selenium.start()
 }
}

shared_behavior "stop selenium" , {
 then "selenium should be stopped", {
 selenium.stop()
 server.stop()
 }
}

Ainsi, une story utilisant selenium sera codée de cette façon :


package fr.duprey.easyb.sample;

shared_stories "./utils/WithSeleniumBehavior.story"

before "start selenium", {
it_behaves_as "start selenium"
}
after "stop selenium", {
it_behaves_as "stop selenium"
}

scenario "an invalid password has been entered", {

 when "filling out the connexion form with somebody's credentials", {
 selenium.open("/connexion/?lang=fr")
 selenium.type("email", "youremail")
 selenium.type("password", "42")
 }

 and "the submit link has been clicked", {
selenium.click("connexion")
selenium.waitForPageToLoad("2000")
}

 then "the page should display an error message on the password field", {
 passwordFieldErrorSelector = "//form/div/div[text()='Mot de passe']/../div[@class='champs erreur']/span"
 selenium.getText(passwordFieldErrorSelector).shouldBeEqualTo "Mot de passe incorrect"
 }
}

ce qui va donner à l'exécution :


given selenium is up and running
when filling out the connexion form with somebody's credentials
and the submit link has been clicked
then the page should display an error message on the password field
then selenium should be stopped

Attention

  • Pour que le plugin Eclipse, le plugin Maven, ou le plugin JUnit acceptent de lancer vos tests, vous devez suivre une règle simple : l'extension de vos fichiers doit être .story ou .specification (et pas .groovy, bien qu'ils contiennent du Groovy. Le plugin Eclipse reconnaitra les fichiers et utilisera la coloration syntaxique Groovy).
  • Vous ne pouvez pas utiliser toutes ces méthodes en même temps :
    • le plugin JUnit ne supporte pas les versions d'easyb 0.9.8 et supérieures (il existe un patch http://code.google.com/p/easyb-junit/issues/detail?id=7 pour le support de la 0.9.8)
    • les tags ont été introduits dans easyb 0.9.8, donc le flag
      -Deasyb.tags='runme,metoo'
      du plugin Maven ne fonctionnera pas avec les versions antérieures
    • le plugin Maven (tout du moins les versions 0.9.7-1 et 1.3 que j'ai testées) a des problèmes d'encodage, les tests Selenium qui vérifient par exemple des phrases contenant des accents échouent avec le plugin Maven (expected "Connectez-vous à" but was "Connectez-vous �") mais passent avec le plugin Eclipse.
    • le plugin Maven 0.9.7-1 a des problèmes dans la génération du rapport HTML : il n'est généré qu'une fois sur trois en moyenne. J'ai l'impression que c'est mieux avec la version 1.3, et c'est peut-être dû ici aussi à des problèmes d'encodage.
  • si vous choisissez la génération de rapport HTML avec le plugin Maven, précisez le nom du rapport sinon vous obtiendrez l'extension .txt (étrange !).
Pour résumer les combos possibles :
  • maven-easyb-plugin 0.9.7-1 + easyb 0.9.7 + easyb-junit 0.5.3
    • + maven
    • + junit
    • - tags
    • - rapports HTML
  • maven-easyb-plugin 1.3 (pas besoin de dépendance easyb)
    • + maven
    • - junit
    • + tags
    • + rapports HTML

Conclusion sur les possibilités d'intégration

JUnit apporte clairement l'avantage de la visualisation rapide des étapes de la story qui échouent (vert/rouge). Mais il requiert du travail supplémentaire (l'écriture du Launcher) et ne permet pas d'utiliser les dernières versions du plugin Maven et d'easyb (donc on ne profite pas des corrections et des nouvelles fonctionnalités bien utiles comme les tags).
Avec le plugin easyb pour Eclipse, on peut lancer les stories une par une dans Eclipse et voir le résultat dans la console ; même si c'est un résultat "texte" (de plus, il est assez "pollué" si on utilise Selenium) et donc moins lisible que le vert/rouge de JUnit, je trouve cette méthode suffisante et donc je la préfère à l'utilisation d'anciennes versions d'easyb.

A propos des tests d'acceptation

Les tests d'acceptation permettent une meilleure communication entre développeurs, entre les développeurs et les chefs de produit, ils permettent d'automatiser la vérification que le comportement attendu est bien reproduit, (et par la suite, lors des sprints suivants, qu'il n'y a pas de régressions dues aux nouvelles implémentations, à condition de maintenir les tests), ils sont un très bon moyen de vérifier que toute l'équipe partage la même vision de ce qui est attendu du logiciel/de la user story, ou encore de "ce qui est fini" (Done) ; ils permettent de documenter le code : on peut les considérer comme des spécifications exécutables. Mais il faut garder à l'esprit qu'ils ne permettent pas de vérifier l'absence de bug ni la qualité du logiciel si on se contente de tester les cas attendus.
Une discussion intéressante sur ce dernier point : http://www.satisfice.com/blog/archives/638

Lectures

Autres articles intéressants sur l'ATDD et easyb :

By A Web Design

Logiciels libres - Général

Agenda du libre

Le mois dernier Septembre 2014 Le mois prochain
L Ma Me J V S D
week 36 1 2 3 4 5 6 7
week 37 8 9 10 11 12 13 14
week 38 15 16 17 18 19 20 21
week 39 22 23 24 25 26 27 28
week 40 29 30
                        

Contact

Laissez moi un message

Profil Viadeo