Écrire des bons BDD

Je travaille sur différents projets dans lesquels les personnes utilisent des outils BDD (Business Driven Developement) comme cucumber ou JBehave.

C’est une très bonne idée cela permet, par exemple, d’avoir des spécifications par l’exemple. Néanmoins, ce n’est pas simple d’écrire du BDD !

LB_BDD_1

Dans cet article je vais tenter d’expliquer ce que doit être un bon BDD.

Mauvaises pratiques :

Commençons avec quelques mauvaises pratiques que j’ai trop souvent rencontrées.

Imaginons que nous devons tester un logiciel d’assurance.

Mauvaise pratique #1 : Faire le lien avec l’IHM (Interface Homme Machine)

Utiliser l’IHM pour écrire votre test est une mauvaise option. Malheureusement cette mauvaise pratique peut être encouragée par des composants comme « seleniumcucumber » (si vous l’utilisez sans redéfinir les étapes des tests).

Exemple :

BAD PRACTICE #1
Scenario: insured should be older than 18
        Given I navigate to "http://www.insuranceadress.com/insurance"
        And I enter "01/01/2001" into input field having id "birthdate"
        When I click on element having id "next"
        Then I should see a message "Insured should be older than 18"
        And I should see page title as "Please enter birth date of insured"

Cet exemple n’est pas à suivre pour plusieurs raisons:

  • L’IHM n’est pas assez stable (car elle évolue beaucoup) ce qui engendre beaucoup de maintenance sur un test de ce type.
  • Le test est souvent verbeux car vous souhaitez suivre l’IHM
  • Le test n’est pas candidat à du « Test first » car l’IHM est obligatoire pour pouvoir l’écrire (comment connaitre autrement les IDs des différents champs ?)
  • Le test ne montre pas l’impact business mais plus le comportement de l’IHM. Cela n’aide donc pas à comprendre le vrai comportement de l’application et donc d’avoir une documentation vivante.

Je ne dis pas que vous ne pouvez pas faire du test IHM en BDD, seulement que la fonctionnalité ne devrait pas être liée à la logique de l’IHM.

Mauvaise pratique #2 : trop verbeux

Une autre mauvaise habitude est l’utilisation du business model et de définir tous les attributs de tous les objets à manipuler dans les tests. La raison derrière cela est que les attributs sont obligatoires et doivent être définis.

Voici un autre exemple :

BAD PRACTICE #2
Scenario: Woman should have a 10% discount
        Given a person:
        | FirstName | June       |
        | Name      | Doe        |
        | BirthDate | 20/01/1985 |
        | BirthPlace| LA         |
        | Sex       | Female     |
        And a car:
        | Brand     | VW         |
        | Name      | Beetle     |
        | Year      | 2000       |
        | Engine    | 1100cc     |
        | Place     | 4          |
        | Color     | red        |
        And a insurance type:
        | Comprehensive    | No      |
        | Collision        | Yes     |
        | Usage            | Pleasure|
        | Accident         | No      |
        When insurer wants to compute the insurance prize
        Then it should be 315$

Une bonne règle est de définir uniquement les données qui sont importantes pour le test (c’est le même principe que la simplification des tables de décisions). Si les données sont obligatoires mais n’influent pas sur le test il faut laisser la liberté de décider la valeur à utiliser à la personne qui automatise le test. Cela sera alors dans le code de définition des étapes et sera plus facile à maintenir et réutiliser.

De plus, en lisant le cas en exemple, à part avec le titre, vous ne savez pas ce que fait le test ni quelles sont les données importantes.

A la fin, même la personne qui lit le test ne connait plus le but de ce test.

Mauvaise pratique #3 : tester des fonctionnalités triviales

Il arrive que des personnes test des créations triviales ce qui donne des tests triviaux comme celui-ci :

BAD PRACTICE #3
Scenario: Add an insured
        When insurer creates a person:
        | FirstName | June       |
        | Name      | Doe        |
        | BirthDate | 20/01/1985 |
        | BirthPlace| LA         |
        | Sex       | Female     |
        Then the list of persons should be:
        | FirstName | Name | BirthDate  | BirthPlace | Sex     |
        | June      | Doe  | 20/01/1985 | LA         | Female  |

Ce type de test doit être fait avec les tests unitaires. De plus il n’y a pas de règle métier qui s’applique à ce test. Oui, vous devez tester la création quand des règles métiers s’y appliquent (comme les opérations, les cas d’erreurs, les liens vers d’autres objets…), mais tester une création triviale ne vaut vraiment pas le coût (et crée de la redondance)

Mauvaise pratique #4 : Dépendance entre les tests

Une autre mauvaise pratique que j’ai rencontrée avec le BDD est d’avoir des « tests liés » dans lesquels on utilise les données des tests précédents pour les tests d’après. Cela veut dire que le BDD n’est pas indépendant et très compliqué à lire.

BAD PRACTICE #4
Scenario: premium increase when recording an second accident in a year
        Given the scenario "record a first accident" was passed
        When insured records a new accident on his car 
        Then premium increase of 10% should be applied on my contract

Le principal problème est de ne pas connaitre les prérequis si vous n’avez pas lu le scenario précédent… et ceux d’avants si le scénario précédent est également lié à un autre scénario antérieur.

Une bonne règle pour les tests (BDD ou non) est d’avoir des tests indépendants. Un test BDD a besoin d’une description claire dans sa partie « Given ».

Il est également très compliqué de faire du retest quand on doit ré-exécuter tous les tests précédents.

Mauvaise pratique #5 : Objectifs multiples

Une bonne pratique bien connue du test est d’avoir uniquement 1 objectif par test. Cela est le cas quel que soit le niveau de tests.

Vous ne devez donc pas écrire des tests BDD avec plusieurs objectifs.

Exemple :

BAD PRACTICE #5
Scenario: premium increase when recording an second accident in a year
        Given an insurance contract
        When insured records a new accident on his car 
        Then premium should be the same than before
        When insured records a new accident on his car 
        Then premium increase of 10% should be applied on my contract

Il ne devrait y avoir qu’un seul « then » à la fin (un « And » est également possible), sinon vous retombez dans les travers précédents (ou des objectifs multiples) et il devient compliqué de comprendre quand et pourquoi un test est en échec

Mauvaise pratique #6 : Pas d’exemple

Quelque fois, le BDD n’est plus un exemple mais uniquement une règle. C’est clairement une mauvaise pratique car cela n’aide pas le développeur à comprendre.

BAD PRACTICE #5
Scenario: review accidents
        Given a list of accidents
        When insurer wants to review the list of accidents 
        Then only accidents in status "to review" should be displayed

Vos tests doivent être un vrai exemple avec des valeurs (même si vous devez définir une valeur minimale quand dans l’exemple Mauvaise pratique #2, cela doit rester un exemple). Dans ce BDD le test est en succès même avec une liste d’accident vide et tend donc à ne rien montrer.

Bonnes pratiques :

La première chose à faire est d’éviter les mauvaises pratiques. Cela donnera à votre test de bonnes chances d’être fiable et compréhensible.

Utilisez le passé avec « Given », le présent avec « When » et le futur (should) avec Then.

C’est une très bonne habitude d’utiliser cette petite règle. Cela permet de reconnaitre le type d’étape d’un seul coup d’œil et évite les confusions.

Les actions sont clairement différentes selon ce qui est écrit :

  • Given a contract was created (setup)
  • When a contract is created (trigger)
  • Then a contract should be created (assertion)

Utilisez la 3ème personne

Il y a débat entre utiliser 1ère et la 3ème personne. Quel est le meilleur point de vue ? Il n’y a pas de bonne réponse mais j’ai la conviction que les étapes de tests devraient être à la 3ème personne.

Commencez avec un état « vide »

Avant le « Given » d’un scénario, nous devons considérer qu’il n’y a aucune donnée présente. Par contre, « aucune donnée » dépend du système, toutes les données de référence doivent évidemment être présentes.

Si, pour une fonctionnalité spécifique vos tests ont besoin de la même donnée, utilisez simplement le « Backgroud keyword » (dans cucumber). Il vous permet de mettre un contexte à tous vos tests (le « Given » dans le BackGround est exécuté pour tous les tests).

Cela veut également dire que vous devez « nettoyer » vos données persistantes afin d’assurer que chaque test débute dans un état « vide ».

Soyez cours et lisible

Finalement, un grand avantage du BDD est de fournir une documentation vivante. Vous pouvez utiliser vos tests comme une documentation. L’automatisation rend « vivant » vos tests et permet donc d’avoir une documentation à jour.

Mais si vous voulez bénéficier de cet avantage, votre BDD doit être lisible et compréhensible par tout membre du projet. Evitez donc les tests technique (pensez DDD : Data Driven Development) et validez vos fichiers avec le métier est un très bon moyen d’atteindre cet objectif.

Article de Laurent Bouhier, publié initialement sur ce blog et traduit de l’anglais par Marc Hage Chahine

Publié par

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion /  Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s