2010-01-08 10 views
14

Ich bin ziemlich neu in der Unit-Tests und experimentiere derzeit ein wenig mit Visual Studio Test-Tools.Wie Modell Parallelität in Komponententests?

Meine Frage ist, wie in diesen Tests Aussagen über gleichzeitigen Verhalten zu definieren. Z.B. eine Klasse BoundedChan<T> einen beschränkten Kanal Implementierung, da, wie kann ich Tests angeben wie

  1. channel.Send wird nicht blockieren“ oder
  2. „Wenn die Kapazität des Kanals überschritten wird, channel.Send wird blockiert, bis ein Wert gelesen wird“

Gibt es eine elegante Lösung, um diese Behauptungen zu schreiben?

+1

Ich bin mir nicht sicher, gibt es irgendwelche genaue Duplikate (obwohl diese nah ist: http: // stackoverflow.com/questions/314580/how-do-i-perform-unit-test-using-threads), aber es gibt ziemlich viel gutes SO-Material dazu. Ich habe einige der besseren Diskussionen in meiner Antwort hier aufgelistet: http://stackoverflow.com/questions/1520539/how-to-prove-that-multithreading-is-working/1520619#1520619. –

+0

@Jeff: Warum postest du das nicht als Antwort - Sieht für mich ziemlich nützlich aus. – Dario

Antwort

6

Hier ist eine blog article, die das Thema behandelt; es konzentriert sich auf NUnit.

Leider ist die Parallelität immer noch ein Bereich der Komponententests, der schwierig zu strukturieren ist. Es ist kein einfaches Problem und erfordert immer noch, dass Sie im Test einige Ihrer eigenen Synchronisations- und Gleichzeitigkeitslogik implementieren.

Für das Beispiel, das Sie angeben, kann es unmöglich sein, einen Test zu schreiben, der schlüssig zeigt, dass eine Methode unter bestimmten Bedingungen blockiert wird oder nicht. Sie können möglicherweise ein gewisses Maß an Sicherheit erreichen, indem Sie zuerst Worst-Case-Situationen erstellen, bei denen Sie das Blockierungsverhalten erwarten würden - und dann Tests schreiben, um festzustellen, ob dies der Fall ist oder nicht.

+0

Link ist tot, aber Wayback Machine hat deinen Rücken. Original Dan Barvitsky Artikel: https://web.archive.org/web/20140822013404/http://www.atalasoft.com/cs/blogs/danbarvitsky/archive/2009/06/12/techniques-for-testing-concurrent -code-in-nunit.aspx. Sein Follow-up-Post: https://web.archive.org/web/20100526080326/http://www.atalasoft.com/cs/blogs/danbarvitsky/archive/2009/06/15/my-solution-for-unit -testing-concurrent-code-in-nunit.aspx. –

+0

@ SørenBoisen Ihre Links sind auch tot :(es sagt Seite kann nicht angezeigt werden wegen robots.txt. –

+0

@BogdanMart Autsch, so eine neu erstellte robots.txt wird Wayback Machine den Zugriff auf (oder löschen) alte Website Kratzer zu blockieren. Schlechte Nachrichten für die Internetarchivierung: Ich schätze, die Blogposts sind jetzt wirklich verloren. –

4

Diese Frage könnte zu genügend Inhalt führen, um ein Buch zu füllen.

Im Allgemeinen würde ich nicht empfehlen, Komponententests zu Ihren Klassen für gleichzeitige Szenarien hinzuzufügen. Mit etwas Übung werden Sie lernen, dass automatisierte Komponententests einen oder mehrere "Sweet Spots" haben. Wenn Sie sich auf diese Bereiche konzentrieren (und andere Praktiken in anderen Bereichen anwenden), erzielen Sie einen besseren ROI.

Aber Ihre Klasse scheint über Nebenläufigkeit (kann nicht sicher sagen, basierend auf Informationen zur Verfügung gestellt), und deshalb könnte dies ein Fall sein, wo Sie wirklich einen Gleichzeitigkeit simulierenden Test wollen.

Sie können (soweit ich weiß) mehrere Threads in einem Komponententest starten, wenn Sie möchten. Aber es könnte einen einfacheren Weg geben. Erwägen Sie, das Muster Compose Method zu nutzen. Während wir auf dem Thema sind - dieses Muster ist ziemlich entscheidend für effektive Komponententests über alle, nicht nur mit Nebenläufigkeit.

1

ich einen Helfer erstellt haben, die eine Reihe von Threads beginnen können gleichzeitige Aktionen auszuführen. Der Helfer stellt Synchronisationsgrundelemente und Protokollierungsmechanismen bereit. Es kann in Verbindung mit jedem Unit-Test-Framework verwendet werden. Hier ist ein Code-Fragment aus einer Einheit Test:

[Test] 
public void TwoCodeBlocksInParallelTest() 
{ 
    // This static method runs the provided Action delegates in parallel using threads 
    CTestHelper.Run(
     c => 
      { 
       Thread.Sleep(1000); // Here should be the code to provide something 
       CTestHelper.AddSequenceStep("Provide"); // We record a sequence step for the expectations after the test 
       CTestHelper.SetEvent(); 
      }, 
     c => 
      { 
       CTestHelper.WaitEvent(); // We wait until we can consume what is provided 
       CTestHelper.AddSequenceStep("Consume"); // We record a sequence step for the expectations after the test 
      }, 
     TimeSpan.FromSeconds(10)); // This is a timeout parameter, if the threads are deadlocked or take too long, the threads are terminated and a timeout exception is thrown 

    // After Run() completes we can analyze if the recorded sequence steps are in the correct order 
    Expect(CTestHelper.GetSequence(), Is.EqualTo(new[] { "Provide", "Consume" })); 
} 

es verwendet werden kann Client/Server-Synchronisation oder in Komponenten zu testen oder einfach ein Gewinde mit einem Timeout auszuführen. Ich werde das in den nächsten Wochen weiter verbessern. Hier ist die Projektseite: Concurrency Testing Helper