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?

0voto

mercury0114 Punkte 1168

Ein einfaches Testmuster, das geeignet ist für einige (nicht alle!) Fälle ist es, denselben Test mehrmals zu wiederholen. Nehmen wir zum Beispiel an, Sie haben eine Methode:

def process(input):
    # Spawns several threads to do the job
    # ...
    return output

Erstellen Sie eine Reihe von Tests:

process(input1) -> expect to return output1
process(input2) -> expect to return output2
...

Führen Sie nun jeden dieser Tests mehrere Male durch.

Wenn die Implementierung von process einen subtilen Fehler (z. B. Deadlock, Race Condition usw.) enthält, der mit einer Wahrscheinlichkeit von 0,1 % auftritt, ergibt die 1000-malige Ausführung des Tests eine Wahrscheinlichkeit von 64 %, dass der Fehler mindestens einmal auftritt. Bei einer 10000-maligen Ausführung des Tests liegt die Wahrscheinlichkeit bei >99 %.

-1voto

Avraham Shalev Punkte 110

Wenn Sie einfache Tests durchführen new Thread(runnable).run() Sie können Thread nachahmen, um die Runnable sequenziell auszuführen

Wenn zum Beispiel der Code des getesteten Objekts einen neuen Thread wie folgt aufruft

Class TestedClass {
    public void doAsychOp() {
       new Thread(new myRunnable()).start();
    }
}

Dann kann Mocking neue Threads und führen Sie die runnable Argument sequentiell helfen

@Mock
private Thread threadMock;

@Test
public void myTest() throws Exception {
    PowerMockito.mockStatic(Thread.class);
    //when new thread is created execute runnable immediately 
    PowerMockito.whenNew(Thread.class).withAnyArguments().then(new Answer<Thread>() {
        @Override
        public Thread answer(InvocationOnMock invocation) throws Throwable {
            // immediately run the runnable
            Runnable runnable = invocation.getArgumentAt(0, Runnable.class);
            if(runnable != null) {
                runnable.run();
            }
            return threadMock;//return a mock so Thread.start() will do nothing         
        }
    }); 
    TestedClass testcls = new TestedClass()
    testcls.doAsychOp(); //will invoke myRunnable.run in current thread
    //.... check expected 
}

-5voto

Dill Punkte 1876

(wenn möglich) keine Threads, sondern Akteure / aktive Objekte verwenden. Leicht zu testen.

-7voto

user590444 Punkte 4104

Sie können EasyMock.makeThreadSafe verwenden, um die Testinstanz thread-sicher zu machen

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