Jusqu'à présent, j'ai évité le cauchemar qui teste le code multi-thread car il semble tout simplement trop d'un champ de mines. Je voudrais savoir comment les gens ont testé le code qui s'appuie sur les threads pour une exécution réussie, ou comment les gens ont testé les types de problèmes qui n'apparaissent que lorsque deux threads interagissent d'une manière donnée?
Cela semble être un problème vraiment clé pour les programmeurs aujourd'hui, il serait utile de mettre en commun nos connaissances sur celui-ci à mon humble avis.
Réponses:
Regardez, il n'y a pas de moyen facile de le faire. Je travaille sur un projet qui est intrinsèquement multithread. Les événements proviennent du système d'exploitation et je dois les traiter simultanément.
La façon la plus simple de gérer le test d'un code d'application complexe et multithread est la suivante: si c'est trop complexe à tester, vous le faites mal. Si vous avez une seule instance qui a plusieurs threads agissant dessus et que vous ne pouvez pas tester des situations où ces threads se chevauchent, votre conception doit être refaite. C'est à la fois aussi simple et aussi complexe que cela.
Il existe de nombreuses façons de programmer le multithreading qui évite que les threads ne traversent les instances en même temps. Le plus simple est de rendre tous vos objets immuables. Bien sûr, ce n'est généralement pas possible. Vous devez donc identifier les emplacements de votre conception où les threads interagissent avec la même instance et réduire le nombre de ces emplacements. En procédant ainsi, vous isolez quelques classes où le multithreading se produit réellement, ce qui réduit la complexité globale des tests de votre système.
Mais vous devez réaliser que même en faisant cela, vous ne pouvez toujours pas tester chaque situation où deux threads se marchent. Pour ce faire, vous devez exécuter deux threads simultanément dans le même test, puis contrôler exactement les lignes qu'ils exécutent à un moment donné. Le mieux que vous puissiez faire est de simuler cette situation. Mais cela peut vous obliger à coder spécifiquement pour les tests, et c'est au mieux un demi-pas vers une vraie solution.
La meilleure façon de tester le code pour les problèmes de thread est probablement par l'analyse statique du code. Si votre code threadé ne suit pas un ensemble fini de modèles thread-safe, vous pouvez avoir un problème. Je crois que l'analyse de code dans VS contient une certaine connaissance du filetage, mais probablement pas beaucoup.
Regardez, dans l'état actuel des choses (et cela durera probablement encore un bon moment), la meilleure façon de tester des applications multithread est de réduire autant que possible la complexité du code threadé. Minimisez les zones où les threads interagissent, testez le mieux possible et utilisez l'analyse de code pour identifier les zones dangereuses.
la source
Cela fait un moment que cette question a été publiée, mais il n'y a toujours pas de réponse ...
La réponse de kleolb02 est bonne. J'essaierai d'entrer dans plus de détails.
Il y a un moyen que je pratique pour le code C #. Pour les tests unitaires, vous devriez pouvoir programmer des tests reproductibles , ce qui est le plus grand défi du code multithread. Ma réponse vise donc à forcer le code asynchrone dans un faisceau de test, qui fonctionne de manière synchrone .
C'est une idée du livre de Gerard Meszardos " xUnit Test Patterns " et s'appelle "Humble Object" (p. 695): Vous devez séparer le code logique de base et tout ce qui sent le code asynchrone les uns des autres. Cela entraînerait une classe pour la logique de base, qui fonctionne de manière synchrone .
Cela vous met en position de tester le code logique de base de manière synchrone . Vous avez un contrôle absolu sur le timing des appels que vous effectuez sur la logique principale et pouvez ainsi effectuer des tests reproductibles . Et c'est votre avantage de séparer la logique principale et la logique asynchrone.
Cette logique de base doit être enveloppée par une autre classe, qui est chargée de recevoir les appels à la logique de base de manière asynchrone et délègue ces appels à la logique de base. Le code de production n'accédera à la logique principale que via cette classe. Parce que cette classe ne devrait déléguer que les appels, c'est une classe très "stupide" sans beaucoup de logique. Ainsi, vous pouvez garder vos tests unitaires pour cette classe ouvrière asychrone au minimum.
Tout ce qui est supérieur à cela (tester l'interaction entre les classes) sont des tests de composants. Dans ce cas également, vous devriez avoir un contrôle absolu sur le timing, si vous vous en tenez au modèle "Humble Object".
la source
Un dur en effet! Dans mes tests unitaires (C ++), j'ai divisé cela en plusieurs catégories selon le modèle de concurrence utilisé:
Tests unitaires pour les classes qui fonctionnent dans un seul thread et ne sont pas sensibles aux threads - facile, testez comme d'habitude.
Tests unitaires pour les objets Monitor (ceux qui exécutent des méthodes synchronisées dans le thread de contrôle des appelants) qui exposent une API publique synchronisée - instanciez plusieurs threads factices qui exercent l'API. Construisez des scénarios qui exercent les conditions internes de l'objet passif. Incluez un test de fonctionnement plus long qui en vaut la peine à partir de plusieurs threads pendant une longue période de temps. C'est non scientifique, je sais, mais cela renforce la confiance.
Tests unitaires pour les objets actifs (ceux qui encapsulent leur propre thread ou threads de contrôle) - similaires au n ° 2 ci-dessus avec des variations selon la conception de la classe. L'API publique peut être bloquante ou non bloquante, les appelants peuvent obtenir des contrats à terme, les données peuvent arriver dans les files d'attente ou doivent être retirées de la file d'attente. Il existe de nombreuses combinaisons possibles ici; boîte blanche loin. Nécessite toujours plusieurs threads simulés pour effectuer des appels à l'objet testé.
En aparté:
Dans la formation de développeur interne que je fais, j'enseigne les piliers de la concurrence et ces deux modèles comme cadre principal de réflexion et de décomposition des problèmes de concurrence. Il y a évidemment des concepts plus avancés, mais j'ai trouvé que cet ensemble de bases aide à garder les ingénieurs hors de la soupe. Cela conduit également à un code plus testable à l'unité, comme décrit ci-dessus.
la source
J'ai rencontré ce problème plusieurs fois ces dernières années lors de l'écriture de code de gestion de threads pour plusieurs projets. Je fournis une réponse tardive car la plupart des autres réponses, tout en fournissant des alternatives, ne répondent pas réellement à la question sur les tests. Ma réponse s'adresse aux cas où il n'y a pas d'alternative au code multithread; Je couvre les problèmes de conception de code pour être complet, mais je discute également des tests unitaires.
Écriture de code multithread testable
La première chose à faire est de séparer le code de gestion de votre thread de production de tout le code qui effectue le traitement des données. De cette façon, le traitement des données peut être testé en tant que code à thread unique, et la seule chose que fait le code multithread est de coordonner les threads.
La deuxième chose à retenir est que les bogues dans le code multithread sont probabilistes; les bogues qui se manifestent le moins fréquemment sont les bogues qui se faufileront en production, seront difficiles à reproduire même en production, et causeront ainsi les plus gros problèmes. Pour cette raison, l'approche de codage standard consistant à écrire le code rapidement puis à le déboguer jusqu'à ce qu'il fonctionne est une mauvaise idée pour le code multithread; il en résultera du code où les bogues faciles sont corrigés et les bogues dangereux sont toujours là.
Au lieu de cela, lors de l'écriture de code multithread, vous devez écrire le code avec l'attitude que vous allez éviter d'écrire les bogues en premier lieu. Si vous avez correctement supprimé le code de traitement des données, le code de gestion des threads doit être suffisamment petit - de préférence quelques lignes, au pire quelques dizaines de lignes - pour que vous puissiez l'écrire sans écrire de bogue, et certainement sans écrire de nombreux bogues. , si vous comprenez le filetage, prenez votre temps et faites attention.
Écriture de tests unitaires pour du code multithread
Une fois que le code multithread est écrit aussi soigneusement que possible, il vaut toujours la peine d'écrire des tests pour ce code. Le but principal des tests n'est pas tant de tester des bogues de conditions de course très dépendants du temps - il est impossible de tester de telles conditions de course de manière répétée - mais plutôt de tester que votre stratégie de verrouillage pour empêcher de tels bogues permet à plusieurs threads d'interagir comme prévu .
Pour tester correctement le comportement de verrouillage correct, un test doit démarrer plusieurs threads. Pour rendre le test reproductible, nous voulons que les interactions entre les threads se produisent dans un ordre prévisible. Nous ne voulons pas synchroniser les threads en externe dans le test, car cela masquera les bogues qui pourraient survenir en production lorsque les threads ne sont pas synchronisés en externe. Cela laisse l'utilisation de délais de synchronisation pour la synchronisation des threads, qui est la technique que j'ai utilisée avec succès chaque fois que j'ai dû écrire des tests de code multithread.
Si les retards sont trop courts, le test devient fragile, car des différences de synchronisation mineures - disons entre les différentes machines sur lesquelles les tests peuvent être exécutés - peuvent entraîner une interruption du chronométrage et un échec du test. Ce que j'ai généralement fait, c'est commencer avec des retards qui provoquent des échecs de test, augmenter les retards pour que le test passe de manière fiable sur ma machine de développement, puis doubler les retards au-delà de cela pour que le test ait de bonnes chances de passer sur d'autres machines. Cela signifie que le test prendra un temps macroscopique, bien que d'après mon expérience, une conception de test minutieuse peut limiter ce temps à pas plus d'une douzaine de secondes. Comme vous ne devriez pas avoir beaucoup d'endroits nécessitant du code de coordination de threads dans votre application, cela devrait être acceptable pour votre suite de tests.
Enfin, gardez une trace du nombre de bugs détectés par votre test. Si votre test a une couverture de code de 80%, on peut s'attendre à ce qu'il détecte environ 80% de vos bogues. Si votre test est bien conçu mais ne trouve aucun bogue, il y a une chance raisonnable que vous n'ayez pas de bogues supplémentaires qui n'apparaîtront qu'en production. Si le test détecte un ou deux bogues, vous pourriez toujours avoir de la chance. Au-delà de cela, et vous voudrez peut-être envisager un examen attentif ou même une réécriture complète de votre code de gestion des threads, car il est probable que le code contienne encore des bogues cachés qui seront très difficiles à trouver jusqu'à ce que le code soit en production, et très difficile à réparer alors.
la source
J'ai également eu de sérieux problèmes pour tester du code multithread. Ensuite, j'ai trouvé une solution vraiment cool dans "xUnit Test Patterns" de Gerard Meszaros. Le motif qu'il décrit est appelé objet humble .
Fondamentalement, il décrit comment extraire la logique dans un composant distinct, facile à tester, découplé de son environnement. Après avoir testé cette logique, vous pouvez tester le comportement compliqué (multi-threading, exécution asynchrone, etc ...)
la source
Il y a quelques outils qui sont assez bons. Voici un résumé de certains de ceux de Java.
Quelques bons outils d'analyse statique incluent FindBugs (donne quelques conseils utiles), JLint , Java Pathfinder (JPF & JPF2) et Bogor .
MultithreadedTC est un assez bon outil d'analyse dynamique (intégré à JUnit) où vous devez configurer vos propres cas de test.
ConTest d'IBM Research est intéressant. Il instrumente votre code en insérant toutes sortes de comportements de modification de threads (par exemple sommeil et rendement) pour essayer de découvrir des bogues de manière aléatoire.
TOURNER est un outil vraiment cool pour modéliser vos composants Java (et autres), mais vous devez disposer d'un cadre utile. Il est difficile à utiliser tel quel, mais extrêmement puissant si vous savez comment l'utiliser. De nombreux outils utilisent SPIN sous le capot.
MultithreadedTC est probablement le plus courant, mais certains des outils d'analyse statique répertoriés ci-dessus valent vraiment la peine d'être examinés.
la source
L'attente peut également être utile pour vous aider à écrire des tests unitaires déterministes. Il vous permet d'attendre la mise à jour d'un état quelque part dans votre système. Par exemple:
ou
Il prend également en charge Scala et Groovy.
la source
Une autre façon de (un peu) tester du code threadé, et des systèmes très complexes en général, est par le biais de Fuzz Testing . Ce n'est pas génial, et il ne trouvera pas tout, mais il est susceptible d'être utile et simple à faire.
Citation:
la source
J'en ai fait beaucoup, et oui ça craint.
Quelques conseils:
throwable
champ et archivez-letearDown
(voir Listing 1). Si vous interceptez une mauvaise exception dans un autre thread, affectez-la simplement à throwable.AtomicBoolean
vos tests. Il est thread-safe et vous aurez souvent besoin d'un type de référence final pour stocker les valeurs des classes de rappel et autres. Voir l'exemple dans le Listing 3.@Test(timeout=60*1000)
), car les tests de simultanéité peuvent parfois se bloquer indéfiniment lorsqu'ils sont interrompus.Listing 1:
Listing 2:
Listing 3:
la source
Tester le code MT pour l'exactitude est, comme déjà indiqué, un problème assez difficile. En fin de compte, cela revient à s'assurer qu'il n'y a pas de courses de données mal synchronisées dans votre code. Le problème avec cela est qu'il existe une infinité de possibilités d'exécution de threads (entrelacements) sur lesquelles vous n'avez pas beaucoup de contrôle (assurez-vous de lire ceci article, cependant). Dans des scénarios simples, il pourrait être possible de prouver réellement l'exactitude par le raisonnement, mais ce n'est généralement pas le cas. Surtout si vous voulez éviter / minimiser la synchronisation et ne pas opter pour l'option de synchronisation la plus évidente / la plus simple.
Une approche que je suis consiste à écrire du code de test hautement simultané afin de faire en sorte que des courses de données potentiellement non détectées se produisent. Et puis je lance ces tests pendant un certain temps :) Une fois, je suis tombé sur une conversation où un informaticien montrait un outil de ce genre (en créant au hasard un test à partir des spécifications et en les exécutant de manière sauvage, simultanément, en vérifiant les invariants définis) être cassé).
Soit dit en passant, je pense que cet aspect du test du code MT n'a pas été mentionné ici: identifier les invariants du code que vous pouvez vérifier au hasard. Malheureusement, trouver ces invariants est également un problème assez difficile. De plus, ils peuvent ne pas tenir tout le temps pendant l'exécution, vous devez donc trouver / appliquer des points d'exécution où vous pouvez vous attendre à ce qu'ils soient vrais. Apporter l'exécution du code à un tel état est également un problème difficile (et pourrait lui-même entraîner des problèmes de concurrence. Ouf, c'est sacrément difficile!
Quelques liens intéressants à lire:
la source
Pete Goodliffe a une série sur les tests unitaires de code threadé .
C'est dur. Je prends la voie la plus facile et j'essaie de garder le code de threading abstrait du test réel. Pete mentionne que ma façon de procéder est erronée, mais j'ai la bonne séparation ou j'ai juste eu de la chance.
la source
Pour Java, consultez le chapitre 12 de JCIP . Il existe des exemples concrets d'écriture de tests unitaires déterministes et multithreads pour au moins tester l'exactitude et les invariants du code simultané.
"Prouver" la sécurité des threads avec des tests unitaires est beaucoup plus difficile. Ma conviction est que cela est mieux servi par des tests d'intégration automatisés sur une variété de plates-formes / configurations.
la source
J'aime écrire deux ou plusieurs méthodes de test à exécuter sur des threads parallèles, et chacune d'elles fait des appels dans l'objet testé. J'ai utilisé des appels Sleep () pour coordonner l'ordre des appels des différents threads, mais ce n'est pas vraiment fiable. C'est aussi beaucoup plus lent car vous devez dormir suffisamment longtemps pour que le timing fonctionne généralement.
J'ai trouvé la bibliothèque Java TC multithread du même groupe qui a écrit FindBugs. Il vous permet de spécifier l'ordre des événements sans utiliser Sleep (), et il est fiable. Je ne l'ai pas encore essayé.
La plus grande limitation de cette approche est qu'elle ne vous permet que de tester les scénarios que vous suspectez de causer des problèmes. Comme d'autres l'ont dit, vous devez vraiment isoler votre code multithread dans un petit nombre de classes simples pour avoir tout espoir de les tester en profondeur.
Une fois que vous avez soigneusement testé les scénarios que vous prévoyez de causer des problèmes, un test non scientifique qui lance un tas de demandes simultanées à la classe pendant un certain temps est un bon moyen de rechercher des problèmes inattendus.
Mise à jour: j'ai joué un peu avec la bibliothèque Java TC multithread, et cela fonctionne bien. J'ai également porté certaines de ses fonctionnalités vers une version .NET que j'appelle TickingTest .
la source
Je gère les tests unitaires des composants filetés de la même manière que je gère tout test unitaire, c'est-à-dire avec inversion des cadres de contrôle et d'isolement. Je développe dans l'arène .Net et hors de la boîte, le filetage (entre autres) est très difficile (je dirais presque impossible) à isoler complètement.
Par conséquent, j'ai écrit des wrappers qui ressemblent à ceci (simplifié):
À partir de là, je peux facilement injecter IThreadingManager dans mes composants et utiliser le cadre d'isolation de mon choix pour que le thread se comporte comme je m'y attendais pendant le test.
Jusqu'à présent, cela a très bien fonctionné pour moi, et j'utilise la même approche pour le pool de threads, les choses dans System.Environment, Sleep, etc., etc.
la source
Jetez un oeil à ma réponse connexe à
Conception d'une classe de test pour une barrière personnalisée
Il est biaisé vers Java mais a un résumé raisonnable des options.
En résumé, (IMO) ce n'est pas l'utilisation d'un cadre sophistiqué qui garantira l'exactitude, mais comment vous allez concevoir votre code multithread. La division des préoccupations (concurrence et fonctionnalité) contribue grandement à accroître la confiance. La croissance d'un logiciel orienté objet guidé par des tests explique certaines options mieux que moi.
L'analyse statique et les méthodes formelles (voir Concurrence: modèles d'état et programmes Java ) sont une option mais je les ai trouvées d'une utilité limitée dans le développement commercial.
N'oubliez pas que les tests de style de chargement / trempage sont rarement garantis pour mettre en évidence des problèmes.
Bonne chance!
la source
tempus-fugit
bibliothèque ici, quihelps write and test concurrent code
;)J'ai récemment découvert (pour Java) un outil appelé Threadsafe. C'est un outil d'analyse statique un peu comme findbugs, mais spécifiquement pour repérer les problèmes de multi-threading. Ce n'est pas un remplacement pour les tests mais je peux le recommander dans le cadre de l'écriture de Java multi-thread fiable.
Il détecte même des problèmes potentiels très subtils autour de choses comme la subsomption de classe, l'accès à des objets dangereux via des classes simultanées et la détection de modificateurs volatils manquants lors de l'utilisation du paradigme de verrouillage à double vérification.
Si vous écrivez Java multithread, essayez-le .
la source
L'article suivant propose 2 solutions. Envelopper un sémaphore (CountDownLatch) et ajoute des fonctionnalités comme externaliser les données du thread interne. Un autre moyen d'atteindre cet objectif consiste à utiliser Thread Pool (voir Points d'intérêt).
Sprinkler - Objet de synchronisation avancée
la source
J'ai passé la majeure partie de la semaine dernière dans une bibliothèque universitaire à étudier le débogage de code simultané. Le problème central est que le code concurrent n'est pas déterministe. En règle générale, le débogage académique est tombé dans l'un des trois camps ici:
Maintenant, comme l'ont remarqué les commentateurs ci-dessus, vous pouvez concevoir votre système simultané dans un état plus déterministe. Cependant, si vous ne le faites pas correctement, vous revenez à la conception d'un système séquentiel.
Ma suggestion serait de se concentrer sur un protocole de conception très strict sur ce qui est enfilé et ce qui ne l'est pas. Si vous contraignez votre interface pour qu'il y ait un minimum de dépendances entre les éléments, c'est beaucoup plus facile.
Bonne chance et continuez à travailler sur le problème.
la source
J'ai eu la malheureuse tâche de tester du code threadé et ce sont certainement les tests les plus difficiles que j'ai jamais écrits.
Lors de la rédaction de mes tests, j'ai utilisé une combinaison de délégués et d'événements. Fondamentalement, il s'agit d'utiliser des
PropertyNotifyChanged
événements avec unWaitCallback
ou une sorte deConditionalWaiter
sondages.Je ne sais pas si c'était la meilleure approche, mais cela a fonctionné pour moi.
la source
En supposant que sous le code "multi-thread", cela signifiait quelque chose qui est
En d'autres termes, nous parlons de tester une classe / méthode / unité thread-safe personnalisée avec état - qui devrait être une bête très rare de nos jours.
Parce que cette bête est rare, nous devons d'abord nous assurer qu'il existe toutes les excuses valables pour l'écrire.
Étape 1. Envisagez de modifier l'état dans le même contexte de synchronisation.
Aujourd'hui, il est facile d'écrire du code simultané et asynchrone à composer où les E / S ou autres opérations lentes sont déchargées en arrière-plan mais l'état partagé est mis à jour et interrogé dans un contexte de synchronisation. par exemple les tâches asynchrones / en attente et Rx dans .NET, etc. - elles sont toutes testables par conception, les "vraies" tâches et les planificateurs peuvent être substitués pour rendre les tests déterministes (mais cela est hors de portée de la question).
Cela peut sembler très contraint, mais cette approche fonctionne étonnamment bien. Il est possible d'écrire des applications entières dans ce style sans avoir besoin de rendre tout état thread-safe (je le fais).
Étape 2. Si la manipulation de l'état partagé sur un contexte de synchronisation unique n'est absolument pas possible.
Assurez-vous que la roue n'est pas réinventée / il n'y a certainement aucune alternative standard qui peut être adaptée pour le travail. Il devrait être probable que le code soit très cohésif et contenu dans une seule unité, par exemple avec de bonnes chances, c'est un cas particulier d'une structure de données standard sécurisée pour les threads comme une carte de hachage ou une collection ou autre.
Remarque: si le code est volumineux / s'étend sur plusieurs classes ET a besoin d'une manipulation d'état multi-thread, il y a de fortes chances que la conception ne soit pas bonne, reconsidérez l'étape 1
Étape 3. Si cette étape est atteinte, nous devons tester notre propre classe / méthode / unité thread-safe avec état .
Je serai très honnête: je n'ai jamais eu à écrire de tests appropriés pour un tel code. La plupart du temps, je m'éloigne à l'étape 1, parfois à l'étape 2. La dernière fois que j'ai dû écrire du code thread-safe personnalisé, c'était il y a tellement d'années que c'était avant d'adopter les tests unitaires / probablement je n'aurais pas à l'écrire avec les connaissances actuelles de toute façon.
Si je devais vraiment tester un tel code ( enfin, la réponse réelle ), j'essaierais deux ou trois choses ci-dessous
Tests de résistance non déterministes. Par exemple, exécutez 100 threads simultanément et vérifiez que le résultat final est cohérent. Ceci est plus typique pour les tests de niveau supérieur / d'intégration de plusieurs scénarios d'utilisateurs, mais peut également être utilisé au niveau de l'unité.
Exposez des «hooks» de test où test peut injecter du code pour aider à créer des scénarios déterministes où un thread doit effectuer l'opération avant l'autre. Aussi laid soit-il, je ne vois rien de mieux.
Des tests retardés pour faire fonctionner les threads et effectuer des opérations dans un ordre particulier. À strictement parler, ces tests ne sont pas non plus déterministes (il existe un risque de gel du système / arrêt de la collection GC du monde qui peut fausser les retards autrement orchestrés), il est également moche mais permet d'éviter les crochets.
la source
Pour le code J2E, j'ai utilisé SilkPerformer, LoadRunner et JMeter pour les tests de concurrence des threads. Ils font tous la même chose. Fondamentalement, ils vous offrent une interface relativement simple pour administrer leur version du serveur proxy, nécessaire, afin d'analyser le flux de données TCP / IP et de simuler plusieurs utilisateurs effectuant des demandes simultanées à votre serveur d'applications. Le serveur proxy peut vous donner la possibilité d'analyser les demandes, en présentant la page entière et l'URL envoyées au serveur, ainsi que la réponse du serveur, après avoir traité la demande.
Vous pouvez trouver des bogues en mode http non sécurisé, où vous pouvez au moins analyser les données du formulaire qui sont envoyées et les modifier systématiquement pour chaque utilisateur. Mais les vrais tests sont lorsque vous exécutez dans https (Secured Socket Layers). Ensuite, vous devez également composer avec une modification systématique des données de session et de cookie, ce qui peut être un peu plus compliqué.
Le meilleur bogue que j'ai jamais trouvé, lors du test de la concurrence, a été lorsque j'ai découvert que le développeur s'était appuyé sur la récupération de place Java pour fermer la demande de connexion établie lors de la connexion au serveur LDAP lors de la connexion. Cela a entraîné l'exposition des utilisateurs aux sessions des autres utilisateurs et aux résultats très déroutants, lorsque vous essayez d'analyser ce qui s'est passé lorsque le serveur a été mis à genoux, à peine capable de terminer une transaction, toutes les quelques secondes.
En fin de compte, vous ou quelqu'un devrez probablement boucler et analyser le code pour les erreurs comme celui que je viens de mentionner. Et une discussion ouverte entre les départements, comme celle qui s'est produite, lorsque nous avons dévoilé le problème décrit ci-dessus, est très utile. Mais ces outils sont la meilleure solution pour tester du code multi-thread. JMeter est open source. SilkPerformer et LoadRunner sont propriétaires. Si vous voulez vraiment savoir si votre application est sécurisée pour les threads, c'est comme ça que les grands garçons le font. J'ai fait cela pour de très grandes entreprises de façon professionnelle, donc je ne pense pas. Je parle d'expérience personnelle.
Une mise en garde: il faut du temps pour comprendre ces outils. Il ne s'agira pas simplement d'installer le logiciel et de lancer l'interface graphique, sauf si vous avez déjà été exposé à une programmation multi-thread. J'ai essayé d'identifier les 3 catégories critiques de domaines à comprendre (formulaires, données de session et cookies), dans l'espoir qu'au moins commencer par comprendre ces sujets vous aidera à vous concentrer sur des résultats rapides, au lieu d'avoir à lire le documentation complète.
la source
La concurrence est une interaction complexe entre le modèle de mémoire, le matériel, les caches et notre code. Dans le cas de Java, au moins ces tests ont été en partie traités principalement par jcstress . Les créateurs de cette bibliothèque sont connus pour être les auteurs de nombreuses fonctionnalités de concurrence JVM, GC et Java.
Mais même cette bibliothèque a besoin d'une bonne connaissance de la spécification Java Memory Model pour que nous sachions exactement ce que nous testons. Mais je pense que cet effort se concentre sur les mircobenchmarks. Pas d'énormes applications commerciales.
la source
Il y a un article sur le sujet, utilisant Rust comme langue dans l'exemple de code:
https://medium.com/@polyglot_factotum/rust-concurrency-five-easy-pieces-871f1c62906a
En résumé, l'astuce consiste à écrire votre logique concurrente afin qu'elle soit robuste au non-déterminisme impliqué avec plusieurs threads d'exécution, en utilisant des outils comme les canaux et les condvars.
Ensuite, si c'est ainsi que vous avez structuré vos "composants", la façon la plus simple de les tester est d'utiliser des canaux pour leur envoyer des messages, puis de bloquer sur d'autres canaux pour affirmer que le composant envoie certains messages attendus.
L'article lié est entièrement écrit à l'aide de tests unitaires.
la source
Si vous testez un nouveau thread simple (exécutable) .run () Vous pouvez vous moquer de Thread pour exécuter séquentiellement l'exécutable.
Par exemple, si le code de l'objet testé appelle un nouveau thread comme celui-ci
Ensuite, se moquer de nouveaux threads et exécuter séquentiellement l'argument exécutable peut aider
la source
(si possible) n'utilisez pas de threads, utilisez des acteurs / objets actifs. Facile à tester.
la source
Vous pouvez utiliser EasyMock.makeThreadSafe pour rendre le threadsafe d'instance de test
la source