806 Stimmen

Wie sollte ich Multithreading-Code in der Einheit testen?

Bisher habe ich den Albtraum des Testens von Multithreading-Code vermieden, da er mir einfach zu sehr wie ein Minenfeld erscheint. Ich möchte fragen, wie die Leute über das Testen von Code, der auf Threads für die erfolgreiche Ausführung angewiesen ist, oder einfach nur, wie die Leute über das Testen dieser Art von Fragen, die nur zeigen, wenn zwei Threads in einer bestimmten Weise interagieren gegangen sind?

Dies scheint ein wirklich zentrales Problem für die Programmierer heute, wäre es nützlich, unser Wissen auf dieser einen imho Pool.

2 Stimmen

Ich hatte vor, eine Frage zu genau diesem Thema zu stellen. Obwohl Will im Folgenden viele gute Punkte anführt, denke ich, dass wir es besser machen können. Ich stimme zu, dass es keinen einzigen "Ansatz" gibt, um das Problem sauber zu lösen. Aber "so gut wie möglich zu testen" setzt die Messlatte sehr niedrig an. Ich werde mit meinen Ergebnissen zurückkommen.

0 Stimmen

In Java: Das Paket java.util.concurrent enthält einige schlecht bekannte Klassen, die helfen können, deterministische JUnit-Tests zu schreiben. Werfen Sie einen Blick auf - CountDownLatch - Semaphor - Austauscher

0 Stimmen

Können Sie bitte einen Link zu Ihrer vorherigen Frage zu Unit-Tests angeben?

7voto

scim Punkte 203

Ich handhabe Unit-Tests von Komponenten mit Threads auf die gleiche Weise wie alle anderen Unit-Tests, d.h. mit Inversion der Kontrolle und Isolations-Frameworks. Ich entwickle in der .Net-Arena, und das Threading ist (neben anderen Dingen) von Haus aus sehr schwer (ich würde sagen, fast unmöglich) vollständig zu isolieren.

Deshalb habe ich Wrapper geschrieben, die etwa so aussehen (vereinfacht):

public interface IThread
{
    void Start();
    ...
}

public class ThreadWrapper : IThread
{
    private readonly Thread _thread;

    public ThreadWrapper(ThreadStart threadStart)
    {
        _thread = new Thread(threadStart);
    }

    public Start()
    {
        _thread.Start();
    }
}

public interface IThreadingManager
{
    IThread CreateThread(ThreadStart threadStart);
}

public class ThreadingManager : IThreadingManager
{
    public IThread CreateThread(ThreadStart threadStart)
    {
         return new ThreadWrapper(threadStart)
    }
}

Von dort aus kann ich den IThreadingManager einfach in meine Komponenten injizieren und mein Isolations-Framework der Wahl verwenden, um den Thread so zu machen, wie ich es während des Tests erwarte.

Das hat bei mir bisher gut funktioniert, und ich verwende den gleichen Ansatz für den Thread-Pool, Dinge in System.Environment, Sleep etc. etc.

6voto

Toby Punkte 9044

Sehen Sie sich meine entsprechende Antwort unter

Entwerfen einer Testklasse für eine benutzerdefinierte Barriere

Sie ist zwar auf Java ausgerichtet, bietet aber eine gute Zusammenfassung der Optionen.

Zusammenfassend lässt sich sagen, dass (IMO) nicht die Verwendung eines ausgefallenen Frameworks für die Korrektheit sorgt, sondern die Art und Weise, wie Sie Ihren Multithreading-Code gestalten. Die Aufteilung der Belange (Gleichzeitigkeit und Funktionalität) trägt wesentlich dazu bei, das Vertrauen zu erhöhen. Wachsende objektorientierte Software, geleitet von Tests erklärt einige Optionen besser als ich es kann.

Statische Analyse und formale Methoden (siehe, Gleichzeitigkeit: Zustandsmodelle und Java-Programme ) ist eine Option, aber ich habe festgestellt, dass sie in der kommerziellen Entwicklung nur von begrenztem Nutzen sind.

Vergessen Sie nicht, dass Belastungs- und Sickertests nur selten garantieren, dass sie Probleme aufdecken.

Viel Glück!

6voto

Scott Bale Punkte 10399

Für Java, siehe Kapitel 12 von JCIP . Es gibt einige konkrete Beispiele für das Schreiben von deterministischen Multithreading-Unit-Tests, um zumindest die Korrektheit und Invarianten von nebenläufigem Code zu testen.

Der "Nachweis" der Thread-Sicherheit mit Unit-Tests ist viel schwieriger. Ich bin der Meinung, dass dies besser durch automatisierte Integrationstests auf einer Vielzahl von Plattformen/Konfigurationen erreicht werden kann.

6voto

graham.reeds Punkte 15745

Pete Goodliffe hat eine Serie über die Unit-Tests von Threads Code.

Das ist schwer. Ich wähle den einfacheren Weg und versuche, den Threading-Code vom eigentlichen Test zu abstrahieren. Pete erwähnt zwar, dass die Art und Weise, wie ich es tue, falsch ist, aber entweder habe ich die Trennung richtig hinbekommen oder ich hatte einfach Glück.

6voto

Don Kirkby Punkte 46803

Ich schreibe gerne zwei oder mehr Testmethoden, die auf parallelen Threads ausgeführt werden, und jede von ihnen ruft das zu testende Objekt auf. Bisher habe ich Sleep()-Aufrufe verwendet, um die Reihenfolge der Aufrufe in den verschiedenen Threads zu koordinieren, aber das ist nicht wirklich zuverlässig. Es ist auch viel langsamer, weil man lange genug schlafen muss, damit das Timing normalerweise funktioniert.

Ich fand die Multithreading TC Java-Bibliothek von der gleichen Gruppe, die FindBugs geschrieben hat. Damit können Sie die Reihenfolge der Ereignisse festlegen, ohne Sleep() zu verwenden, und es ist zuverlässig. Ich habe es noch nicht ausprobiert.

Die größte Einschränkung dieses Ansatzes ist, dass Sie nur die Szenarien testen können, von denen Sie vermuten, dass sie Probleme verursachen werden. Wie andere bereits gesagt haben, müssen Sie Ihren Multithreading-Code wirklich in eine kleine Anzahl einfacher Klassen isolieren, damit Sie überhaupt die Möglichkeit haben, ihn gründlich zu testen.

Nachdem Sie die Szenarien, von denen Sie erwarten, dass sie Probleme verursachen, sorgfältig getestet haben, ist ein unwissenschaftlicher Test, bei dem eine Reihe von gleichzeitigen Anfragen an die Klasse gestellt werden, ein guter Weg, um nach unerwarteten Problemen zu suchen.

Aktualisierung: Ich habe ein wenig mit der Multithreaded TC Java-Bibliothek gespielt, und es funktioniert gut. Ich habe auch einige ihrer Funktionen in eine .NET-Version portiert, die ich TickingTest .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X