Aujourd’hui nous allons parler du Behavior-Driven Development, plus particulièrement son utilisation dans RubyOnRails grâce à la gem cucumber.

C’est quoi le BDD?

le Behavior-Driven Development est une méthode agile qui met l’accent sur le travail en collaboration entre des personnes techniques (comme des ingénieurs) avec des personnes non techniques.

La particularité de cette méthode de travail est qu’elle est très "verbeuse": On décrit une fonctionnalité (feature) en langage naturel, puis on écrit des scénarios d’acceptation (toujours en langage naturel) pour illustrer celle-ci. Chaque scénario est composé de plusieurs étapes (steps) qui commencent toutes par un mot-clé significatif: Given, When, et Then qui peuvent être liés par le mot-clé And.

Et donc, que fait cucumber dans l’histoire?

Cucumber est une gem qui permet de rédiger et d’exécuter ce type de test d’acceptation de manière automatique.

Logo-cucumber

Nous décrivons notre fonctionnalité dans un fichier .feature, puis nous implémentons chaque steps dans un fichier à part.

Tout d’abord, installons cucumber et capybara via notre gemfile:

group :development, :test do  gem 'cucumber-rails', '~> 1.4.1', :require => false  gem 'database_cleaner', '~> 1.2.0'  gem 'capybara', '~> 2.2.1'end

Noter que j’utilise cucumber dans un projet rails, je peux donc directement utiliser la gem cucumber-rails. On nous renseigne sur le dépôt github qu’il est fortement recommandé d’installer la gem database_cleaner.

Installer les nouvelles gems via la commande suivante:

bundle install

Ensuite, vous pouvez exécuter la commande suivante :

rails g cucumber:install

Cette commande installeras les fichiers et dossiers nécessaire au fonctionnement de cucumber.

En exécutant la commande cucumber vous pourrez lancer les tests d’acceptation que vous aurez préalablement rédigé.

Notre première feature

Pour illustrer le fonctionnement de cucumber je vais utiliser l’exemple d’un formulaire d’authentification. Nous partons du postulat que nous avons un formulaire d'authentification fonctionnel et que celui à besoin d'être testé et de figurer dans notre répertoire de tests d'acceptations.

Authentication.featureFeature: AuthenticationIn order to be authenticated on the websiteA visitorShould use an authentication form@authentication_formScenario: Authentication via sign in formGiven I'm a guest on the sign in pageAnd I fill in "user_email" with "mymail@mail.com"And I fill in "user_password" with "mysecretpassword"When I press "Sign in"Then I should be authenticate@authentication_formScenario: Authentication attempt via sign in form (password error)Given I'm a guest on the sign in pageAnd I fill in "user_email" with "mymail@mail.com"And I fill in "user_password" with "anotherpassword"When I press "Sign in"Then I shouldn't be authenticated

Comme vous pouvez le voir, on ne croirait pas voir des tests mais bien l'extrait d’un cahier des charges! (En anglais ;) )

Voici le fichier contenant les steps associées a cette feature:

authentication_steps.rbGiven(/^I'm a guest on the sign in page\$/) dovisit new_user_session_pathendGiven(/^I fill in "(._?)" with "(._?)"\$/) do |field, value|fill_in field, with: valueendGiven(/^I should be redirect on the Sign up page\$/) doexpect(page).to have_content 'Inscription'endWhen(/^I press "(.\*?)"\$/) do |button|click_button buttonendThen(/^I should be authenticate\$/) doexpect(page).to have_content 'You are now authenticate'endThen(/^I shouldn't be authenticated\$/) doexpect(page).to have_content 'Authentication error'end

On peut observer qu’une step n’est composée ici que d’une action élémentaire. Ce n'est pas une règle mais plutôt une bonne pratique. Nous utilisons ici la gem capybara pour simuler des événements navigateur comme un clique sur un bouton ou encore le remplissage d'un champs de formulaire.

En lançant la commande suivante:

cucumber

Nous devrions voir le résultat de nos tests.

2 scenarios (0 failed, 2 passed)10 steps (0 failed, 0 skipped, 10 passed)

Pour aller plus loin: les tags et hooks

Un peu à la manière de rspec, il est parfois nécessaire d’effectuer des actions précise avant l’execution de nos tests pour les faire fonctionner.

Typiquement, dans le cadre d’une authentification, nous avons besoin d’un utilisateur dans la base de données qui possède l’email et le mot de passe correspondant a notre scénario.

C’est ainsi qu’interviennent les tags et les hooks. Ce sont des manières d’indiquer a cucumber qu’il faut effectuer certaines actions avant (ou après) l’exécution d’un scénario.

Il suffit de placer un @ suivi du nom d’identifier de votre choix. Ici j’ai choisi @authenticationform. Vous pourrez voir où ce place les _tags en regardant l'extrait de code du fichier Authentication.feature.

Le code de notre hook se placera dans le dossier support, contenu dans le dossier features, à la racine de notre application.

authentication_hooks.rbBefore('@authentication_form') doFactoryGirl.create(:user, email: "mymail@mail.com", password: "mysecretpassword")end

Ici rien de particulier, cela ressembles fortement a la directive before, utilisable avec rspec. Sachez tout de même qu’il existe d’autres types de block, comme After.