Problématique

Ecrire et jouer rapidement des tests fonctionnels d’un site sous drupal

Solution : Behat avec l’extension pour Drupal. https://drupal.org/project/drupalextension

Installation de l’extensions pour durpal

L’installation est très simple en utilisant composer, il suffit d’écrire le fichier composer.json suivant dans un répertoire de travail

{
    "require": {
        "drupal/drupal-extension": "*"
    },
    "config": {
        "bin-dir": "bin/"
    }
}

et voilà, il ne reste qu’à lancer la commande :

composer install

Cela aura pour effet d’installer l’extension drupal et les dépendances (behat inclus)

Initialisation et configuration

La première chose à faire est l’initialisation de l’environnement de travail de behat. La commande suivante permet génère l’arborescence minimal et les fichiers nécessaires à behat

./bin/behat --init

l’étape suivante est la configuration de behat avec le fichier behat.yml.

default:
    filters:
        tags: "@drush"
    paths:
        features: 'features'
    extensions:
        Behat\MinkExtension\Extension:
            goutte: ~
            selenium2: ~
            base_url: http://localhost:8888
        Drupal\DrupalExtension\Extension:
            blackbox: ~
            drush:
               #alias: /home/cbrun/Apps/drush/drush/drush
                root: /data/services/web/demo/cms/drupal/quick-drupal-20140214100728/drupal
            region_map:
                left sidebar: "#sidebar-first"

Avec :

  • filters : permet de filtrer les tests ayant pour tags “@drush”
  • base_url : url du site à tester
  • drush : paramétrage à la commande drush
    • root : répertoire du site drupal à tester
  • region_map : permet de définir le mapping entre les régions et les identifiants css

Enfin, avant d’écrire des scénario, il reste à modifier le fichier bootstrap. Il faut éditer le fichier feature/bootstrap/FeatureContext.php, pour qu’il ressemble à ça

<?php
/**
 * @file
 * boostrap
 */
use Behat\Behat\Context\ClosuredContextInterface,
    Behat\Behat\Context\TranslatedContextInterface,
    Behat\Behat\Context\BehatContext,
    Behat\Behat\Context\Step\Then,
    Behat\Behat\Context\Step\Given,
    Behat\Behat\Context\Step\When,
    Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode,
    Behat\Gherkin\Node\TableNode;
use Behat\MinkExtension\Context\MinkContext;
use Drupal\DrupalExtension\Context\DrupalContext;

//
// Require 3rd-party libraries here:
//
require_once 'PHPUnit/Autoload.php';
require_once 'PHPUnit/Framework/Assert/Functions.php';

/**
 * Features context.
 */
class FeatureContext extends DrupalContext {
  /**
   * Initializes context.  * Every scenario gets its own context object.
   *
   * @param array $parameters 
   *   context parameters (set them up through behat.yml)
   */
  public function __construct(array $parameters) {
    // Initialize your context here.
  }
  /**
   * @Given /^wait (\d+)$/
   */
  public function wait($arg1) {
      $this->getSession()->wait($arg1);
  }
}

Et voilà, on est prêt à écrire des tests pour drupal. Le contexte Drupal qui est utilisé dans notre fichier bootstrap va nous permettre d’écrire dans nos scénarios des commandes drupal, drush pour tester nos sites

Pour avoir la liste des commandes utilisables pour écrire nos scénarios, il suffit de demander à behat ce qu’il peut interpréter

./bin/behat -dl

Scénarios

Test de l’authentification d’un utilisateur

Premier fichier de tests à écrire dans feature/login.feature

# behat features/login.feature
Feature: Login
  Les tests de login
    @drush
    Scenario: Login with drush
        Given I am logged in as a user with the "authenticated user" role
        When I click "My account"
        Then I should see the heading "History"

Ce test va créer un utilisateur, l’authentifier. Ensuite il y aura clic sur la page “Mon compte”. Le test sera valide si la page contient la chaîne “History”.

Pour lancer le tests, il suffit de lancer la commande :

./bin/behat

Il faut bien sûr avoir un Selenium qui fonctionne pour exécuter les tests

Tests de la présence d’un block dans une région

Le tests ci-dessous permet de valider que le block login est présent dans la colonne de gauche. Il est valide sur une installation vierge avec le thème standard

# behat features/block.feature
Feature: Block
  Les tests des blocks
    @drush
    Scenario: Find a heading in a region
        Given I am not logged in
        When I am on the homepage
        Then I should see the heading "User login" in the "left sidebar" region

Création d’un contenu par un administrateur

Le scénario ci-dessous va créer et authentifier un utilisateur ayant le rôle administrateur. Puis, il y aura création d’un contenu de type article. Le test sera valide si drupal retourne le message que le contenu est bien créé

Feature: Article
    Tests on articles
    @drush @javascript
    Scenario: Admin can create a article
        Given I am logged in as a user with the "administrator" role
        When I am on "/node/add/article"
        And I fill in the following:
           | Title     | Test article                  |
           | Body      | This is the body of article   |
       And faire un screenshot
        And I press "Save"
        And faire un screenshot
        Then faire un screenshot
        And I break
        And I should see the text "Article"
        And I should see the text "Test article"
        And I should see the text "has been created."

Astuces

Faire une pause dans un scénario

Le code ci-dessous ajouter au fichier feature/bootstrap/FeatureContext.php permet d’ajouter la commande wait XXXX qui permet de faire une pause de XXXX ms.

/**
* @Given /^wait (\d+)$/
*/
public function wait($arg1) {
$this->getSession()->wait($arg1);
}

Ajouter un break

l’extensions drupal permet dans les scénarios de stopper le scénarios jusqu’à ce que l’utilisateur appuie sur la touche Enter. Pratique pour le débugging des scénarios

Ajouter une commande de copies d’écran

Là, aussi, il faut modifier le fichier feature/bootstrap/FeatureContext.php. Un exemple ci-dessous de ce fichier avec la fonction

class FeatureContext extends MinkContext
{
  private $stepnum;
  /**
  * Initializes context.
  * Every scenario gets it’s own context object.
  *
  * @param array $parameters context parameters (set them up through behat.yml)
  */
  public function __construct(array $parameters)
  {
    // Initialize your context here
    $this->stepnum=0;
  }
  /**
  * @Given /^je fais une copie écran$/
  */
  public function jeFaisUneCopieEcran()
  {
    $this->stepnum=$this->stepnum+1;
    $file=fopen(’screen_’.$this->stepnum.’.png’,’w’);
    $screen=$this->getSession()->getDriver()->getScreenshot();
    fwrite($file,$screen);
    fclose($file);
  }
}

Et voilà, nous pouvons utiliser la commande suivante dans nos scénarios

Je fais une copie écran

Conclusion

Avec cette extensions et behat, il devient de plus en plus facile et rapide d’écrire des scénarios de tests.