Trucs et astuces Rspec

Tester une application est indispensable mais les tests sont souvent lents, ce qui fait perdre le fil et rend la correction des bugs plus longue et complexe. Voici quelques astuces pour ne faire tourner que les tests utiles et arrêter de perdre du temps à regarder des lignes de points verts défiler à l’écran…

Tags : Rspec Ruby Rails Tests DX

Publié le 13 mars 2024

Installer Rspec

Pour ajouter Rspec à une application Rails, il suffit de lancer les commandes suivantes :

bundle add rspec-rails --group=test,development
bundle exec rails generate rspec:install

Lancer uniquement un ou plusieurs tests

Après avoir tourné, Rspec affiche un rapport listant une ligne par erreur, avec pour chaque test qui n’est pas passé le chemin du fichier et le numéro de ligne (ou de groupe pour les tests générés et les exemples partagés). Exemple :

Finished in 3.47 seconds (files took 4.35 seconds to load)
16 examples, 2 failures

Failed examples:

rspec ./spec/models/location_spec.rb:7 # [Message du test]
rspec ./spec/requests/some_controller_spec.rb[1:1:1:1] # [Message du test]

Conseil de pro: Triple-cliquer une ligne après “Failed examples”, puis la copier-coller pour lancer uniquement ce test.

Pour lancer plusieurs tests du même fichier, il suffit de les lister après le nom de fichier, séparées par deux-points. Exemple :

rspec spec/models/user_spec.rb:5:10:15 # Lancer les tests des lignes 5, 10 et 15

Il est aussi possible d’indiquer un numéro de ligne correspondant à un bloc context ou describe, Rspec fera tourner tous les tests inclus dans ces blocs. Si la ou les lignes ne correspondent ni à un bloc it, context ou describe, Rspec remontera ligne par ligne jusqu’à en trouver un. C’est pratique, mais attention car des changements dans le fichier peuvent faire exécuter des tests différents.

Si on lui passe un nom de dossier (ou plusieurs), Rspec exécutera tous les fichiers de test (se terminant par _spec.rb) contenus dans ces dossiers. Exemple :

rspec spec/models/ spec/mailers # Lance tous les tests de modèles et de mailers

On peut aussi utiliser * pour lancer les fichiers correspondant à un motif. Exemple :

rspec spec/models/user* # Lancera user_spec.rb, par exemple, et tout autre fichier de type "user*_spec.rb"

Les étiquettes

Pour ajouter des étiquettes à un test, la syntaxe est simple :

it "does something", :fancy do # Ça fonctionne aussi avec context et describe

Voici la syntaxe pour lancer les tests correspondant :

rspec --tag fancy # Lancer tous les tests :fancy
rspec --tag fancy spec/models # Lancer tous les tests de modèle ayant l'étiquette :fancy
rspec --tag ~fancy spec/models # Lancer tous les tests de modèle SAUF ceux qui ont l'étiquette :fancy

S’arrêter à la première erreur avec --fail-fast

Si on passe l’option --fail-fast, Rspec s’arrête à la première erreur rencontrée. C’est pratique quand on débugge, en particulier si une même erreur affecte plusieurs tests, par exemple une factory qui ne permet plus d’instancier un modèle valide.

En s’arrêtant à la première erreur, on peut corriger le problème sans devoir attendre que la suite entière finisse de tourner.

Relancer uniquement les tests échoués avec --only-failures

Rspec est capable de ne relancer que les tests qui ont échoué la dernière fois qu’ils ont tourné. Pour ça, il lui faut permettre à Rspec d’enregistrer le résultat de chaque test, ce qui se configure dans spec/spec_helper.rb en décommentant la ligne :

config.example_status_persistence_file_path = "spec/examples.txt"

Ce fichier ne doit pas être traqué par Git :

echo 'spec/examples.txt' >> .gitignore

À noter : les options --only-failures et --fail-fast peuvent être combinées pour accélérer le débogage.

Aller plus loin

  • Lisez le manuel ! rspec --help liste toutes les options disponibles
  • Ajouter des raccourcis dans le terminal pour lancer rspec --only-failures et rspec --fail-fast, pour éviter des coquilles et de la fatigue digitale.
  • Utiliser aggregate failures pour ne pas répéter les temps de mise en place complexes
  • Générer toute sorte de valeurs facilement: Faker
  • Remplacer les fixtures par des factories: FactoryBot ou Fabrication
  • Réinitialiser la base de données entre les tests: DatabaseCleaner
  • Analyser les performances de la suite de test : TestProfGitlab a réduit le temps de CI de 40% après avoir corrigé des problèmes mis à jour par cet outil !

Avez-vous d’autres astuces à ajouter à celles-ci ?