Wie kann ich NUnit-Tests parallel ausführen?

83

Ich habe eine große Testsuite (~ 10 Sekunden pro Test), die mit NUnit geschrieben wurde. Ich möchte die Tatsache nutzen, dass meine Maschinen alle mehrere Kernboxen sind. Im Idealfall kann ein Test unabhängig von anderen Tests pro Kern ausgeführt werden.

Es gibt PNUnit, aber es wurde zum Testen auf Threading-Synchronisationsprobleme und ähnliches entwickelt, und ich habe keinen offensichtlichen Weg gesehen, dies zu erreichen.

Gibt es einen Schalter / ein Tool / eine Option, mit der ich die Tests parallel ausführen kann?

Billy ONeal
quelle
Auch ich würde gerne mehr darüber wissen. @ Billy ONeal bitte poste eine Antwort, wenn du eine findest.
PK
Sie sagen zehn Sekunden pro Test und idealerweise einen Test pro Kern. Sind die Tests CPU-intensiv? Andernfalls sollte es möglich sein, dass viel mehr gleichzeitig ausgeführt werden.
Mattias Nilsson
@ Mattias: Ja, die Tests sind CPU-intensiv.
Billy ONeal

Antworten:

52

Wenn Sie NUnit-Tests parallel ausführen möchten, gibt es mindestens zwei Optionen:

  • NCrunch bietet es sofort an (ohne etwas zu ändern, ist aber ein kommerzielles Produkt)
  • NUnit 3 bietet ein parallelisierbares Attribut, mit dem angegeben werden kann, welche Tests parallel ausgeführt werden können
David_001
quelle
Diese Antwort scheint angesichts der Frage falsch zu sein, eher ein guter Vorschlag als eine wahre Antwort. Meiner Meinung nach benötigt NCrunch Ihre Upvotes und sollte die beste Antwort sein, da es (NUnit) Tests gleichzeitig innerhalb desselben oder mehrerer Prozesse und auf einem oder mehreren Computern ausführen kann und dies von VS oder von einem Build-Server aus tun wird.
Chillitom
2
@chillitom NCrunch wurde veröffentlicht, nachdem diese Frage beantwortet wurde, und ist eine gute Wahl (da dies sofort funktionieren sollte, obwohl es für einige zu teuer ist). Weitere Optionen in der Zukunft könnten NUnit 3 sein, das möglicherweise die parallele Ausführung von Tests ermöglicht (laut github.com/nunit/dev/wiki/Roadmap ).
David_001
3
Obwohl dies die beste Antwort ist, ist sie nicht mehr so ​​korrekt wie früher. Nunit 3.0 wurde Ende 2015 veröffentlicht und verfügt nun über ein parallelisierbares Attribut. Ref: github.com/nunit/nunit/wiki/Parallelizable-Attribute
pb.
36

NUnit Version 3 unterstützt das parallele Ausführen von Tests:

Durch Hinzufügen des Attributs zu einer Klasse: [Parallelizable(ParallelScope.Self)]werden Ihre Tests parallel ausgeführt.

• ParallelScope.None gibt an, dass der Test möglicherweise nicht parallel zu anderen Tests ausgeführt wird.

• ParallelScope.Self gibt an, dass der Test selbst möglicherweise parallel zu anderen Tests ausgeführt wird.

• ParallelScope.Children gibt an, dass die Nachkommen des Tests möglicherweise parallel zueinander ausgeführt werden.

• ParallelScope.Fixtures gibt an, dass Fixtures parallel zueinander betrieben werden können.

NUnit Framework-Parallel-Test-Ausführung

Peter
quelle
10

Wenn Ihr Projekt mehrere Test-DLLs enthält, können Sie diese mit diesem MSBuild-Skript parallel ausführen. Natürlich müssen Sie die Pfade an Ihr Projektlayout anpassen.

Um mit 8 Kernen zu laufen, laufen Sie mit: c:\proj> msbuild /m:8 RunTests.xml

RunTests.xml

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="RunTestsInParallel" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
    <Nunit Condition=" '$(Nunit)' == '' ">$(MSBuildProjectDirectory)\..\tools\nunit-console-x86.exe</Nunit>
  </PropertyGroup>

  <!-- see http://mikefourie.wordpress.com/2010/12/04/running-targets-in-parallel-in-msbuild/ -->

  <Target Name="RunTestsInParallel">
    <ItemGroup> 
      <TestDlls Include="..\bin\Tests\$(Configuration)\*.Tests.dll" />
    </ItemGroup>

    <ItemGroup> 
      <TempProjects Include="$(MSBuildProjectFile)" > 
        <Properties>TestDllFile=%(TestDlls.FullPath)</Properties> 
      </TempProjects> 
    </ItemGroup> 

    <MSBuild Projects="@(TempProjects)" BuildInParallel="true" Targets="RunOneTestDll" /> 
  </Target>

  <Target Name="RunOneTestDll"> 
    <Message Text="$(TestDllFile)" />
    <Exec Command="$(Nunit) /exclude=Integration $(TestDllFile)  /labels /xml:$(TestDllFile).results.xml"
      WorkingDirectory="$(MSBuildProjectDirectory)\..\bin\Tests\$(Configuration)" /> 
  </Target>

</Project>

Update Wenn ich diese Frage jetzt beantworten würde, würde ich NCrunch und sein Befehlszeilentestlauf-Tool für maximale Testlaufleistung wärmstens empfehlen . Es gibt nichts Vergleichbares und es wird gleichzeitig Ihren Code-Test-Debug-Zyklus revolutionieren.

chillitom
quelle
1
Dies hat mir geholfen, die Laufzeit von Unit-Tests von 3 Minuten auf 2 Minuten zu reduzieren. Ich habe auf einer 2-Core-CPU getestet.
Dmitrii Lobanov
4

In diesem Artikel wird erwähnt, dass das Poster zur Beschleunigung von Tests mehrere Instanzen von NUnit mit Befehlsparametern ausführt, die angeben, welche Tests jede Instanz ausführen soll.

Freihandelsabkommen:

Ich bin auf ein seltsames Problem gestoßen.

Wir verwenden nunit-console, um Tests auf unserem Continuous Integration Server durchzuführen. Kürzlich sind wir von Nunit 2.4.8 auf 2.5.5 und von .Net 3.5 auf 4.0 umgestiegen. Um die Testausführung zu beschleunigen, führen wir mehrere Instanzen von Nunit parallel mit verschiedenen Befehlszeilenargumenten aus

  • Wir haben zwei Kopien unserer Testbaugruppen und der Nunit-Binärdateien in Ordner A und B.
  • In Ordner A führen wir aus

nunit-console-x86.exe Model.dll Test.dll / exclude: MyCategory /xml=TestResults.xml /framework=net-4.0 / noshadow

  • In Ordner B führen wir aus

nunit-console-x86.exe Model.dll Test.dll / include: MyCategory /xml=TestResults.xml /framework=net-4.0 / noshadow

Wenn wir die Befehle nacheinander ausführen, werden beide erfolgreich ausgeführt. Aber wenn wir sie parallel ausführen, ist nur einer erfolgreich. Soweit ich das beurteilen kann, ist es derjenige, der zuerst die Testvorrichtungen lädt. Der andere schlägt mit der Meldung "Gerät kann nicht gefunden werden" fehl.

Ist dieses Problem bereits bekannt? Ich konnte nichts in der Fehlerliste auf dem Launchpad finden. Übrigens: Auf unserem Server wird Windows Server 2008 64-Bit ausgeführt. Ich könnte das Problem auch unter Windows 7 64-Bit reproduzieren.

Angenommen, dieser Fehler ist behoben oder Sie führen nicht die neueren Versionen der genannten Software aus, sollten Sie in der Lage sein, deren Technik zu replizieren.

Aktualisieren

TeamCity sieht aus wie ein Tool, mit dem Sie NUnit-Tests automatisch ausführen können. Sie haben einen hier diskutierten NUnit-Launcher, mit dem mehrere NUnit-Instanzen gestartet werden können. In diesem Blogbeitrag wird die Zusammenführung mehrerer NUnit-XML-Ergebnisse zu einer einzigen Ergebnisdatei erläutert.

Theoretisch könnte TeamCity also automatisch mehrere NUnit-Tests starten, je nachdem, wie Sie die Arbeitslast aufteilen und die Ergebnisse dann für die Verarbeitung nach dem Test in einer einzigen Datei zusammenführen möchten.

Ist das automatisiert genug für Ihre Bedürfnisse?

kniemczak
quelle
Dies ist die gleiche Idee, die bereits über Kategorien veröffentlicht wurde ... Ich möchte hier keine einigermaßen gleichen Laufzeiten zwischen den Instanzen beibehalten müssen. Ich würde lieber meinen eigenen NUnit-Läufer schreiben, bevor ich das mache.
Billy ONeal
Soweit ich weiß, unterstützt NUnit dies nicht ohne eine Problemumgehung wie das Ausführen mehrerer Instanzen. Wenn Sie möchten, können Sie ein Tool erstellen, das die Tests in N Sätze aufteilt und N Instanzen von NUnit automatisch ausführt, wobei N die Anzahl der Prozessoren / Kerne ist, über die Sie verfügen. Dies wäre die einzige Möglichkeit, eine Art automatisierten parallelen Test durchzuführen, den ich mir mit NUnit vorstellen kann.
Kniemczak
Ich habe ein Update hinzugefügt, in dem das TeamCity-Tool für die kontinuierliche Integration erläutert wird, und einige Beiträge zur Verwendung dieses Tools zur Lösung Ihrer Automatisierungsanforderungen hinzugefügt.
Kniemczak
3

Nur weil PNUnit die Synchronisation innerhalb des Testcodes durchführen kann, bedeutet dies nicht, dass Sie diesen Aspekt tatsächlich verwenden müssen. Soweit ich sehen kann, hindert Sie nichts daran, nur ein Set zu spawnen und den Rest zu ignorieren, bis Sie es brauchen.

Übrigens habe ich nicht die Zeit, alle Quellen zu lesen, war aber neugierig, die Barrier-Klasse zu überprüfen, und es ist ein sehr einfacher Sperrzähler. Es wartet nur, bis N Threads eintreten, und sendet dann den Impuls, damit alle gleichzeitig weiterlaufen. Das ist alles, was es zu tun gibt - wenn Sie es nicht berühren, wird es Sie nicht beißen.

Könnte für eine normale Thread-Entwicklung etwas kontraintuitiv sein (Sperren werden normalerweise verwendet, um den Zugriff zu serialisieren - 1 zu 1), aber es ist eine ziemlich temperamentvolle Ablenkung :-)

ZXX
quelle
3

Sie können jetzt NCrunch verwenden, um Ihre Komponententests zu parallelisieren, und Sie können sogar konfigurieren, wie viele Kerne von NCrunch und wie viele von Visual Studio verwendet werden sollen.

Außerdem bekommst du als Bonus kontinuierliche Tests :)

Rickard
quelle
3
NCrunch ist großartig, wenn Sie es in Visual Studio verwenden, aber es hilft nicht, wenn Sie versuchen, Ihre Tests auf Ihrem Build-Server zu parallelisieren.
Paccc
3
NCrunch verfügt jetzt über ein Befehlszeilentool, das auf Build-Servern sehr gut funktioniert.
Chillitom
3

Alternativ zum Hinzufügen des Attributs Parallelizable zu jeder Testklasse:

Fügen Sie dies der AssemblyInfo.cs-Klasse des Testprojekts für nunit3 oder höher hinzu:

// Make all tests in the test assembly run in parallel
[assembly: Parallelizable(ParallelScope.Fixtures)]
Tom Redfern
quelle
2

Es wäre ein bisschen hacken, aber Sie könnten die Unit-Tests in eine Reihe von Kategorien aufteilen . Starten Sie dann für jede Kategorie eine neue Instanz von NUnit.

Bearbeiten: Es sieht so aus, als hätten sie der Konsolen-App eine / process-Option hinzugefügt. In der Befehlszeilenhilfe wird angegeben, dass dies das "Prozessmodell für Tests: Einzel, Separat, Mehrfach" ist. Der Testläufer scheint diese Funktion ebenfalls zu haben.

Bearbeiten 2: Leider werden die Agenten nacheinander ausgeführt, obwohl für jede Assembly separate Prozesse erstellt werden. Die Option zur Prozessisolierung (/ process über die Befehlszeile) führt die Agenten nacheinander aus.

Pedro
quelle
2

Da das Projekt hier nicht erwähnt wurde, möchte ich NUnit.Multicore ansprechen . Ich habe das Projekt nicht selbst ausprobiert, aber es scheint einen interessanten Ansatz für das parallele Testproblem mit NUnit zu haben.

Tronda
quelle
2

Sie können mein kleines Tool TBox oder Console Parallel Runner oder sogar ein Plugin ausprobieren, um verteilte Berechnungen durchzuführen, mit denen auch Unit-Tests auf dem SkyNet- PC- Set ausgeführt werden können

TBox wurde entwickelt, um die Arbeit mit großen Lösungen zu vereinfachen, die viele Projekte enthalten. Es unterstützt viele Plugins und eines davon bietet die Möglichkeit, NUnit-Tests parallel auszuführen. Dieses Plugin erfordert keine Änderungen an Ihren vorhandenen Tests.

Auch unterstützt es:

  • Klonen des Ordners mit Unit Test (wenn Ihre Tests lokale Daten ändern),

  • Synchronisierungen der Tests (zum Beispiel, wenn Ihre Tests auf testfixtureteardown alle Entwicklungsserver oder Chromerunner für qunit beenden)

  • x86-Modus und Administratorrechte zum Ausführen von Tests

  • Stapellauf - Sie können Tests für viele Baugruppen parallel ausführen

  • Selbst für Single-Thread-Runs funktioniert es schneller als Standard-Nunit-Runner, wenn Sie viele kleine Tests haben.

Dieses Tool unterstützt auch den Befehlszeilentest-Runner (für den parallelen Lauf) und kann mit kontinuierlicher Integration verwendet werden.

Alex H.
quelle
Wenn Sie mit diesem Produkt verbunden sind, geben Sie dies bitte an. Sie haben mehrere Dinge gepostet, die darauf hinweisen.
Brad Larson
Klar, TBox - ist mein eigenes Werkzeug. Ich habe es allein in meiner Freizeit geschrieben. Wenn es hier schlecht ist, über kostenlose Tools zu sprechen, werde ich diese Antwort entfernen, es ist kein Problem :)
Alex H
Wir möchten nur, dass die Menschen sich über die Produkte im Klaren sind, an denen sie beteiligt sind. Wenn Sie vollständig offenlegen, dass es Ihnen gehört, warum es angemessen wäre, das durch die Frage aufgeworfene Problem zu lösen und es nicht zu aggressiv zu bewerben, sollten Ihre Antworten hier akzeptabel sein.
Brad Larson
@brad Es ist Open Source auf Codeplex, nicht sicher, warum es hier ein Problem gibt.
Dvallejo
@DanVallejo - Ein Open-Source-Projekt zu sein, ist der Grund, warum dies beim Posten nicht von der Community gelöscht wurde. Wir geben dort etwas mehr Spielraum, bitten Sie jedoch weiterhin, Ihre Zugehörigkeit zum Projekt offenzulegen, damit die Menschen den Kontext hinter Ihrer Empfehlung verstehen können. Alex hat dies hier getan, daher ist seine Antwort in der jetzigen Form vollkommen in Ordnung.
Brad Larson
1

Ich habe NUnit 3.0.0 Beta-4 erfolgreich verwendet, um Tests parallel auszuführen

  • Läuft auf dem Build-Server
  • Führt Selentests durch
  • Hat Visual Studio-Unterstützung
  • Noch keine Resharper-Unterstützung

Vielen Dank für die Antwort von Kollegen .

Fallstricke:

  • Das parallelisierbare Attribut wird nicht vererbt, daher muss es in der Testklasse angegeben werden.
Alvis
quelle
1
NUnit 3.0 ist jetzt raus
Ralph Willgoss
0

Sie können den folgenden PowerShell-Befehl verwenden (für NUnit3, für NUnit2 den Namen des Läufers ändern):

PS> nunit3-console (ls -r *\bin\Debug\*.Tests.dll | % FullName | sort-object -Unique)

Der vorgestellte Befehl führt alle Testbaugruppen in einer einzigen Nunit-Instanz aus, wodurch der in die Engine integrierte parallele Testlauf genutzt werden kann .

Bemerkungen

  1. Denken Sie daran, das Verzeichnissuchmuster zu optimieren. In diesem Beispiel werden nur Assemblys ausgeführt, die mit .Tests.dllund in \bin\DebugVerzeichnissen enden .

  2. Achten Sie auf das UniqueFiltern - möglicherweise möchten Sie es nicht haben.

one_mile_run
quelle