Warum lassen xUnit-Frameworks nicht zu, dass Tests parallel ausgeführt werden?

15

Kennen Sie ein xUnit-Framework, mit dem Tests parallel ausgeführt werden können, um auf dem heutigen Computer mehrere Kerne zu verwenden?

Wenn keiner (oder so wenige) von ihnen dies tut, gibt es vielleicht einen Grund ... Sind Tests normalerweise so schnell, dass die Leute einfach nicht das Bedürfnis haben, sie zu paralellieren?

Gibt es etwas Tieferes, das die Verteilung (zumindest einiger) Tests auf mehrere Threads ausschließt?

Xavier Nodet
quelle
Unit-Tests sind definitiv langsam. Selbst wenn jeder Test für sich schnell ist, würden sie sich summieren, da die Leute buchstäblich Millionen von Testfällen haben.
Pacerier

Antworten:

6

NUnit 2.5 gebündeltes pNUnit, das die parallele Ausführung von Tests ermöglicht.

Diese Version enthält pNUnit, einen erweiterten NUnit-Runner für verteilte parallele Tests. Das pNUnit-Programm wurde von Codice Software zum Testen des Plastic SCM entwickelt und zu NUnit beigetragen. Weitere Informationen zur Verwendung von pNUnit finden Sie auf der pNUnit-Site.

Die JUnit-Seite hat sowohl Parallel-Junit als auch Amino .

Aaron McIver
quelle
Der einzige Grund für die anderen Frameworks wäre also "noch nicht implementiert"?
Xavier Nodet
1
@ Xavier Ja; Das ist eine faire Aussage.
Aaron McIver
10

Um den zweiten Teil Ihrer Frage zu beantworten: Gibt es etwas Tieferes, das die Verteilung (zumindest einiger) Tests auf mehrere Threads ausschließt?

Ein Großteil des Codes funktioniert nur, wenn Single-Threaded ausgeführt wird. Es ist trivial, versehentlich Ressourcenkonflikte und Deadlocks zu erzeugen, wenn Programme unter der Annahme geschrieben werden, dass sie mit einem einzigen Thread ausgeführt werden. Und das funktioniert gut, da die meisten Programme tatsächlich Single-Threaded ausführen. Parallelität wird erreicht, indem mehrere Kopien oder verschiedene Programme gleichzeitig ausgeführt werden (Web-Skripte sind ein häufiges Beispiel - viele Benutzer, die auf eine einzelne Seite zugreifen, bedeuten, dass viele Kopien der Skripte für diese Seite gleichzeitig ausgeführt werden).

Stellen Sie sich eine einfache "Log to File" -Klasse vor. Wenn Sie eine Instanz erstellen, wird die Datei zum Schreiben geöffnet. Wenn Sie die Instanz freigeben, wird die Datei geschlossen. Der erste Test erstellt also eine Instanz und startet die Ausführung eines Tests. Der zweite Test macht dasselbe in einem zweiten Thread. Und schlägt fehl, weil die zweite Instanz keinen Schreibzugriff auf die Datei erhält. Aber wenn alle Tests einzeln ausgeführt würden, wären sie erfolgreich.

All dies kann programmiert werden, und das einfache Beispiel könnte angepasst werden, um zu funktionieren. Dies ist jedoch für das ursprüngliche Programm wahrscheinlich nicht erforderlich . Es ist für viele Menschen unvernünftig, thread-sicheren Code zu schreiben, um Unit-Tests durchführen zu können. Daher sollten Multithread-Unit-Tests ein optionales Extra bleiben.


quelle
+1 Dies sollte die Ausnahmeantwort sein, da es tatsächlich das Warum beantwortet.
Oliver Weiler
4

Wenn Tests eine Datenbank einrichten und abfragen müssen, stören sich parallel ausgeführte Tests gegenseitig, es sei denn, für jeden parallel ausgeführten Test ist eine separate Datenbank vorhanden.

Clint Miller
quelle
Dies ist nicht für die Testplattform (xUnit) von Belang. Das ist ein Implementierungsdetail.
Aaron McIver
Und nicht alle Tests, die in einem Unit-Test-Framework geschrieben wurden, sind Unit-Tests, so wie derjenige, der auf die Datenbank zugreift, kein Unit-Test ist, sondern eher ein Integrationstest.
c_maker
Nur weil ein Test eine Datenbank berührt, heißt das noch lange nicht, dass es sich um einen Integrationstest handelt. Eine Methode, die zum Beispiel teilweise in C # und teilweise in einem Datenbank-Sproc ausgeführt wird, ist konzeptionell immer noch ein Komponententest, solange keine Vorkonfiguration erwartet wird (dh das Datenschema ist vorhanden, aber keine Daten sind vorhanden). Solche Tests können Daten für einen einzelnen Lauf erzeugen, sollten jedoch nach Abschluss auf einen leeren Zustand zurückgesetzt werden. Dies ist wahrscheinlich eine kontroverse Meinung, aber solche Tests können nicht als Integrationstests betrachtet werden, da sie explizit Zero-Config- und Zero-Deploy-Tests zum Testen kleiner Codeeinheiten sind.
Triynko
2

Während JUnit per se dies möglicherweise nicht zulässt (mit den neuesten Versionen bin ich jedoch nicht vertraut), bietet Maven mit seinem Surefire-Plugin die Möglichkeit, Tests parallel auszuführen. Ich habe es aber noch nicht ausprobiert.

Ich bin nicht stark genug, um diese Option zu untersuchen, da wir nur etwas mehr als tausend Tests haben und diese schnell genug laufen. Ich weiß jedoch, dass einige der Test-Fixtures implizite Abhängigkeiten aufweisen (wir haben einige solche Abhängigkeiten festgestellt, als einige Tests in der Vergangenheit unerwartet abgebrochen wurden), sodass das Risiko besteht, dass bei Parallelisierung der Tests einige von ihnen unvorhersehbar ausfallen. Sie können sagen, dass dies in Ordnung ist, da es das Problem explizit macht. Wir haben es jedoch mit einem Legacy-System zu tun, und wir haben viele wichtigere Probleme zu lösen - Zeit ist (wie üblich) eine knappe Ressource.

Péter Török
quelle
0

Multithread-Codierung ist nicht trivial. Selbst wenn dies von Leuten gemacht wird, die wissen, was sie tun, können zeitabhängige Fehler auftreten. Sie sind schwer zu reparieren. Nachdem ich mich mit den ein paar tausend Fällen befasst habe, die Multi-Treading-Fehler erzeugen können, würde ich es vorziehen, sie nicht in meinem Test-Framework zu haben. Das erste Update, das ich bekam, schien zu funktionieren, aber bei weiteren Tests stellte sich heraus, dass es sich nur um einen Fehler von Zehntausenden handelte.

Die Techniken für Multi-Threading auf Multi-Prozessoren werden mit dem Aufkommen von Multi-Prozessor-PCs immer besser. Es wird jedoch einige Zeit dauern, bis sie weit verbreitet sind.

Einige Testsuiten weisen Abhängigkeiten zwischen Tests auf, die nicht explizit angegeben werden müssen, wenn die Tests in einem einzelnen Stream ausgeführt werden. Bei einer Mehrdampfmaschine müssten sie jedoch explizit angegeben werden. (Wo solche Abhängigkeiten bestehen sollten, ist eine andere Frage.)

Unter einem anderen Gesichtspunkt müssen einige Dinge einfach nicht parallel ausgeführt werden. Wenn der Prozess ausreichend schnell ausgeführt wird, ist es möglicherweise besser, sich auf andere Dinge als die Implementierung von Multithreading zu konzentrieren.

BillThor
quelle
0

MBUnit kann Tests einfach durch Angabe einiger Attribute auf Assembly-Ebene parallel ausführen.

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

Ich benutze dieses Projekt seit einiger Zeit sehr erfolgreich, um parallel Selentests durchzuführen. Leider ist das Projekt nicht mehr sehr lebendig.

xUnit 2.0 sollte auch das Testen paralleler Einheiten unterstützen, ich habe es jedoch noch nicht ausprobiert.

Ivo Grootjes
quelle