PHP

Après la traduction du tutoriel Hamcrest pour Java, voir ici, voici maintenant son pendant pour PHP (avec des morceaux de PHPUnit dedans, d'ailleurs, Monsieur PHPUnit, Sebastian Bergmann, n'y est pas étranger).

Voir le site de Hamcrest et la documentation originale par Sebastian Bergmann.

Introduction

Hamcrest est un framework pour écrire des objets de correspondance (matchers) permettant d'écrire déclarativement des règles de correspondance. Il y a nombre de situations pour lesquels les matchers sont inestimables, comme pour la validation d'IHM ou le filtrage de données mais c'est dans le domaine de l'écriture des tests flexibles que les matchers sont le plus communément utilisés. Ce tutoriel va montrer comment utiliser Hamcrest pour les tests unitaires en PHP.

Quand on écrit des tests, il est parfois difficile de trouver le juste équilibre entre sur spécifier le test (et le rendre fragile face au changement) et ne pas le spécifier suffisamment (rendant le test moins de moindre valeur puisqu'il continuer à passer même quand la chose testée est cassée). Avoir un outil qui vous permet de cerner précisément l'aspect à tester et de décrire les valeurs qu'il doit avoir à un niveau de précision contrôlé aide grandement à écrire des tests qui sont "justes adaptés". De tels tests échouent quand le comportement de l'aspect qui est testé dévie du comportement attendu, mais continuent à réussir quand des modifications mineures et sans liens avec le comportement sont faites.

Mon premier test Hamcrest

Nous allons commencer par écrire un test PHPUnit très simple, mais au lieu d'utiliser des méthodes PHPUnit assertEquals ou assertThat, nous allons utiliser la fonction Hamcrest assertThat et son ensemble de matchers standards:

  <?php
  require_once 'PHPUnit/Framework.php';
  require_once 'Hamcrest.php';
   
  class BiscuitTest extends PHPUnit_Framework_TestCase
  {
      public function testEquals()
      {
          $theBiscuit = new Biscuit('Ginger');
          $myBiscuit = new Biscuit('Ginger');
          assertThat($theBiscuit, equalTo($myBiscuit));
      }
  }
  ?>

La méthode assertThat est une phrase stylisée pour faire une affirmation de test. Dans cet exemple, le sujet de l'affirmation est l'objet Biscuit qui est le premier paramètre de la méthode. Le second paramètre est le matcher pour les objets Biscuits, ici un matcher qui vérifie qu'un objet est égal à un autre.

Si vous avez plus d'une affirmation dans votre test, vous pouvez inclure un identifiant pour la valeur testée dans l'affirmation:

  assertThat('chocolate chips', $theBiscuit->getChocolateChipCount(), equalTo(10));
  assertThat('hazelnuts', $theBiscuit->getHazelnutCount(), equalTo(3));

Sucre

Hamcrest s'efforce de rendre vos tests aussi lisibles que possible. Par exemple, le matcher is est un enrobeur qui n'ajoute aucun comportement supplémentaire au matcher sous-jacent. Les affirmations suivantes sont toutes équivalentes:

  assertThat($theBiscuit, equalTo($myBiscuit));
  assertThat($theBiscuit, is(equalTo($myBiscuit)));
  assertThat($theBiscuit, is($myBiscuit));

Un aperçu des matchers courants

Hamcrest vient avec une bibliothèque de matchers utiles. Voici ceux qui sont déjà portés en PHP:

  • Noyau
    • anything - correspond toujours, utile si vous ne vous souciez pas le l'objet testé
    • describedAs - décorateur pour ajouter une description d'échec personnalisée
    • is - décorateur pour améliorer la lisibilité - voir "Sucre" ci-dessus
  • Logique
    • allOf - correspond si tous les matchers correspondent, fonctionne en court-circuit (comme le && PHP)
    • anyOf - correspond si l'un des matchers correspond, fonctionne en court-circuit (comme le || PHP)
    • not - correspond si le matcher enrobé ne correspond pas et vice versa
  • Objet
    • equalTo - test l'égalité d'objet en utilisant l'opérateur ==
    • anInstanceOf - teste le type
    • notNullValue, nullValue - teste pour la valeur null
    • sameInstance - teste l'identité des objets en utilisant l'opérateur ===
    • identicalTo - alias de sameInstance, mais avec une sémantique similaire à equalTo
  • Nombre
    • closeTo - teste si des valeurs en virgule flottante sont proches d'une valeur donnée
    • greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo - teste l'ordre
  • Collections
    • hasItem, hasItems - teste si un tableau contient un ou davantage d'éléments
  • Texte
    • equalToIgnoringCase - teste l'égalité de chaînes de caractères en ignorant la casse
    • equalToIgnoringWhiteSpace - teste l'égalité de chaînes de caractères en ignorant les différences d'espaces
    • containsString, endsWith, startsWith - teste la correspondance de chaînes de caractères
  • Combinaisons
    • both et either, par exemple:
  both(startsWith('a'))->andAlso(endsWith('b'))
  either(startsWith('x'))->orElse(endsWith('y'))