Le test en Ruby on Rails : forfait, hors forfait

Publié le 28 février 2010 par Pbernard

Ruby on Rails est un framework web fantastique. Il est puissant, on peut faire de l'Ajax très facilement... Et il a une qualité qu'un compulsif du développement piloté par les tests tel que moi ne peut qu'apprécier : le test fait partie intégrante du framework.

Forfait

Fort heureusement, RoR inclut l'essentiel :

  • Tests des modèles
  • Tests des contrôleurs et des vues
  • Test d'intégration

Mieux : en RoR, les tests sont aussi naturels que le code lui-même. Lorsqu'on crée un modèle ou un contrôleur, RoR crée non seulement ledit contrôleur, mais aussi le test qui va avec.

RoR inclut également un environnement de test, c'est à dire une configuration et une base de données dédiées au test. Cet environnement est distinct de celui dont on se sert pour faire des essais à la main, de sorte que les tests s'exécutent vraiment "dans leur coin" et sans interférence. La bascule d'un environnement se fait très simplement (pour ne pas dire automatiquement lorsqu'on lance les tests) et sans bidouillage : on ne passe pas son temps à trafiquer un obscur fichier de configuration pour pointer sur une base ou l'autre, ou toute autre manipulation douteuse de ce genre. RoR fait tout cela proprement.

L'environnement de test s'accompagne de fixtures, données qui servent à initialiser la base de test. Des utilisateurs, des commandes, des produits... tout ce qu'il faut pour que les tests puissent démarrer en ayant des données sous la main.

Hors forfait

RoR n'est pas parfait, il manque quelques éléments et certains domaines pourraient être complétés.

Tests des helpers

Les helpers hébergent le code spécifique aux vues qu'on pourrait être tenté d'insérer directement dans les template ERB. Bon choix de design, les helpers permettent de garder les vues aussi légères que possible.

Malheureusement, point de test de helper. Pourtant la génération du contrôleur serait le moment idéal pour créer le test du helper mais non, rien de tel.

C'est dommage, puisque cela oblige à vérifier le résultat des helpers directement dans les vues, dont le test est plus complexe et fragile. Rien d'insurmontable toutefois, il existe un plugin pour tester les helpers. Et RoR est pardonné pour cet écart.

Test des librairies

Les "librairies" sont le code qu'on place dans le répertoire lib de l'application, souvent parce qu'il n'a sa place dans aucun contrôleur ou modèle et qu'on veut le rendre accessible depuis toute l'application.

RoR n'inclut pas les tests des librairies. En réalité, pour créer un tel test, il suffit de le créer. Le test de lib/my_lib.rb devrait logiquement être test/lib/my_lib_test.rb. RoR aurrait pu faire un petit quelque chose pour lancer les tests sous test/lib avec rake test:libs, ainsi que lorsqu'on lance les tests avec rake test. Qu'à cela ne tienne, un simple ajout dans lib/tasks et le tour est joué.

Tests des migrations

Les migrations sont l'une des bonnes idées de RoR. A vrai dire cela a probablement existé avant RoR mais leur intégration au framework est réussie. Une migration est généralement en charge d'une modification "atomique" sur la base. Typiquement, la création d'une table. Ce peut être également l'ajout de colonnes à une table existante, l'ajout d'index dont on a réalisé l'importance après la mise en production... Ce type de modification ne nécessite pas de test en soit : il suffit d'écrire les tests classiques (unitaires, etc.) qui tourneront sur la base mise à jour.

Certaines migrations font en revanche plus que cela. Elles créent une table pour transformer une relation 1-n en relation n-n, elles modifient une colonne pour stocker non plus des euros mais des centimes d'euro, etc. Dans de tels cas, les migrations ne se contentent pas de nouvelles déclarations, elles itèrent sur les données existantes pour les mettre à jour. Le genre de chose qu'on voudrait tester avant de se lancer en production. RoR ne permet pas de tester les migrations. A ma connaissance, il n'existe pas d'extension pour tester spécifiquement les effets d'une migration.

Fixtures véloces

Les fixtures de RoR sont décrites en Yaml. C'est simple et efficace. Jusqu'à ce qu'elles prennent une certaine ampleur. A partir d'un certain point, les fixtures deviennent délicates à maintenir. Parfois, lorsqu'un test important exige un cas particulier, on se retrouve à modifier de nombreuses fixtures ainsi que certains des tests qui reposaient sur elles.

Des factories se proposent de remplacer les fixtures en Yaml. Celles-ci rendent les données de test plus dynamiques et proche du code. Reste à en faire bon usage, mais c'est un premier pas appréciable.

Un peu plus de vues ?

L'intégration d'un framework de test d'application web haut niveau, comme Selenium, serait un plus. Non pas que RoR ait oublié le test des vues, mais assert_select ne fait pas tout et ne remplace pas un rendu dans un véritable navigateur. Certes l'adhérence à un framework de test spécifique pourrait sembler un peu déplacé de la part de RoR. Mais ses concepteurs ont déjà franchi le pas, avec succès, dans d'autres domaines. Par exemple, RoR utilise Prototype et script.aculo.us, deux frameworks JavaScript qu'on est bien content de trouver déjà tout prêt et bien intégrés dans RoR.

Avertissement

J'ai tenté de dresser un tableau fidèle à la réalité, quoique probablement incomplet. Cependant, Ruby on Rails est un domaine qui évolue très vite et possède de nombreuses ramifications. Il est possible que certaines affirmations soient dépassées. N'hésitez pas à compléter ou rectifier !