Contactez-nous

Concept : la structure d'un test RSpec (describe/it/expect)

Maîtrisez la grammaire de RSpec, le framework de test Ruby. Ce guide décompose la structure fondamentale describe/it/expect pour vous aider à écrire des tests clairs, lisibles et expressifs.

Une grammaire conçue pour la lisibilité

RSpec se distingue des autres frameworks de test par sa syntaxe. Elle est conçue pour être lue presque comme de l'anglais. Il ne s'agit pas simplement de code, mais d'un langage spécifique (DSL) pour décrire le comportement d'un logiciel. Cette approche, inspirée du Behavior-Driven Development (BDD), vise à rendre les tests compréhensibles par tous, y compris les non-développeurs.

La structure d'un test RSpec repose sur trois mots-clés fondamentaux qui s'emboîtent comme les poupées russes : `describe`, `it`, et `expect`. Pensez à cette structure comme à la rédaction d'une spécification :

  • `describe` : Annonce le sujet que nous allons décrire (ex: "Concernant la classe Calculatrice...").
  • `it` : Décrit un comportement spécifique que ce sujet devrait avoir (ex: "...elle devrait additionner correctement deux nombres.").
  • `expect` : Vérifie que le résultat de ce comportement est bien celui attendu (ex: "...je m'attends à ce que le résultat soit 5.").

Ensemble, ils créent un test qui non seulement vérifie la logique, mais la documente aussi de manière très claire.

Le bloc `describe` : Définir le sujet du test

Le bloc `describe` est le conteneur de plus haut niveau. Son rôle est de regrouper un ensemble de tests logiquement liés. L'argument que vous lui passez est généralement la classe ou le module que vous testez.

# On décrit le comportement de la classe Calculator
describe Calculator do
  # ... tous les tests pour Calculator viendront ici
end

Une bonne pratique consiste à imbriquer les blocs `describe` pour créer une hiérarchie claire. Par exemple, pour tester une méthode spécifique, on peut ajouter un `describe` imbriqué. Par convention, on préfixe le nom d'une méthode d'instance par un `#` et celui d'une méthode de classe par un `.`.

describe Calculator do
  describe '#add' do
    # ... tous les tests spécifiques à la méthode 'add' viendront ici
  end
end

Cette structure est très utile car, en cas d'échec, RSpec affichera le chemin complet ("Calculator #add ..."), vous permettant de localiser l'erreur instantanément.

Le bloc `it` : Spécifier un comportement unique

A l'intérieur d'un bloc `describe`, le bloc `it` (ou son synonyme `example`) définit un scénario de test unique et isolé. Chaque bloc `it` doit tester une seule chose. La description textuelle qui suit `it` doit être une phrase qui a du sens lorsqu'elle est lue à la suite de la description du bloc parent.

Par exemple, si le parent est `describe '#add'`, une bonne description pour `it` serait `'returns the sum of two positive numbers'`. L'ensemble se lit de manière fluide : "Calculator #add returns the sum of two positive numbers."

describe '#add' do
  it 'returns the sum of two positive numbers' do
    # Le code de test...
  end

  it 'returns the sum of a positive and a negative number' do
    # Un autre scénario de test...
  end
end

Chaque bloc `it` est indépendant. Un échec dans le premier test n'empêchera pas le second de s'exécuter. C'est fondamental pour obtenir un rapport de test complet.

La méthode `expect` : Affirmer le résultat attendu

C'est au sein d'un bloc `it` que la magie opère. La méthode `expect` est le coeur de la vérification. C'est elle qui compare le résultat obtenu par votre code (la valeur actuelle) avec le résultat que vous attendiez (la valeur attendue).

Sa syntaxe est très expressive : `expect(valeur_actuelle).to matcher(valeur_attendue)`.

  • `expect(...)` : Prend en argument le résultat produit par votre code.
  • `.to` ou `.not_to` : Indique si vous vous attendez à ce que la condition soit vraie ou fausse.
  • `matcher(...)` : C'est la condition de comparaison. Le plus courant est `eq(...)`, qui vérifie l'égalité de valeur (équivalent à `==`).

it 'returns the sum of two positive numbers' do
  calculator = Calculator.new
  result = calculator.add(2, 3)
  expect(result).to eq(5) # On s'attend à ce que le résultat soit égal à 5.
end

Une erreur fréquente est de confondre `eq` et `equal`. `eq` vérifie que les valeurs sont les mêmes (ex: `2` et `2.0`), tandis que `equal` vérifie que c'est le même objet en mémoire. Dans 99% des cas, vous utiliserez `eq`. RSpec propose des dizaines d'autres matchers très utiles comme `be_nil`, `be_truthy`, `include(...)` ou `raise_error(...)` pour couvrir tous les cas de figure.