Accélération des tests RSpec dans une grande application Rails

J’ai une application Rails avec plus de 2000 exemples dans mes tests RSpec. Inutile de dire que c’est une grande application et qu’il y a beaucoup à tester. L’exécution de ces tests à ce stade est très inefficace et, comme cela prend trop de temps, nous sums presque sur le point d’être découragés de les écrire avant de lancer une nouvelle version. J’ai ajouté –profile à mes spec.opts pour trouver les exemples les plus anciens et au moins 10 d’entre eux durent en moyenne 10 secondes. Est-ce normal parmi vous les experts de RSpec? Est-ce que 10 secondes sont trop longues pour un exemple? Je me rends compte qu’avec 2 000 exemples, il faudra beaucoup de temps pour tout tester à fond – mais à ce stade, 4 heures sont un peu ridicules.

Quel genre de temps voyez-vous pour vos exemples les plus anciens? Que puis-je faire pour dépanner mes spécifications existantes afin de déterminer les goulots d’étranglement et d’accélérer les choses? Chaque minute aiderait vraiment à ce stade.

    10 secondes, c’est très long pour qu’un seul test soit exécuté. Mon instinct est que votre cible de spécification exécute des tests d’unité et d’intégration en même temps. C’est une chose typique que les projets entrent et à un certain stade, vous devrez surmonter cette dette technique si vous voulez produire plus, plus rapidement. Il existe un certain nombre de stratégies qui peuvent vous aider à faire cela … et je vous en recommanderai quelques-unes que j’ai utilisées par le passé.

    1. Séparer l’unité des tests d’intégration

    La première chose à faire est de séparer les tests unitaires des tests d’intégration. Vous pouvez le faire soit par:

    1. Les déplacer (dans des dossiers séparés sous le répertoire spec) – et modifier les cibles de rake
    2. Les marquer (rspec vous permet de marquer vos tests)

    La philosophie est que vous voulez que vos builds réguliers soient rapides, sinon les gens ne seront pas trop heureux de les exécuter souvent. Retournez donc sur ce territoire. Faites en sorte que vos tests réguliers s’exécutent rapidement et utilisez un serveur d’continuous integration pour exécuter la version la plus complète.

    Un test d’intégration est un test qui implique des dépendances externes (par exemple, firebase database, WebService, queue, et certains diront que FileSystem). Un test unitaire ne fait que tester l’élément de code spécifique que vous souhaitez vérifier. Il devrait fonctionner rapidement (9 000 en 45 secondes est possible), c’est-à-dire que la plus grande partie devrait fonctionner en mémoire.

    2. Convertir les tests d’intégration en tests unitaires

    Si le gros de vos tests unitaires est plus petit que votre suite de tests d’intégration, vous avez un problème. Cela signifie que les incohérences commenceront à apparaître plus facilement. Donc, à partir de là, commencez à créer plus de tests unitaires pour remplacer les tests d’intégration. Les choses que vous pouvez faire pour aider dans ce processus sont les suivantes:

    1. Utilisez un cadre moqueur au lieu de la ressource réelle. Rspec a un cadre de construction intégré.
    2. Exécutez rcov sur votre suite de tests unitaire. Utilisez-le pour évaluer la qualité de votre suite de tests unitaires.

    Une fois que vous avez un ou plusieurs tests unitaires appropriés pour remplacer un test d’intégration, supprimez le test d’intégration. Les tests en double ne font qu’aggraver la maintenance.

    3. N’utilisez pas de luminaires

    Les appareils sont mauvais. Utilisez plutôt une fabrique (machinist ou factory_girl). Ces systèmes peuvent générer des graphiques de données plus adaptables, et plus important encore, ils peuvent créer des objects en mémoire que vous pouvez utiliser, plutôt que de charger des objects à partir d’une source de données externe.

    4. Ajouter des contrôles pour arrêter les tests unitaires devenant des tests d’intégration

    Maintenant que vous avez des tests plus rapides en place, il est temps de vérifier si cela ne se reproduit plus.

    Il existe des bibliothèques dont le patch active l’enregistrement de singe pour lancer une erreur lors de la tentative d’access à la firebase database (UnitRecord).

    Vous pouvez également essayer l’appairage et le TDD, ce qui peut aider votre équipe à écrire des tests plus rapidement car:

    1. Quelqu’un vérifie – alors personne ne devient paresseux
    2. Un TDD correct nécessite un retour rapide. Les tests lents ne font que rendre la situation difficile.

    5. Utiliser d’autres bibliothèques pour surmonter le problème

    Quelqu’un a mentionné spork (accélère les temps de chargement de la suite de tests sous rails3), hydra / parallel_tests – pour exécuter des tests unitaires en parallèle (sur plusieurs cœurs).

    Cela devrait probablement être utilisé LAST. Votre véritable problème est tout à fait aux étapes 1, 2 et 3. Résolvez cela et vous serez mieux à même de mettre en place une infrastructure supplémentaire.

    Pour un excellent livre de recettes sur l’amélioration des performances de votre suite de tests, consultez la présentation Grease Your Suite .

    Il documente une accélération de 45x dans l’exécution de la suite de tests en utilisant des techniques telles que:

    • fast_context
    • quickerclip
    • hydre
    • réglages effrayants du système de fichiers
    • tcmalloc
    • Tuning Ruby Enterprise Edition GC

    Vous pouvez utiliser Spork. Il prend en charge 2.3.x,

    https://github.com/sporkrb/spork

    ou ./script/spec_server qui peut fonctionner pour 2.x

    Vous pouvez également modifier la configuration de la firebase database (ce qui accélère essentiellement les requêtes de firebase database, etc.), ce qui augmentera également les performances des tests.

    10 secondes par exemple semble être une très longue période. Je n’ai jamais vu de spécification nécessitant plus d’une seconde, et la plupart en prennent beaucoup moins. Testez-vous les connexions réseau? Base de données écrit? Le système de fichiers écrit?

    Utilisez autant que possible des simulations et des stubs – ils sont beaucoup plus rapides que l’écriture de code dans la firebase database. Malheureusement, il faut plus de temps pour se moquer et écrabouiller (et c’est plus difficile à faire correctement). Vous devez équilibrer le temps passé à écrire des tests et le temps passé à exécuter des tests.

    J’appuie ensuite le commentaire d’ Andrew Grimm sur la recherche d’un système de CI qui pourrait vous permettre de paralléliser votre suite de tests. Pour quelque chose de cette taille, cela pourrait être la seule solution viable.

    Plusieurs personnes ont mentionné Hydra ci-dessus. Nous l’avons utilisé avec beaucoup de succès par le passé. J’ai récemment documenté le processus de mise en service d’hydra: http://logicalfriday.com/2011/05/18/faster-rails-tests-with-hydra/

    Je suis d’accord avec le sentiment que ce type de technique ne devrait pas être utilisé comme substitut à la rédaction de tests bien structurés et rapides par défaut.

    Si vous utilisez des modèles ActiveRecord, vous devez également prendre en compte le coût du chiffrement BCrypt.

    Vous pouvez en savoir plus à ce sujet sur cet article de blog: http://blog.syncopelabs.co.uk/2012/12/speed-up-rspec-test.html

    Commander cette présentation: http://grease-your-suite.heroku.com/#1

    Vous pouvez essayer http://github.com/ngauthier/hydra

    fast_require gem pourrait vous aider. En outre, votre seul moyen est de (comme vous l’avez fait) profiler et optimiser, ou d’utiliser spork ou quelque chose qui exécute vos spécifications en parallèle pour vous. http://ruby-toolbox.com/categories/dissortingbuted_testing.html

    Il y a une vidéo très générale sur l’amélioration de vos vitesses de test. Pourrait aider.

    Vous pouvez suivre quelques conseils simples pour commencer par rechercher où la plupart du temps est passé si vous ne les avez pas déjà essayés. Regardez l’article ci-dessous:

    https://blog.mavenhive.in/7-tips-to-speed-up-your-webdriver-tests-4f4d043ad581

    Je suppose que la plupart d’entre elles sont des étapes génériques qui s’appliqueraient quel que soit l’outil utilisé pour les tests.

    Supprimez la suite de tests existante. Sera incroyablement efficace.