Comment accélérer la java des tests unitaires?
Actuellement, notre projet a plus de 3000 tests unitaires, et "ant testAll" prend plus de 20 minutes.
en plus d'avoir un meilleur matériel, il y a des moyens pour accélérer les choses?
- Vous devriez être plus précis, qu'est-ce que la tenue de ces tests.
- J'ai rejoint ce projet il y a deux mois, et c'est déjà une grande base de code. Ce n'est pas une application web et à l'exception d'un tas de fichiers de configuration xml, il ne fait pas de Fichier IO assez souvent. Nous sommes à l'aide de notre personnalisés Lanceur. mais le truc, c'est que nous sommes seulement de développer uniquement des plugins pour le système, et en tant que tel, nous n'avons pas le Lanceur de code source. Je suppose Lanceur du réalisateur a été assez intelligent pour avoir optimisé l'installation de trucs, donc, par exemple, ne pas avoir à analyser les configurations xml dans chaque série de tests.
- êtes-vous en utilisant les objets fantaisie pour se moquer de lent à accéder à des objets à partir de vos tests unitaires? Au travail, nous avons 6000 tests unitaires et ils vous prendre environ une minute ou peut-être deux à s'exécuter.
Vous devez vous connecter pour publier un commentaire.
La même manière que vous le feriez accélérer tout autre code. Découvrez les tests prennent le plus de temps, et de voir comment ils peuvent être optimisés.
Il y a beaucoup d'activités qui peuvent être lents, et si vous ne leur 3000 fois, il ajoute. Parfois, la réutilisation de données entre les tests en vaut la peine (même si vous n'êtes pas censé le faire dans les tests unitaires, il peut être nécessaire, si c'est ce qu'il faut pour obtenir votre tests à exécuter à une vitesse acceptable).
Temps de vos tests. Généralement, 90% d'entre eux va exécuter presque instantanément, et les derniers 10% aura presque tout le temps. Trouver ces 10% et de voir ce qu'ils font.
Exécuter le code par l'intermédiaire d'un générateur de profils, et notez le temps passé. Devinant est une perte de temps. Ce que vous pense le test runner est en train de faire est dénuée de sens. Au lieu de deviner, trouver ce qu'il fait. Ensuite, vous saurez comment l'accélérer.
Quelques idées:
Vous pouvez diviser vos tests unitaires dans les suites. Votre demande est modulaire? Combien de fois avez-vous vraiment besoin pour exécuter tous les tests? Serait-il acceptable si vos développeurs seulement couru l'unité de tests pertinents à leur propre module, et vous avez eu l'éventail de tests exécuter tous les soirs et/ou sur une IC?
Sont a t-il des tests unitaires qui sont très complexes (je sais, je suis le glisser dans la fonctionnelle et les tests d'intégration ici, mais parfois la frontière est floue), mais peut-être s'exécuter sur un santé mentaleniveau au cours du développement et ensuite exécuter en plein sur l'IC?
Modifier: Juste pour le plaisir, je vais brièvement décrire les routines de test à un de mes précédents projets
Tout d'abord, la croissance du système de test a été organiques, ce qui signifie qu'il n'a pas été prévu à l'origine, mais a été modifié et changé comme elle a grandi. Par conséquent, il n'était pas parfait, et il y avait certaines conventions de nommage, ce qui était devenu apocryphe avec le temps.
De tests automatiques - c'est le chien de noix.
Pour Commencer :
a) d'Obtenir des statistiques sur les temps d'exécution de vos Tests Junit.Vous avez peut-être déjà caputring que informaion dans vos rapports de test.
b) Prendre top 10 des classes de test (en temps) et d'essayer de réduire le temps .Ce que vous devez faire sur une base continue.
c) Essayer de réduire le temps d'exécution par refactoring ou même le changement de l'approche de test.
Un de ces cas, je suis venu à travers est dans une classe de Test pour CRUD des cas de test.Mise à jour de cas de test a d'abord été la création de la funtionlaity et puis updateing .Mais nous avons déjà testé de créer dans seprate cas de test.Donc, dans ces cas, vous pouvez enchaîner vos cas de test comme
Afin de vous enregistrer sur le fait de faire dupicate tests.
d)Un autre exemple où j'ai été en mesure de réduire le temps significalntly a été.
Nous avions un système (inherietd )où chaque cas de test est appel programme d'Installation(À Ressort Serveur etc) et après l'exécution de l'arrêt de ressources système.Cela a été très long ,j'ai donc refait il pour commencer à coomon ressources avant de tester le costume et après toute la suite est fait, puis fermez-les.
e) en Fonction de votre projet peut être d'autres obstacles que vous pouvez avoir besoin de repasser.
Comment gérer les temps de compilation en mode TDD
Je suis en supposant que vous avez traversé toutes les autres étapes habituelles comme se moquant d'appels de base de données, l'optimisation de l'installation d'essai phases etc. et ce qui est de prendre le test, c'est que vous avez 3000 tests pas que des tests individuels sont très lents.
Si oui, une approche multi-thread de votre essai. Test-NG supporte très bien. La conversion de vos tests junit pour tester-ng n'est pas si dur et ne doit être effectuée qu'une fois.
Tests qui doivent être exécutées de manière séquentielle peut être facilement marqué:
Sur une machine multi-coeur vous verrez d'énormes améliorations dans l'exécution. Même sur un seul core, vous verrez une bonne amélioration des fils d'attente pour les opérations d'e /s.
Voir ici pour plus de détails sur comment le configurer:
http://beust.com/weblog/archives/000407.html
Espère que cette aide.
....
Quelques suggestions - je ne peux pas croire que vous n'utilisez pas d'intégration Continue. Faites-moi confiance 30 développeurs ne va pas surcharger votre serveur CI. Même si vous ne pouvez pas acheter dans pour l'IC, installer hudson sur votre propre machine, il faudra 10 minutes pour l'installation et les avantages sont énormes. Demandez à votre gestionnaire de ce qui est le pire de tout développeur assis en attente pour les tests unitaires pour valider ou d'avoir un serveur pour le faire pour vous. Avoir un stupide chapeau pour la personne qui s'est cassé la construction est généralement suffisant pour convaincre les développeurs d'exécuter leurs tests unitaires.
Si la qualité d'archivages sont vraiment un énorme souci (n'oubliez pas de faire un check-in peut toujours être annulée) d'envisager de Teamcity - il exécute les tests et ne pas commettre le code si les tests échoue.
Enfin, une option qui peut convenir à votre cas d'utilisation est également le trèfle et le bambou. La dernière version conserve un enregistrement de ce code est testé par quels tests et lorsqu'une modification est faite, il ne fonctionne que les tests en question. C'est potentiellement très puissant.
Mais rappelez-vous outils intelligents comme test-ng, teamcity et le trèfle ne fera que vous obtenez ce jour - bon tests ne pas écrire eux-mêmes!
Pour résumer ma solution c'est d'essayer de toutes ou de certaines des étapes suivantes:
Êtes-vous à l'aide de
fork="yes"
dans votrejunit
appel? Si oui, assurez-vous de définirforkMode="once"
, sinon la junit tâche de commencer une nouvelle VM pour chaque cas de test de la classe. Avec 3000 tests unitaires, qui fera une énorme différence.http://ant.apache.org/manual/Tasks/junit.html
Évidemment, il y a quelque chose dans votre essai qui prend du temps.
Parfois, vous ne pouvez pas obtenir autour de ralentir test. Par exemple, les tests que le Printemps peut lire tous ses fichiers de configuration, les tests que hibernate mapping fonctionne, ce genre de trucs. La bonne chose à propos de ces test est qu'il suffit de s'exécuter dans un seul test et ensuite vous pouvez vous moquer de tout, mais vous pouvez aussi décider d'exécuter dans le cadre du test d'intégration et de laisser le serveur de build vous inquiétez à ce sujet.
Le reste de l'tests sont lents, soit parce qu'ils sont en train de faire IO ou parce qu'ils sont trop liées à l'UC.
IO peut être beaucoup de choses. Service Web et base de données des appels peut être abstrait et se moquèrent, et les rares appels que vous avez à faire peut être déplacé à la phase d'intégration en cas de besoin. La journalisation peut vraiment ralentir les choses ainsi - surtout avec 3.000 cas de test. Je dirais juste désactiver la journalisation entièrement et de compter sur votre cerveau et votre débogueur lorsqu'un test échoue.
Il peut y avoir des cas où l'OI est lui-même l'appareil testé. Par exemple, si vous testez le cadre d'un serveur de base de données qui écrit les données de la table sur le disque. Dans ce cas, essayez de garder autant d'IO en mémoire que possible. En Java, de nombreux IO abstractions ont en mémoire les implémentations.
CPU limites des tests vient en différentes saveurs ainsi. La performance Pure et test de débit doit être dans l'intégration de la phase de test. Si vous échappez à un tas de fils pour essayer un vétérinaire une simultanéité bug, vous pouvez déplacer le grand test de la phase d'intégration et de garder une version dans votre suite de tests.
Et enfin, le profileur est votre ami. Il se pourrait bien que les parties de votre code peut être rendue plus efficace et donner un sensiblement la vitesse de vos tests jusqu'.
Sans la connaissance de ce qui est testé, les deux seules approches qui se présentent sont:
Vous pouvez même exécuter un profiler sur le test et voir si il y a tout particulièrement inefficace mis en œuvre des tests.
Bien, je ne sais pas ce que votre Unité de test sont en train de faire, mais vous devez demander vous-même pourquoi c'est en prenant 20 minutes.
De mon expérience, il y a souvent beaucoup de tests exécutés dans un délai de quelques millisecondes et quelques essais qui composent le reste du temps. Le plus souvent ce sont des tests impliquant IO/réseau/DB-Stuff.
Par exemple, si vous passez beaucoup de temps d'attente en raison d'un réseau de latence, vous pourriez envisager de l'exécution de vos tests en parallèle.
Vous pourriez traquer les tests en question et chercher à s'améliorer. Mais faire vos tests rapides ne pas faire de votre code mieux.
Vous voudrez peut-être regarder pour des tests qui nécessitent beaucoup de temps parce que la classe sous test n'est pas optimal. Repérer et l'amélioration des situations comme celles-ci sera très probablement faire de votre produit mieux/plus vite.
Je suis d'accord avec Pablojim. Paralléliser vos tests. Nous sommes à l'aide de clearcase et le transfert de tout, de viewservers vraiment ralentir les choses. Lorsque nous avons parallélisé sur un duelcore nous avons obtenu 6 à 8 fois plus rapide, plus court essai.
Nous sommes à l'aide de la CPPUnit cadre et nous avons juste ajouté des scripts python pour kickstart différentes suites de tests sur des threads différents.
Nous avons également utilisé clearmake pour paralléliser le processus de construction. Notre prochaine étape sera probablement de paralléliser les tests sur les clients de la part des développeurs.
Déplacer la suite de tests complète en Continu d'un moteur d'Intégration système, de sorte que les développeurs n'ont pas à les exécuter à chaque fois. De tels systèmes ont BEAUCOUP plus de patience que les développeurs.
Je voudrais aborder ce problème comme vous le feriez pour tout autre problème de performance:
Vous pouvez trouver que vous avez à creuser dans ce test runner finalement. Vous pouvez utiliser une décompilation outil comme cavaj pour générer du code source à partir du fichier de classe (bien qu'il sera plus difficile à lire que le code d'origine, évidemment). Vous pouvez trouver que quelque chose dans le lanceur de test de la mise en œuvre est d'affecter les performances. Par exemple, vous l'avez déjà mentionné la lecture des fichiers de configuration XML comme une activité que le test runner effectue -- c'est quelque chose qui pourrait potentiellement afffect performance.
Un autre domaine où vous pourriez éventuellement trouver des problèmes de performance est dans la coutume de "base" classes de cas de test. Ceux-ci ont tendance à être des choses qui ajoutent beaucoup de pratique, mais il peut être difficile de se rappeler que votre commodité-l'ajout de comportements vont potentiellement être amortis sur 10k tests dans un projet de grande envergure, si chaque test doit la commodité de comportement ou pas.
Je vous suggérerais d'avoir deux versions (en Incrémental qui est exécuté sur chaque enregistrement, et une version Complète qui est exécuté pendant la nuit),
L'augmentation fonctionne plus courte tests en environ 7 minutes, tandis que la version complète exécute tous les tests de plus en moins de 40 minutes.
Clearcase encourage une ramification de cauchemar, mais vous devriez être en mesure d'avoir deux versions par développeur. Je m'interroge sur la valeur en avoir à tous les développer sur leur propre branche que je crois qu'il y a certains avantages à avoir des développeurs de travailler ensemble (en paires ou plus) sur la même branche.
Remarque: Un serveur d'intégration continue peut avoir un nombre quelconque d'agents et si vous ne pouvez pas se permettre plus d'un serveur, vous pouvez utiliser le Pc comme un construit des agents. (Vous devez avoir au moins 30 de ces)
Ici est l'approche que j'allais prendre.
Le moyen le plus efficace pour accélérer une grande suite de test consiste à exécuter de façon incrémentielle, de sorte que seuls les tests qui touche code a changé depuis la dernière série de tests sont ré-exécuté. Après tout, le plus rapide des essais seront toujours celles qui sont pas exécuté. 8^)
La partie la plus difficile est en fait de se faire ce travail. Je suis actuellement en train de travailler à une augmentation des tests pour JUnit 4, qui fait partie de la "JMockit Couverture" de l'outil dans le JMockit développeur de tests boîte à outils. C'est encore immature, mais je crois qu'il va bien travailler.
DB accès et la latence du réseau peut être une zone à examiner. Si vous êtes à effectuer un grand nombre de base de données access dans vos tests d'intégration, vous pouvez explorer à l'aide d'une base de données en mémoire comme HSQL, H2 et Derby au lieu d'un "réel" de la base de données comme Oracle. Si vous utilisez la mise en veille prolongée, vous devrez également changer les paramètres de votre Hibernate configs à utiliser le dialecte spécifique à l'DB (par exemple, HSQLDialect au lieu de OracleDialect). Était sur un projet de fois où chaque version complète finirait par avoir à supprimer et recréer l'ensemble d'un schéma Oracle et à exécuter de nombreuses db tests sur le réseau et qu'il serait parfois prendre jusqu'à 20 minutes, et ensuite de trouver la personne en soute et les choses ont été brisé à nouveau. 🙁
Idéalement, vous voulez avoir juste une DB script est utilisable pour les deux bases de données, mais vous pourriez avoir à synchroniser deux DB scripts de création - l'un pour la production, l'un pour les tests d'intégration.
DB dans la même JVM vs DB dans le réseau peut faire une différence.