Aller au contenu

BDD — Behavior-Driven Development

Spécifications executables, langage Gherkin et living documentation — rendre les tests lisibles par tous.


Le principe

BDD est ne d'un constat : les tests unitaires du TDD sont écrits par des développeurs, pour des développeurs. Le Product Owner, le QA et les utilisateurs ne les lisent pas.

BDD propose d'écrire les tests dans un langage naturel structure que tout le monde comprend — puis de les rendre executables.

graph LR
    A["User Story"] --> B["Scenarios Gherkin<br/>(PO + Dev + QA)"]
    B --> C["Steps implementation<br/>(Dev)"]
    C --> D["Execution automatisee"]
    D --> E["Living Documentation"]

Le langage Gherkin

Gherkin est un format structure en langage naturel. Chaque scenario suit le pattern Given/When/Then :

Feature: Connexion utilisateur
  En tant qu'utilisateur enregistre
  Je veux me connecter a mon compte
  Afin d'acceder a mes donnees personnelles

  Scenario: Connexion reussie avec des identifiants valides
    Given un utilisateur "alice" avec le mot de passe "P@ssw0rd!"
    And le compte est actif
    When l'utilisateur se connecte avec "alice" et "P@ssw0rd!"
    Then la connexion est reussie
    And l'utilisateur est redirige vers le tableau de bord

  Scenario: Connexion echouee avec un mot de passe incorrect
    Given un utilisateur "alice" avec le mot de passe "P@ssw0rd!"
    When l'utilisateur se connecte avec "alice" et "mauvais_mdp"
    Then la connexion echoue
    And le message "Identifiants invalides" est affiche

Mots-clés Gherkin

Mot-clé Rôle
Feature Titre de la fonctionnalité
Scenario Un cas de test spécifique
Given Le contexte initial (preconditions)
When L'action qui déclenche le comportement
Then Le résultat attendu
And / But Continuation du mot-clé précédent
Scenario Outline Scenario parametre avec des exemples
Examples Tableau de données pour un Scenario Outline

Scenario Outline — tests parametres

  Scenario Outline: Validation du format email
    When l'utilisateur saisit l'email "<email>"
    Then la validation retourne <resultat>

    Examples:
      | email              | resultat |
      | user@example.com   | valide   |
      | user@              | invalide |
      | @example.com       | invalide |
      | user.example.com   | invalide |

La conversation structurée

BDD n'est pas juste un format de test — c'est un processus de découverte. Avant d'écrire les scenarios, l'équipe se reunit pour un "Three Amigos" :

graph TD
    PO["Product Owner<br/>Definit le besoin"] --- SC["Scenarios<br/>Gherkin"]
    DEV["Developpeur<br/>Identifie les cas limites"] --- SC
    QA["QA<br/>Challenge les hypotheses"] --- SC

Le processus

  1. Le PO présente la user story
  2. Le développeur pose des questions techniques ("que se passe-t-il si le serveur est down ?")
  3. Le QA cherche les cas limites ("et si l'email contient des caractères unicode ?")
  4. Ensemble, ils redigent les scenarios Gherkin
  5. Le développeur implémenté les steps
  6. La CI exécuté les scenarios à chaque push

L'atelier est la vraie valeur

Le format Gherkin est secondaire. La vraie valeur du BDD est la conversation qui force PO, dev et QA a s'aligner sur le comportement attendu avant le développement.


Implémentation des steps

Les scenarios Gherkin sont liés à du code via des step définitions :

Python (Behave)

# features/steps/login_steps.py
from behave import given, when, then

@given('un utilisateur "{username}" avec le mot de passe "{password}"')
def step_create_user(context, username, password):
    context.user = create_user(username, password)

@when('l\'utilisateur se connecte avec "{username}" et "{password}"')
def step_login(context, username, password):
    context.response = login(username, password)

@then('la connexion est reussie')
def step_login_success(context):
    assert context.response.status == "success"

JavaScript (Cucumber.js)

// features/step_definitions/login_steps.js
const { Given, When, Then } = require('@cucumber/cucumber');

Given('un utilisateur {string} avec le mot de passe {string}', function (username, password) {
  this.user = createUser(username, password);
});

When('l\'utilisateur se connecte avec {string} et {string}', function (username, password) {
  this.response = login(username, password);
});

Then('la connexion est reussie', function () {
  assert.strictEqual(this.response.status, 'success');
});

Living Documentation

Les scenarios BDD forment une documentation vivante : si un scenario passe, la fonctionnalité fonctionne comme décrit. Si un scenario échoué, la documentation est obsolète.

Documentation classique Living Documentation (BDD)
Devient obsolète en quelques mois Toujours à jour (exécutée par la CI)
Redige une fois, jamais mis à jour Mis à jour à chaque changement de comportement
Disconnect entre doc et code La doc est le test

Générer un rapport

La plupart des frameworks BDD génèrent des rapports HTML à partir des scenarios :

# Behave (Python)
behave --format html --outfile report.html

# Cucumber.js
npx cucumber-js --format html:report.html

BDD vs TDD

Critère TDD BDD
Audience Développeurs PO, Dev, QA — toute l'équipe
Langage Code Gherkin (langage naturel)
Granularité Unitaire Fonctionnel (user story)
Objectif Design du code Alignement sur le comportement
Complementaire Oui — BDD au niveau feature, TDD au niveau unitaire Oui

BDD ne remplacé pas TDD

BDD décrit le quoi (le comportement attendu). TDD guide le comment (la conception du code). Ils se combinent naturellement : BDD pour les scenarios d'acceptation, TDD pour l'implémentation des composants internes.


Outils

Outil Langage Lien
Cucumber Multi (JVM, JS, Ruby) cucumber.io
Behave Python behave.readthedocs.io
pytest-bdd Python github.com/pytest-dev/pytest-bdd
SpecFlow .NET specflow.org
Karate JVM github.com/karatelabs/karate