783 votes

Comment dois-je test unitaire fileté code ?

Chaud sur les talons de mes précédents tests unitaires liés à la question, voici un autre toughie:

J'ai donc à présent évité le cauchemar qui est des tests multi-threaded code car il semble juste comme trop d'un champ de mines. Je voudrais vous demander combien de personnes sont passées sur les tests de code qui s'appuie sur des fils de la bonne exécution, ou tout simplement comment les gens qui ont fait le test de ces types de problèmes qui ne se montre que lorsque deux threads d'interagir d'une manière particulière?

Cela semble vraiment comme un problème clé pour les programmeurs d'aujourd'hui, il serait utile de mettre en commun nos connaissances sur ce point à mon humble avis.

270voto

Will Points 76760

Regardez, il n'y a pas de moyen facile de le faire. Je suis en train de travailler sur un projet qui est par nature multithread. Événements à venir dans le système d'exploitation et je dois les traiter simultanément.

La façon la plus simple de traiter avec les tests complexes, multithhreaded le code de l'application est la suivante: Si c'est trop complexe pour tester, vous le faites mal. Si vous avez une seule instance qui a plusieurs threads en agissant sur elle, et vous ne pouvez pas tester les situations où ces threads étape tous les uns les autres, votre conception doit être refait. De son à la fois aussi simple et aussi complexe que cela.

Il existe de nombreuses façons de programme pour le multithreading, qui évite les threads en cours d'exécution à travers les instances en même temps. Le plus simple est de faire tous vos objets immuables. Bien sûr, ce n'est généralement pas possible. Donc, vous devez identifier les endroits dans votre conception où les threads interract avec la même instance et de réduire le nombre de ces lieux. En faisant cela, vous isoler quelques classes où le multithreading en fait se produit, réduire la complexité globale de test de votre système.

Mais vous devez comprendre que même en faisant cela, vous ne pouvez toujours pas de test de chaque situation où les deux fils à l'étape uns sur les autres. Pour ce faire, vous devez exécuter deux threads simultanément dans le même test, puis de contrôler exactement ce que les lignes qu'ils sont en cours d'exécution à un moment donné. Le meilleur que vous pouvez faire est de simuler cette situation. Mais cela peut vous obliger à code spécifiquement pour les tests, et c'est au mieux un demi-pas vers une vraie solution.

Probablement la meilleure façon de tester le code pour les problèmes de threading est par le biais de l'analyse statique du code. Si votre fileté code ne suit pas un ensemble fini de thread-safe modèles, alors vous pourriez avoir un problème. Je crois que l'Analyse de Code dans VS ne contenir une certaine connaissance de l'enfilage, mais probablement pas beaucoup.

Regardez, comme les choses se présentent actuellement (et probablement restera pendant un bon moment à venir), le meilleur moyen pour tester les applications multithread est de réduire la complexité de threaded code autant que possible. Minimiser les zones où les threads interagir, test du mieux que possible, et l'utilisation de l'analyse de code pour identifier les zones de danger.

110voto

Theo Lenndorff Points 2512

Il a été un moment lorsque cette question a été posté, mais c'est toujours pas répondu ...

kleolb02's réponse est bonne. Je vais essayer d'aller dans plus de détails.

Il y a un moyen, que je pratique pour le code C#. Pour les tests d'unité, vous devriez être en mesure de programmer reproductible tests, ce qui est le plus grand défi dans code multithread. Donc, ma réponse vise à forcer le code asynchrone dans un harnais de test, qui fonctionne de manière synchrone.

C'est une idée de Gérard Meszardos du livre "xUnit des Modèles de Test" et est appelé "Objet Humbles" (p. 695): Vous devez séparer la logique de base de code et de tout ce qui sent le code asynchrone les uns des autres. Ce qui aboutirait à une classe de la logique de base, qui fonctionne de manière synchrone.

Cela vous met dans la position de tester la logique de base de code dans un synchrones . Vous avez un contrôle absolu sur le calendrier des appels que vous faites sur la base de la logique et donc peut les rendre reproductibles tests. Et c'est votre gain de la séparation de la logique de base et en logique asynchrone.

Cette logique de base doit être enroulé autour de par une autre classe, qui est responsable de la réception des appels à la base de la logique asynchrone et les délégués de ces appels à la base de la logique. Le code de Production aura uniquement accès à la base de la logique par l'intermédiaire de cette classe. Parce que cette classe ne doit déléguer des appels, c'est un "bête" de la classe sans trop de logique. Donc vous pouvez garder vos tests unitaires pour ce asychronous de la classe ouvrière à un minimum.

Tout ce qui précède que (tests d'interaction entre les classes) sont la composante des tests. Dans ce cas également, vous devriez être en mesure d'avoir un contrôle absolu sur le timing, si vous vous en tenez à la "Humble Objet" modèle.

74voto

David Joyner Points 4994

Difficile en effet! Dans mon (C++) de l'unité de tests, j'ai cassé celle-ci en plusieurs catégories, le long de la lignes de la simultanéité modèle utilisé:

  1. Les tests unitaires pour les classes qui fonctionnent dans un seul thread et ne sont pas thread courant -- facile, test comme d'habitude.

  2. Des tests unitaires pour les objets de surveillance (ceux qui exécutent des méthodes synchronisées dans les appelants " fil de contrôle) qui exposent un synchronisé API publique -- instancier plusieurs se moquer de threads que l'exercice de l'API. Construire des scénarios que l'exercice de la situation interne de l'objet passif. Inclure une plus longue épreuve de course à pied que, fondamentalement, bat le diable hors de lui à partir de plusieurs threads pour une longue période de temps. Ce n'est pas scientifique, je sais, mais il ne le mettre en confiance.

  3. Les tests unitaires pour les objets Actifs (ceux qui contiennent leur propre thread, threads ou de contrôle) - semblable au n ° 2 ci-dessus avec des variations en fonction de la classe de conception. Les API peuvent être bloquant ou non bloquant, les appelants peuvent obtenir des contrats à terme, les données peuvent en arriver à des files d'attente ou un besoin d'être retiré. Il existe de nombreuses combinaisons possibles; boîte blanche loin. Nécessite encore plusieurs se moquer de threads pour faire des appels à l'objet sous test.

En aparté:

En interne, la formation des développeurs que je fais, j'enseigne les Piliers de la Simultanéité et de ces deux modèles comme le principal cadre pour la réflexion et à la décomposition des problèmes de concurrence d'accès. Il y a évidemment des notions plus avancées, mais j'ai trouvé que cet ensemble de notions de base aide à garder les ingénieurs de la soupe. Elle conduit également à un code qui est le plus unité vérifiable, comme décrit ci-dessus.

26voto

ollifant Points 3325

J’ai aussi eu des problèmes graves, test de code multi-threaded. Ensuite, j’ai trouvé une solution vraiment cool dans « xUnit Test Patterns » par Gerard Meszaros. Le modèle qu’il décrit est appelé objet Humble.

Fondamentalement, il décrit comment vous pouvez extraire la logique dans un composant simple de test distinct qui est dissociée de son environnement. Après que vous avez testé cette logique, vous pouvez tester le comportement complexe (multi - threading, asynchrone l’exécution, etc....)

13voto

Yrlec Points 1136

Pour .NET, vous pouvez consulter sur le projet de recherche de Microsoft Chess

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X