Les méthodologies de développement type 'tests first' sont en plein essor : TDD, ATDD, BDD... À travers ce meetup, je vous propose de mettre en pratique un exemple de Behavior Driven Development avec Cucumber Java. Cette démonstration nous permettra de constater que de bonnes pratiques de développement permettent d'améliorer la qualité des livrables avec un effort modéré.
4. QU’APPORTE-T-ELLE ?
➡ Une meilleure compréhension du besoin
4
BESOIN
CRITÈRES
D’ACCEPTATION
TESTS
D’ACCEPTATION
DÉVELOPPEMENT
Equipe métier
Equipe projet
5. QU’APPORTE-T-ELLE ?
➡ Un complément au Test Driven Development (TDD)
5
TEST QUI RÉUSSIT
TEST
QUI ÉCHOUE
Refactoring
TDD Test
d’Acceptation
7. CAS PRATIQUE
En tant que cuisinier, je souhaite noter
une liste de recette
La liste des recettes disponibles est
représentée sur une page
Lorsque je sélectionne une recette, je
peux lui attribuer une note comprise entre
0 et 10
9. He should be able to select oneAnd
LE GHERKIN
8
Given
When
Then
Scenario:List all existing recipes
"shoun" is authenticated
He requests a list of all recipes
He should have a list of recipes
And There is an existing list of recipes
Feature: List recipes
10. public class RecipeStepdefs {
@Given("^"([^"]*)" is authenticated$")
public void userIsAuthenticated(String user) throws Throwable {
// Your test goes here
}
CUCUMBER-JVM
9
public class RecipeStepdefs {
@Given("^"([^"]*)" is authenticated$")
public void userIsAuthenticated(String user) throws Throwable {
// Your test goes here
}
@When("^He requests a list of all recipes$")
public void heRequestsAListOfAllRecipes() throws Throwable {
// Your test goes here
}
@Then("^He should have a list of recipes$")
public void heShouldHaveAListOfRecipes() throws Throwable {
// Your test goes here
}
}
11. public class RecipeStepdefs {
@Given("^"([^"]*)" is authenticated$")
public void userIsAuthenticated(String user) throws Throwable {
// Your test goes here
}
CUCUMBER-JVM
9
Expression
régulièrepublic class RecipeStepdefs {
@Given("^"([^"]*)" is authenticated$")
public void userIsAuthenticated(String user) throws Throwable {
// Your test goes here
}
@When("^He requests a list of all recipes$")
public void heRequestsAListOfAllRecipes() throws Throwable {
// Your test goes here
}
@Then("^He should have a list of recipes$")
public void heShouldHaveAListOfRecipes() throws Throwable {
// Your test goes here
}
}
12. public class RecipeStepdefs {
@Given("^"([^"]*)" is authenticated$")
public void userIsAuthenticated(String user) throws Throwable {
// Your test goes here
}
CUCUMBER-JVM
9
Expression
régulière
Given "shoun" is authenticated
public class RecipeStepdefs {
@Given("^"([^"]*)" is authenticated$")
public void userIsAuthenticated(String user) throws Throwable {
// Your test goes here
}
@When("^He requests a list of all recipes$")
public void heRequestsAListOfAllRecipes() throws Throwable {
// Your test goes here
}
@Then("^He should have a list of recipes$")
public void heShouldHaveAListOfRecipes() throws Throwable {
// Your test goes here
}
}
13. CUCUMBER-JVM - JAVA 8
10
public class RecipeJava8Stepdefs implements En {
public RecipeJava8Stepdefs() {
Given("^"([^"]*)" is authenticated$", () -> {
// Your test goes here
});
When("^He requests a list of all recipes$", () -> {
// Your test goes here
});
Then("^He should have of list of recipes$", () -> {
// Your test goes here
});
}
}
15. # language: fr
12
# language: fr
Fonctionnalité: noter une recette
En tant que cuisinier
Je souhaite noter mes recettes
Afin de les évaluer
Scénario: Je peux noter la recette "Salade de concombre"
Etant donné que "Shoun" est authentifié
Et que les recettes suivantes existent:
| Name | Description |
| Salade de concombre | Salade à base de concombre |
| Salade de crudité | Mélange de salade, tomate et crevettes |
Lorsqu' il attribue la note de 8 la recette "Salade de concombre"
Alors la recette "Salade de concombre" devrait avoir la note de 8
16. IMPLÉMENTATION
13
@Etantdonné("^que "([^"]*)" est authentifié$")
public void queEstAuthentifié() throws Throwable {
// TODO
}
@Et("^que les recettes suivantes existent:$")
public void queLesRecettesSuivantesExistent(List<Recipe> recipes) throws Throwable {
// TODO
}
@Lorsqu("^il attribue la note de (d+) la recette "([^"]*)"$")
public void ilAttribueLaNoteDeLaRecette(int mark, String recipe) throws Throwable {
// TODO
}
@Alors("^la recette "([^"]*)" devrait avoir la note de (d+)$")
public void laRecetteDevraitAvoirLaNote(String recipe, int mark) throws Throwable {
// TODO
}
19. Projet existant
Java & AngularJS
4 Développeurs
1 Business Analyst
1 Scrum Master
24 Sprints
40% de couverture de tests
Client insatisfait
Produit jamais utilisé en production
17 025 lignes de code, 285 classes,
1196 fonctions
Contexte
16
20. Contexte
Équipe hétérogène
17
Je connais le
produit…
J’ai
lu des trucs
sur le BDD
C’est vrai?
Moi pas du tout..
J’ai un peu
d’expérience en
BDD
Mais qu’est-ce
que c’est que cette
@&%#$ ??!
… et je suis
un super Scrum
Master
22. Meilleure compréhension du besoin
Moins de retours client
Meilleure couverture des tests
Meilleure implication de l’équipe de développement
Moins de bugs
Meilleure productivité
Bénéfices attendus
19
23. Bénéfices attendus
19
Meilleure compréhension du besoin
Moins de retours client
Meilleure couverture des tests
Meilleure implication de l’équipe de développement
Moins de bugs
Meilleure productivité
27. Meilleure mais…
Écriture des Gherkin
Sous-évaluation des tâches
Refactoring coûteux sur les anciennes fonctionnalités
Coupler BDD et TDD
Réticence à l’écriture de scénarios
Et la productivité dans tout ça ?
23
28. Retour d’expérience
Tous les membres de l’équipe doivent
s’impliquer
Le Product Owner / Business Analyst doit
être rigoureux
Le temps passé sur les scénarios est utile
mais coûteux
Si les besoins évoluent le risque de
régression est maîtrisé
Une nette amélioration qualitative a été
remarquée
32. Retrouvez-moi
à Culture Kanban le 29 juin
à Agile Laval le 30 juin
sur le blog Viseo http://blog.viseo-bt.com/
author/s-ichida/
sur Twitter @ishoun