Pourquoi les frameworks xUnit ne permettent-ils pas aux tests de s'exécuter en parallèle?

15

Connaissez-vous un framework xUnit permettant d'exécuter des tests en parallèle, d'utiliser plusieurs cœurs dans la machine d'aujourd'hui?

Si aucun (ou si peu) d'entre eux le fait, il y a peut-être une raison ... Est-ce que les tests sont généralement si rapides que les gens ne ressentent tout simplement pas le besoin de les paralyser?

Y a-t-il quelque chose de plus profond qui empêche de distribuer (au moins certains) des tests sur plusieurs threads?

Xavier Nodet
la source
Les tests unitaires sont définitivement lents. Même si chaque test en lui-même est rapide, ils s'accumuleraient car les gens ont littéralement des millions de cas de test.
Pacerier

Réponses:

6

NUnit 2.5 fourni pNUnit qui permet l'exécution de tests en parallèle.

Cette version inclut pNUnit, un exécuteur NUnit étendu pour les tests parallèles distribués. Le programme pNUnit a été développé par Codice Software pour être utilisé dans les tests du Plastic SCM et a été apporté à NUnit. Pour plus d'informations sur l'utilisation de pNUnit, consultez le site pNUnit.

Le côté a JUnit parallèle-junit ainsi que amino .

Aaron McIver
la source
Donc, la seule raison pour laquelle les autres cadres seraient «pas encore mis en œuvre»?
Xavier Nodet
1
@Xavier Oui; c'est une déclaration juste.
Aaron McIver
10

Pour répondre à la deuxième partie de votre question: y a-t-il quelque chose de plus profond qui empêche de distribuer (au moins certains) des tests sur plusieurs threads?

Une grande partie du code ne fonctionne que lorsqu'il est exécuté sur un seul thread. Il est trivial de produire accidentellement des conflits de ressources et des blocages lors de l'écriture de programmes en supposant qu'ils seront exécutés sur un seul thread. Et cela fonctionne très bien car la plupart des programmes fonctionnent en fait à un seul thread. Le parallélisme est obtenu en exécutant plusieurs copies ou différents programmes en même temps (les scripts Web étant un exemple courant - de nombreux utilisateurs accédant à une seule page signifient de nombreuses copies des scripts de cette page s'exécutant en même temps).

Imaginez une simple classe "log to file". Lorsque vous créez une instance, il ouvre le fichier pour l'écriture, lorsque vous libérez l'instance, il ferme le fichier. Ainsi, le premier test crée une instance et commence à exécuter un test. Le deuxième test fait la même chose dans un deuxième thread. Et échoue, car la deuxième instance ne peut pas accéder en écriture au fichier. Mais s'il était exécuté un à la fois, tous les tests réussiraient.

Tout cela peut être codé autour, et l'exemple simple pourrait être modifié pour fonctionner. Mais cela n'est probablement pas nécessaire pour le programme d'origine . Devoir écrire du code thread-safe juste pour pouvoir exécuter des tests unitaires est déraisonnable pour beaucoup de gens. Les tests unitaires multithread devraient donc rester un supplément facultatif.


la source
+1 Ceci devrait être la réponse exceptée car elle répond en fait au pourquoi.
Oliver Weiler
4

Si les tests doivent configurer et interroger une base de données, les tests s'exécutant en parallèle interfèrent les uns avec les autres, sauf s'il existe une base de données distincte pour chaque test exécuté en parallèle.

Clint Miller
la source
Ce n'est pas à la plate-forme de test (xUnit) de se soucier; c'est un détail d'implémentation.
Aaron McIver
Et tous les tests écrits dans un framework de tests unitaires ne sont pas des tests unitaires, tout comme celui qui accède à la base de données n'est pas vraiment un test unitaire, plus comme un test d'intégration.
c_maker
Ce n'est pas parce qu'un test touche une base de données qu'il s'agit d'un test d'intégration. Une méthode qui s'exécute partiellement en C # et partiellement dans une base de données sproc par exemple est toujours conceptuellement un test unitaire, tant qu'aucune préconfiguration n'est attendue (c'est-à-dire que le schéma de données est présent, mais aucune donnée n'est présente). Ces tests peuvent créer des données pour une exécution individuelle, mais doivent être réinitialisés à un état vide une fois terminé). C'est probablement une opinion controversée, mais de tels tests ne peuvent pas être considérés comme des tests d'intégration, car ils sont explicitement des tests de configuration zéro et de déploiement zéro qui testent de petites unités de code.
Triynko
2

Bien que JUnit en soi ne le permette pas (je ne connais pas intimement ses dernières versions), Maven avec son plugin Surefire a une option pour exécuter des tests en parallèle. Je ne l'ai pas encore essayé.

Je ne suis pas fortement pressé d'étudier cette option, car nous n'avons qu'un peu plus d'un millier de tests et ils fonctionnent assez rapidement. Cependant, je sais que certains des montages de test ont des dépendances implicites entre (nous avons trouvé certaines de ces dépendances lorsque certains tests se sont interrompus de manière inattendue dans le passé), donc il y a un risque que la parallélisation des tests fasse échouer certains d'entre eux de manière imprévisible. Vous pouvez dire que c'est bien car cela rend le problème explicite. Cependant, nous avons affaire à un système hérité, et nous avons de nombreux problèmes plus importants à régler - le temps est une ressource rare (comme d'habitude).

Péter Török
la source
0

Le codage multithread n'est pas anodin. Même lorsqu'ils sont effectués par des personnes qui savent ce qu'ils font, des bogues liés au timing peuvent survenir. Ils sont difficiles à réparer. Ayant traité le seul problème que plusieurs milliers de bogues peuvent produire, je préférerais ne pas les avoir dans mon framework de test. Le premier correctif que j'ai obtenu a semblé fonctionner, mais lors de tests supplémentaires, il a été constaté qu'il venait de devenir un bogue sur des dizaines de milliers.

Les techniques de multi-threading sur multi-processeurs s'améliorent avec l'avènement des PC multi-processeurs. Cependant, il faudra du temps avant qu'ils ne soient largement utilisés.

Certaines suites de tests ont des dépendances entre les tests qui n'ont pas besoin d'être explicitement déclarées lorsque les tests sont exécutés dans un seul flux. Cependant, sur un moteur multi-vapeur, ils devraient être explicitement indiqués. (Où de telles dépendances devraient exister est une question différente.)

D'un autre point de vue, certaines choses n'ont tout simplement pas besoin d'être exécutées en parallèle. Si le processus s'exécute suffisamment rapidement, il peut être préférable de concentrer les efforts sur d'autres choses que la mise en œuvre du multithread.

BillThor
la source
0

MBUnit est capable d'exécuter des tests en parallèle simplement en spécifiant certains attributs de niveau d'assemblage.

[assembly: DegreeOfParallelism(6)]
[assembly: Parallelizable(TestScope.All)]

J'utilise ce projet pour exécuter des tests de sélénium en parallèle avec succès depuis un certain temps. Malheureusement, le projet n'est plus très vivant.

xUnit 2.0 devrait également prendre en charge les tests unitaires parallèles, mais je ne l'ai pas encore essayé.

Ivo Grootjes
la source