Dans notre projet, nous avons atteint le point où nous avons presque mille tests et les gens ont cessé de les exécuter avant de procéder à un contrôle, car cela prend tellement de temps. Au mieux, ils exécutent les tests correspondant au code qu'ils ont modifié et au pire, ils l'enregistrent sans test.
Je pense que ce problème est dû au fait que la solution a été étendue à 120 projets (nous réalisons généralement des projets beaucoup plus petits et ce n'est que la deuxième fois que nous effectuons correctement le TDD) et que le temps de test de build + a pris environ deux à trois minutes. sur les petites machines.
Comment pouvons-nous réduire le temps d'exécution des tests? Y a-t-il des techniques? Feindre plus? Simuler moins? Peut-être que les tests d'intégration plus importants ne devraient pas s'exécuter automatiquement lors de l'exécution de tous les tests?
Edit: en réponse à plusieurs réponses, nous utilisons déjà CI et un serveur de compilation, c’est ainsi que je sais que les tests échouent. Le problème (en fait, un symptôme) est que nous continuons à recevoir des messages sur les builds ayant échoué. Exécuter des tests partiels est quelque chose que la plupart des gens font mais pas tous. et en ce qui concerne les tests, ils sont en fait plutôt bien faits, ils utilisent des faux pour tout et il n’ya pas d’IO du tout.
la source
Réponses:
Une solution possible consisterait à déplacer la partie de test des machines de développement vers une configuration d'intégration continue ( Jenkins par exemple) à l'aide d'un logiciel de contrôle de version d'une certaine version ( git , svn , etc.).
Lorsqu'un nouveau code doit être écrit, le développeur en question crée une branche pour ce qu'il fait dans le référentiel. Tout le travail sera effectué dans cette branche et ils pourront valider leurs modifications à tout moment sans modifier la ligne de code principale.
Lorsque la fonctionnalité donnée, la correction de bogue ou tout autre travail sur lequel ils travaillent est terminé, cette branche peut être fusionnée dans le coffre (ou selon votre préférence) où tous les tests unitaires sont exécutés. Si un test échoue, la fusion est rejetée et le développeur en est informé afin qu'il puisse corriger les erreurs.
Vous pouvez également demander à votre serveur CI d'exécuter les tests unitaires sur chaque branche de fonctionnalité au fur et à mesure que les validations sont effectuées. De cette façon, le développeur peut apporter des modifications, valider le code et laisser le serveur exécuter les tests en arrière-plan pendant qu'il continue à travailler sur des modifications supplémentaires ou d'autres projets.
Vous trouverez ici un excellent guide sur une manière de réaliser une telle configuration (spécifique à git mais qui devrait fonctionner pour d'autres systèmes de contrôle de version): http://nvie.com/posts/a-successful-git-branching-model/
la source
La majorité des tests unitaires devrait prendre moins de 10 millisecondes chacun environ. Avoir "presque mille tests" n'est rien et devrait prendre peut - être quelques secondes à courir.
Si ce n'est pas le cas, arrêtez d'écrire des tests d' intégration fortement couplés (sauf si c'est ce dont le code a besoin) et commencez à écrire de bons tests unitaires (en commençant par du code bien découplé et l'utilisation appropriée de faux / mock / stubs / etc.). Ce couplage aura également une incidence sur la qualité des tests et sur le temps nécessaire pour les écrire. Il ne s'agit donc pas simplement de réduire la durée d'exécution des tests.
la source
py.test
) fait des tonnes de magie en arrière-plan, et tout est en pur code Python ("100x plus lent que C "), exécuter environ 500 tests dans un projet mien prend moins de 6 secondes sur un netbook lent, vieux de plusieurs années. Ce chiffre est à peu près linéaire dans le nombre de tests; Bien qu'il y ait des frais généraux de démarrage, ils sont amortis sur tous les tests, et les frais généraux par test sont O (1).J'ai utilisé plusieurs approches pour résoudre un problème similaire:
De plus, vous pouvez utiliser les outils suivants pour vous simplifier la vie et accélérer les tests.
pnunit
et configuration de CI avec plusieurs nœuds.la source
0. Écoutez vos programmeurs.
S'ils n'exécutent pas les tests, cela signifie qu'ils perçoivent que le coût (attendre l'exécution des tests, gérer les faux échecs) est supérieur à la valeur (détecter immédiatement les bugs). Diminuez les coûts, augmentez la valeur et les utilisateurs exécuteront les tests tout le temps.
1. Rendez vos tests 100% fiables.
Si vous avez des tests qui échouent avec de faux négatifs, résolvez-le immédiatement. Corrigez-les, changez-les, éliminez-les, de manière à garantir une fiabilité à 100%. (Il est correct d'avoir un ensemble de tests peu fiables, mais utiles, que vous pouvez exécuter séparément, mais le corps principal des tests doit être fiable.)
2. Modifiez vos systèmes pour garantir que tous les tests passent avec succès.
Utilisez des systèmes d'intégration continue pour vous assurer que seuls les commits passants sont fusionnés dans la branche principale / officielle / version / quelle que soit.
3. Changez votre culture pour valoriser à 100% les tests.
Apprenez à la leçon qu'une tâche n'est pas "terminée" jusqu'à ce que 100% des tests soient réussis et qu'elle ait été fusionnée dans la branche principale / officielle / de la version / quelle que soit leur origine.
4. Faites les tests rapidement.
J'ai travaillé sur des projets où les tests prennent une seconde, et sur des projets où ils durent toute la journée. Il existe une forte corrélation entre le temps nécessaire pour exécuter des tests et ma productivité.
Plus les tests sont longs, moins vous les exécutez souvent. Cela signifie que vous irez plus longtemps sans recevoir de commentaires sur les modifications que vous apportez. Cela signifie également que vous passerez plus de temps entre les commits. S'engager plus souvent signifie de plus petites étapes qui sont plus faciles à fusionner; engager l'histoire est plus facile à suivre; trouver un bug dans l'historique est plus facile; Il est également plus facile de revenir en arrière.
Imaginez des tests qui fonctionnent si vite que cela ne vous dérange pas de les exécuter automatiquement chaque fois que vous compilez.
Faire des tests rapidement peut être difficile (c'est ce que le PO a demandé, non!). Le découplage est la clé. Les imitations / faux sont acceptables, mais je pense que vous pouvez faire mieux en procédant à une refactorisation afin de les rendre superflus. Voir le blog d'Arlo Belshee, commençant par http://arlobelshee.com/post/the-no-mocks-book .
5. Faites des tests utiles.
Si les tests n'échouent pas lorsque vous vous trompez, alors à quoi ça sert? Apprenez-vous à écrire des tests qui détecteront les bugs que vous êtes susceptible de créer. Ceci est une compétence en soi, et prendra beaucoup d'attention.
la source
Quelques minutes suffisent pour les tests unitaires. Cependant, gardez à l'esprit qu'il existe 3 principaux types de tests:
Ceux-ci sont énumérés par ordre de vitesse. Les tests unitaires devraient être rapides. Ils ne verront pas tous les bogues, mais ils établiront que le programme est décemment sain d’esprit. Les tests unitaires doivent être exécutés avec un matériel minimum de 3 minutes ou moins. Vous dites que vous n'avez que 1000 tests unitaires, et qu'ils prennent 2-3 minutes? Eh bien, c'est probablement OK.
Choses à vérifier:
Assurez-vous cependant que vos tests unitaires et vos tests d'intégration sont séparés. Les tests d'intégration seront toujours plus lents.
Assurez-vous que vos tests unitaires fonctionnent en parallèle. Il n'y a aucune raison pour qu'ils ne le fassent pas si ce sont de vrais tests unitaires
Assurez-vous que vos tests unitaires sont "sans dépendance". Ils ne devraient jamais accéder à une base de données ou au système de fichiers
En dehors de cela, vos tests ne sonnent pas trop mal pour le moment. Cependant, à titre de référence, l'un de mes amis faisant partie de l'équipe Microsoft a 4 000 tests unitaires qui s'exécutent en moins de 2 minutes sur du matériel correct (et c'est un projet compliqué). Il est possible d'avoir des tests unitaires rapides. Éliminer les dépendances (et ne simuler que ce qui est nécessaire) est l’essentiel pour obtenir de la vitesse.
la source
Formez vos développeurs sur les processus logiciels personnels (PSP) pour les aider à comprendre et à améliorer leurs performances en faisant preuve de plus de discipline. L'écriture de code n'a rien à voir avec claquer vos doigts sur un clavier, puis appuyez sur un bouton de compilation et d'enregistrement.
La PSP était très populaire dans le passé, quand compiler du code était un processus qui prenait beaucoup de temps (heures / jours sur un mainframe, donc tout le monde devait partager le compilateur). Mais lorsque les postes de travail personnels sont devenus plus puissants, nous avons tous accepté le processus:
Si vous pensez avant de taper, puis après avoir tapé, révisez ce que vous avez écrit, vous pouvez réduire le nombre d'erreurs avant d'exécuter une suite de génération et de test. Apprenez à ne pas appuyer sur Build 50 fois par jour, mais peut-être une ou deux fois. Il est donc moins important que votre temps de construction et de test prenne quelques minutes de plus.
la source
Une façon possible: divisez votre solution. Si une solution a 100 projets, alors c'est tout à fait ingérable. Le fait que deux projets (par exemple A et B) utilisent un code commun provenant d'un autre projet (par exemple Lib) ne signifie pas qu'ils doivent être dans la même solution.
Au lieu de cela, vous pouvez créer la solution A avec les projets A et Lib, ainsi que la solution B avec les projets B et Lib.
la source
Je suis dans une situation similaire. J'ai des tests unitaires qui testent la communication avec le serveur. Ils testent le comportement avec des délais d'attente, annulent des connexions, etc. L'ensemble des tests dure 7 minutes.
7 minutes est un temps relativement court, mais ce n'est pas quelque chose que vous ferez avant chaque commit.
Nous avons également un ensemble de tests d’interface utilisateur automatisés, leur durée d’exécution est de 2 heures. Ce n'est pas quelque chose que vous voulez exécuter tous les jours sur votre ordinateur.
Alors que faire?
L'important est que tous vos tests soient exécutés souvent, car il est important de détecter les bogues. Cependant, il n'est pas absolument nécessaire de les trouver avant les commits.
la source
Bien que votre description du problème ne donne pas un aperçu complet de la base de code, je pense pouvoir affirmer en toute sécurité que votre problème est double.
Apprenez à écrire les bons tests.
Vous dites que vous avez presque mille tests et 120 projets. En supposant qu'au moins la moitié de ces projets soient des projets de test, vous avez 1000 tests pour 60 projets de code de production. Cela vous donne environ 16-17 tests pr. projet!!!
C’est probablement la quantité de tests que j’aurais à faire pour couvrir environ 1 à 2 classes dans un système de production. Donc, à moins que vous n'ayez que 1 à 2 classes dans chaque projet (dans ce cas, la structure de votre projet est trop fine), vos tests sont trop volumineux, ils couvrent trop de terrain. Vous dites que c'est le premier projet que vous effectuez correctement. A dire, les chiffres que vous présentez indiquent que ce n'est pas le cas, vous ne faites pas la propriété TDD.
Vous devez apprendre à écrire les bons tests, ce qui signifie probablement que vous devez apprendre à rendre le code testable en premier lieu. Si vous ne trouvez pas l'expérience nécessaire au sein de l'équipe pour le faire, je vous suggèrerais de faire appel à une aide extérieure, par exemple sous la forme d'un ou deux consultants aidant votre équipe pendant une période de deux à trois mois à apprendre à écrire du code testable. tests unitaires minimaux.
À titre de comparaison, sur le projet .NET sur lequel je travaille actuellement, nous pouvons exécuter environ 500 tests unitaires en moins de 10 secondes (et cela n'a même pas été mesuré sur une machine de haute spécification). Si c’étaient vos chiffres, vous n’auriez pas peur de les exécuter localement de temps en temps.
Apprenez à gérer la structure du projet.
Vous avez divisé la solution en 120 projets. C'est selon mes normes un nombre impressionnant de projets.
Donc, si cela a du sens d’avoir ce nombre de projets (ce que j’ai le sentiment que ce n’est pas le cas - mais votre question ne fournit pas assez d’informations pour vous permettre d’en juger avec compétence), vous devez diviser les projets en composantes plus petites. peuvent être construits, versionnés et déployés séparément. Ainsi, lorsqu'un développeur exécute la suite de tests unitaire, il n'a plus qu'à exécuter les tests relatifs au composant sur lequel il travaille actuellement. Le serveur de compilation doit s’assurer que tout s’intègre correctement.
Mais scinder un projet en plusieurs composants construits, versionnés et déployés séparément nécessite, selon mon expérience, une équipe de développement très mature, une équipe plus mature que ce que j'ai l'impression que votre équipe est.
Quoi qu'il en soit, vous devez faire quelque chose à propos de la structure du projet. Séparez les projets en composants distincts ou commencez à fusionner des projets.
Demandez-vous si vous avez vraiment besoin de 120 projets?
ps Vous voudrez peut-être consulter NCrunch. C'est un plug-in Visual Studio qui exécute automatiquement votre test en arrière-plan.
la source
Les tests JUnit doivent normalement être rapides, mais certains d'entre eux doivent simplement prendre un certain temps pour s'exécuter.
Par exemple, le test de la base de données prend généralement quelques instants pour s’initialiser et se terminer.
Si vous avez des centaines de tests, même s'ils sont rapides, leur exécution nécessite beaucoup de temps à cause de leur nombre.
Ce qui peut être fait est:
1) Identifiez les tests cruciaux. Ceux qui concernent les parties les plus importantes des bibliothèques et ceux qui risquent le plus d’échouer après des modifications. Seuls ces tests doivent toujours être exécutés sur compilation. Si du code est souvent cassé, ses tests devraient être obligatoires, même s’ils prennent beaucoup de temps. Par contre, si une partie du logiciel n’a jamais posé problème, vous pouvez ignorer les tests sur chaque build.
2) Préparez le serveur d'intégration continue, qui exécutera tous les tests en arrière-plan. C'est à vous de décider si vous décidez de construire toutes les heures ou après chaque commit (la seconde n'a de sens que si vous voulez détecter automatiquement le commit qui a posé problème).
la source
Problèmes que j'ai vus:
a) Utiliser IOC pour construire des éléments de test. 70 secondes -> 7 secondes en retirant le conteneur.
b) Ne pas se moquer de toutes les classes. Gardez vos tests unitaires à un seul élément. J'ai vu des tests se dérouler dans plusieurs cours. Ce ne sont pas des tests unitaires et beaucoup plus susceptibles de casser.
c) Profilez-les pour savoir ce qui se passait. J'ai trouvé que le constructeur construisait des matériaux dont je n'avais pas besoin, je les ai localisés et j'ai réduit les temps d'exécution.
d) Profil. peut-être que le code n’est pas si bon et que vous pouvez gagner en efficacité grâce à un examen.
e) Supprimer les dépendances. Garder votre exécutable de test réduit le temps de chargement. Utilisez une bibliothèque d'interface et des conteneurs IOC pour exécuter votre solution finale, mais seule la bibliothèque d'interface doit être définie pour vos projets de test principaux. Cela garantit la séparation, simplifie les tests et réduit la taille de votre empreinte.
la source
Je ressens votre douleur et je suis tombé sur plusieurs endroits où la vitesse de fabrication peut être considérablement améliorée. Cependant, le nombre que je recommande est de mesurer avec un détail granulaire pour déterminer où votre construction prend le plus longtemps. Par exemple, j'ai une version avec environ 30 projets qui prend un peu plus d'une minute à exécuter. Cependant, ce n'est qu'une partie de la photo. Je sais également quels projets prennent le plus de temps à construire, ce qui aide à concentrer mes efforts.
Choses qui consomment du temps de construction:
Les bibliothèques factices utilisent la réflexion ou injectent du code à l'aide de bibliothèques de code court pour générer la maquette pour vous. Bien que ce soit très pratique, cela prend beaucoup de temps. Si vous générez des simulacres dans une boucle de votre test, cela peut ajouter une durée mesurable aux tests unitaires.
Il existe des moyens de résoudre les problèmes:
Lorsque votre solution contient plus de 100 projets, vous disposez d'une combinaison de code de bibliothèque, de tests et de code d'application. Chacune des bibliothèques peut être sa propre solution avec ses tests associés. Jet Brains Team City est un serveur CI Build qui sert également de serveur Nuget - et je suis sûr que ce n'est pas le seul. Cela vous donne la possibilité de déplacer ces bibliothèques qui ne sont probablement pas souvent modifiées dans leurs propres solutions / projets et d'utiliser Nuget pour résoudre les dépendances de votre code d'application. Des solutions plus petites signifient que vous pouvez apporter vos modifications à une bibliothèque rapidement et sans difficulté et profiter des avantages de la solution principale.
la source
Votre environnement de test peut-il fonctionner n'importe où? Si cela est possible, utilisez le cloud computing pour exécuter les tests. Répartissez les tests entre N machines virtuelles. Si le temps d'exécution des tests sur une seule machine est de T1 secondes, le temps d'exécution des tests, T2, pourrait s'approcher de T2 = T1 / N. (En supposant que chaque scénario de test dure à peu près le même temps.) Et vous ne devez payer que pour les ordinateurs virtuels lorsque vous les utilisez. Donc, vous n'avez pas un tas de machines de test assis dans un laboratoire quelque part 24/7. (J'aimerais pouvoir le faire là où je travaille, mais nous sommes liés à un matériel spécifique. Pas de machines virtuelles pour moi.)
la source