Et si on faisait de la BDD (Behavior Driven Development)

La BDD (Behavior Driven Development) est une pratique Agile créée par Dan North en 2003 qui a pour but de créer des tests fonctionnels avec un langage naturel compris de tous.

Cette pratique encourage le rapprochement des équipes techniques et des équipes fonctionnelles comme le fait les méthodes Agile dans leur ensemble.

Principes de la BDD

Voici les 3 principes principaux de la BDD qu’il faut retenir :

  1. La participation des équipes non techniques au projet
  2. Des scénarios automatisés pour décrire des comportements afin de faire de la non régression et pour commenter le code
  3. Mieux comprendre le comportement attendu pour les équipes techniques.

Mise en place complexe

Cette pratique est beaucoup moins fréquente dans les entreprises que celle des tests unitaires car elle implique beaucoup de changement au niveau des mentalités de l’entreprise.

Nous avons vu de nombreuses DSI tenter de mettre cette pratique en place dans le passé (surtout lors de la popularisation de l’XP) mais n’ont pas su capitaliser dessus ; un accompagnement est vivement conseillé pour la mise en place de pratique telle que celle-ci.

Des Product Owner pas toujours préparés

Souvent en Agile, nous demandons aux Product Owner d’écrire eux-même les tests d’acceptances (pour faire de la BDD) qui permettent souvent de renforcer la qualité fonctionnelle des livrables.

Bien que j’ai déjà vu que cela se faisait par les développeurs dans certaines entreprises, ça n’a pas beaucoup de sens d’imposer ce travail à ceux-ci car si ça va probablement améliorer un peu la qualité générale, je ne suis pas convaincu qu’ils écrivent tous ces tests avec beaucoup d’envie (et donc de rigueur).

j’ai d’ailleurs écrit un article sur un type de user-story qui impose d’écrire ce type de tests aux Product Owner : Un format de user-story très efficace : le story A4.

En tant que coach, nous voyons de plus en plus de Définition of Done inclure des tests d’acceptances sous forme de tests fonctionnels (Article si vous ne connaissez pas le Definition of Done : Faire la Definition of Done des user-story) ; les coach Agile y sont sûrement pour quelque chose car nous essayons d’amener les équipes à chercher constamment à améliorer la qualité des produits livrés.

Cependant cela fonctionne pour des Product Owner (PO) qui ont de l’expérience dans ce poste mais la tâche peut s’avérer plus compliquée pour les Product Owner qui découvrent le métier. Il est indispensable que les PO inexpérimentés soient accompagnés individuellement par un coach si on ne veut pas que l’écriture de ces tests deviennent un point de blocage.

Ecrire un premier test fonctionnel

Ecrire en Gherkin

Nous allons à présent voir comment écrire un test fonctionnel. Pour cela nous allons l’écrire en langage Gherkin qui est le langage naturel compris par l’ensemble des outils de tests fonctionnels.

Le langage Gherkin est un langage naturel lisible par toute personne qu’elle soit du côté business ou du côté technique. Ce langage va décrire des comportements sans détailler comment ceux-ci sont intégrés.

Le langage Gherkin est un langage qui suit une structure spécifique où chaque ligne et l’indentation sont importantes (comme le python ou le YAML pour les personnes techniques qui passent par ici).

Voici un exemple simple proposé par cucumber (un outil de tests fonctionnels très populaire) :

 1: Feature: Some terse yet descriptive text of what is desired
 2:   Textual description of the business value of this feature
 3:   Business rules that govern the scope of the feature
 4:   Any additional information that will make the feature easier to understand
 5: 
 6:   Scenario: Some determinable business situation
 7:     Given some precondition
 8:       And some other precondition
 9:     When some action by the actor
10:       And some other action
11:       And yet another action
12:     Then some testable outcome is achieved
13:       And something else we can check happens too
14: 
15:   Scenario: A different situation
16:       ...

Certains outils reconnaissent le français mais certaines équipes privilégient de tout écrire en anglais car ces contenus se retrouveront partiellement dans le code ; il est devenu très rare que le code soit encore écrit en français de nos jours.

Vous allez utiliser cette syntaxe pour décrire vos tests. Vous allez décrire la fonctionnalité dans son ensemble dans la partie feature puis vous allez définir différents scénarios possibles.

Il est toujours conseillé de proposer des scénarios qui valident une situation et des scénarios qui invalident également cette même situation. Comme ça en cas d’erreur d’inversement d’une condition dans le code, on le détectera tout de suite (l’erreur est humaine).

Faisons notre premier test en PHP

Afin de bien comprendre les principes de la BDD (Behavior Driven Development), nous allons installer un Symfony 3 qui est le framework PHP actuellement le plus populaire en France sur lequel nous allons appliquer nos premiers tests BDD. Voici le minimum requis pour installer le nécessaire sur un Linux Ubuntu 16.04 :

sudo apt-get update
sudo apt-get install -y mysql-server apache2 php7.0 libapache2-mod-php7.0 php7.0-mysql php7.0-cli php7.0-xml phpunit php7.0-curl composer php7.0-mbstring
sudo a2enmod rewrite
service apache restart

Ensuite nous devons installer notre Symfony 3 afin de pouvoir faire notre premier test unitaire :

sudo mkdir -p /usr/local/bin
sudo curl -LsS https://symfony.com/installer -o /usr/local/bin/symfony
sudo chmod a+x /usr/local/bin/symphony
sudo chmod -R 777 /var/www
sudo symfony new /var/www/mon_projet

Nous allons tenter de lancer le serveur web intégré de Symfony afin de vérifier que tout est bien installé :

cd /var/www/mon_projet
bin/console server:run

Nous allons installer Behat qui est un outil qui permet de faire des tests fonctionnels et de la BDD en PHP directement dans Symfony en complétant le fichier composer.json à la racine du projet :

"require-dev": {
    "behat/behat": "^3.1",
    "behat/mink": "^1.7",
    "behat/mink-browserkit- driver": "^1.3",
    "behat/mink-extension": "^2.2",
    "behat/symfony2-extension": "^2.1",
    "behatch/contexts": "^2.5",

Sachez que Behat est installable totalement indépendamment de Symfony car il peut être utilisé sur tous les projets PHP.

Nous allons à présent initialiser Behat qui va créer un dossier features avec un fichier features/bootstrap/FeatureContext.php :

sudo vendor/bin/behat -- init

Nous allons écrire notre premier test avec le langage Gherkin que nous avons vu tout à l’heure et qui est également bien reconnu par Behat. Voici un exemple de tests dans le fichier features/AppBundle/check.feature

Feature: test

Scenario: Test my homepage
    When I load "http://localhost/"
    Then I should see "Welcome to"

En lançant Behat avec la commande « sudo vendor/bin/behat », Behat nous fera un retour complet du type :

Feature: test

Scenario: Test my homepage                 # features/AppBundle/test.feature:2
    When I load "http://localhost/"
    Then I should see "Welcome to"

1 scénario (1 indéfinis)
2 étapes (2 indéfinis)
0m0.02s (7.08Mb)

>> default suite has undefined steps. Please choose the context to generate snippets:

[0] None
[1] FeatureContext
> 1

-- - FeatureContext a des étapes manquantes. Définissez-les avec les modèles suivants :

    /**
     * @When I load :arg1
     */

    public function iLoad($arg1)
    {
         throw new PendingException();
    }

   /**
    * @Then I should see :arg1
    */

    public function iShouldSee($arg1)
    {
        throw new PendingException();
    }

Behat nous indique que le développeur devra écrire un minimum de code pour pouvoir avoir notre test fonctionnel. Nous allons donc écrire le contenu de notre test fonctionnel pour qu’il soit testable concrètement en remplissant le fichier features/bootstrap/FeatureContext.php qui a été créé lors de l’initialisation de Behat :

<?php

use Behat\Behat\Context\Context;
use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;

/**
 * Defines application features from the specific context.
 */

class FeatureContext implements Context
{
    private $_contentPage;

    /**
     * Initializes context.
     *
     * Every scenario gets its own context instance.
     * You can also pass arbitrary arguments to the
     * context constructor through behat.yml.
     */

    public function __construct()
    {
    }

    /**
     * @When I load :arg1
     */

    public function iLoad($arg1)
    {
         $curl = curl_init($arg1);
         curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
         $this->_contentPage = curl_exec($curl);
    }

    /**
     * @Then I should see :arg1
     */
    public function iShouldSee($arg1)
    {
         if (!strstr($this->_contentPage, $arg1)) {
             sprintf("Could not see '%s'", $arg1);
             throw new PendingException();
        }
    }
}

En lançant Behat à nouveau, vous aurez une grosse erreur qui apparait car aucun « Welcome to » n’est retourné sur la page d’accueil.

Par défaut et sans avoir défini de VirtualHost, nous avons la page d’accueil d’Apache 2.

Si maintenant nous définissons notre VirtualHost pour qu’il pointe sur notre projet Symfony, vous verrez que le même test est valide (car la page contient le terme « Welcome to ») :

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot /var/www/mon_projet/web/

    <Directory /var/www/mon_projet>
        AllowOverride All
        Order Allow,Deny
        Allow from All
   </Directory>

</VirtualHost>

Ce test est très simple mais il vous permet de comprendre comment faire des tests fonctionnels. Si ici, nous avons fait cela sur Symfony, la démarche reste relativement proche dans d’autres langages de développement.

Vous trouverez par exemple Jbehave pour Java et Behave sous Python qui fonctionnent plus ou moins de la même façon que Behat.

Conclusion

Mettre en place de la BDD (Behavior Driven Development) n’est pas simple mais avec un bon accompagnement sur le sujet, vous saurez profiter de ces tests fonctionnels pour amener de la qualité à vos applications en leurs empêchant de faire de la non-regression.

Avec ce type de tests, vous diminuerez considérablement le taux de bug à l’avenir sur l’application concernée. Un gain de temps considérable qu’il ne faut pas négliger.

 

Laissez une réponse