it-swarm.com.de

Wie führt man Testmethoden in einer bestimmten Reihenfolge in JUnit4 aus?

Ich möchte Testmethoden ausführen, die von @Test in einer bestimmten Reihenfolge kommentiert werden.

Zum Beispiel:

public class MyTest {
    @Test public void test1(){}
    @Test public void test2(){}
}

Ich möchte sicherstellen, dass test1() vor test2() jedes Mal ausgeführt wird, wenn ich MyTest ausgeführt habe, aber ich konnte keine Anmerkungen wie @Test(order=xx) finden.

Ich denke, es ist sehr wichtig für JUnit, wenn der Autor von JUnit die Order-Funktion nicht will , warum?

371

Ich denke, es ist ein sehr wichtiges Feature für JUnit. Wenn der Autor von JUnit die Bestellfunktion nicht möchte, warum? 

Ich bin nicht sicher, ob dies mit JUnit sauber möglich ist. Meines Wissens geht JUnit davon aus, dass alle Tests in einer beliebigen Reihenfolge durchgeführt werden können. Aus der FAQ:

Wie verwende ich ein Testgerät?

(...) Die Reihenfolge der Aufrufe der Testmethode ist nicht garantiert, daher kann testOneItemCollection () möglicherweise vor testEmptyCollection () ausgeführt werden. (...)

Wieso ist es so? Nun, ich glaube, dass das Erstellen von Tests auftragsabhängig eine Praxis ist, die die Autoren nicht fördern wollen. Tests sollten unabhängig sein, sie sollten nicht gekoppelt sein und Verstöße gegen machen machen die Wartung schwieriger, führen dazu, dass Tests nicht mehr einzeln ausgeführt werden können (offensichtlich) usw.

Wenn Sie jedoch wirklich in diese Richtung gehen möchten, sollten Sie TestNG in Betracht ziehen, da Testmethoden in beliebiger Reihenfolge (und zum Beispiel die Angabe, dass Methoden von Methodengruppen abhängig sind) unterstützt wird. Wie das geht, erklärt Cedric Beust in Reihenfolge der Tests in testng .

217
Pascal Thivent

Wenn Sie Ihre vorhandene Instanz von Junit loswerden und JUnit 4.11 oder höher im Erstellungspfad herunterladen, führt der folgende Code die Testmethoden in der Reihenfolge ihrer Namen in aufsteigender Reihenfolge aus:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {

    @Test
    public void testAcreate() {
        System.out.println("first");
    }
    @Test
    public void testBupdate() {
        System.out.println("second");
    }
    @Test
    public void testCdelete() {
        System.out.println("third");
    }
}
66
Aniket Kulkarni

Wenn die Bestellung wichtig ist, sollten Sie die Bestellung selbst vornehmen. 

@Test public void test1() { ... }
@Test public void test2() { test1(); ... }

Insbesondere sollten Sie ggf. einige oder alle möglichen Order-Permutationen zum Testen auflisten. 

Zum Beispiel, 

void test1(); 
void test2(); 
void test3(); 


@Test
public void testOrder1() { test1(); test3(); }

@Test(expected = Exception.class)
public void testOrder2() { test2(); test3(); test1(); }

@Test(expected = NullPointerException.class)
public void testOrder3() { test3(); test1(); test2(); }

Oder einen vollständigen Test aller Permutationen: 

@Test
public void testAllOrders() {
    for (Object[] sample: permute(1, 2, 3)) {
        for (Object index: sample) {
            switch (((Integer) index).intValue()) {
                case 1: test1(); break; 
                case 2: test2(); break; 
                case 3: test3(); break; 
            }
        }
    }
}

Hier ist permute() eine einfache Funktion, die alle möglichen Permuationen in eine Collection of Array durchläuft.

49
Xiè Jìléi

Die Migration zu TestNG scheint der beste Weg zu sein, aber ich sehe hier keine klare Lösung für jUnit. Hier ist die meiste lesbare Lösung/Formatierung, die ich für jUnit gefunden habe:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {
    @Test
    void stage1_prepareAndTest(){};

    @Test
    void stage2_checkSomething(){};

    @Test
    void stage2_checkSomethingElse(){};

    @Test
    void stage3_thisDependsOnStage2(){};

    @Test
    void callTimeDoesntMatter(){}
}

Dies stellt sicher, dass stage2-Methoden nach stage1-Methoden und vor stage3-Methoden aufgerufen werden. 

39
joro

Es war eines der Hauptprobleme, mit dem ich bei der Arbeit mit Junit konfrontiert war und folgende Lösung gefunden hatte, die für mich gut funktioniert:

import Java.util.ArrayList;
import Java.util.Collections;
import Java.util.Comparator;
import Java.util.List;

import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;

public class OrderedRunner extends BlockJUnit4ClassRunner {

    public OrderedRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
    }

    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        List<FrameworkMethod> list = super.computeTestMethods();
        List<FrameworkMethod> copy = new ArrayList<FrameworkMethod>(list);
        Collections.sort(copy, new Comparator<FrameworkMethod>() {

            @Override
            public int compare(FrameworkMethod f1, FrameworkMethod f2) {
                Order o1 = f1.getAnnotation(Order.class);
                Order o2 = f2.getAnnotation(Order.class);

                if (o1 == null || o2 == null) {
                    return -1;
                }

                return o1.order() - o2.order();
            }
        });
        return copy;
    }
}

erstellen Sie auch eine Schnittstelle wie folgt:

 @Retention(RetentionPolicy.RUNTIME)


@Target({ ElementType.METHOD})

public @interface Order {
public int order();
}

Angenommen, Sie haben Klasse A, in der Sie mehrere Testfälle wie folgt geschrieben haben:

(@runWith=OrderRunner.class)
Class A{
@Test
@Order(order = 1)

void method(){

//do something

}

}

Die Ausführung beginnt also mit der Methode "method ()" . Danke!

17
Aman Goel

Die (noch nicht veröffentlichte) Änderung https://github.com/junit-team/junit/pull/386 führt einen @SortMethodsWith ein. https://github.com/junit-team/junit/pull/293 zumindest machte die Reihenfolge ohne das vorhersagbar (in Java 7 kann es durchaus zufällig sein).

8
Jesse Glick

Schauen Sie sich einen JUnit-Bericht an. JUnit ist bereits nach Paketen organisiert. Jedes Paket hat (oder kann) TestSuite-Klassen, von denen jede mehrere Testfälle ausführt. Jeder Testfall kann über mehrere Testmethoden der Form public void test*() verfügen, von denen jede tatsächlich zu einer Instanz der TestCase-Klasse wird, zu der sie gehören. Jede Testmethode (TestCase-Instanz) hat einen Namen und ein Bestanden/Nicht bestanden-Kriterium.

Was mein Management benötigt, ist das Konzept einzelner TestStep Items, die jeweils ihre eigenen Pass/Fail-Kriterien angeben. Der Ausfall eines Testschritts darf die Ausführung nachfolgender Testschritte nicht verhindern.

In der Vergangenheit haben Testentwickler in meiner Position TestCase-Klassen in Paketen organisiert, die den Teilen des zu testenden Produkts entsprechen, eine TestCase-Klasse für jeden Test erstellt und jede Testmethode zu einem separaten "Schritt" im Test gemacht. komplett mit eigenen Pass/Fail-Kriterien in der JUnit-Ausgabe. Jeder Testfall ist ein eigenständiger "Test", aber die einzelnen Methoden oder Testschritte innerhalb des Testfalls müssen in einer bestimmten Reihenfolge ablaufen.

Die Testfall-Methoden waren die Schritte des Testfalls, und die Testentwickler erhielten pro Testschritt ein separates Bestanden/Nicht bestanden-Kriterium. Jetzt sind die Testschritte durcheinander und die Tests schlagen (natürlich) fehl.

Zum Beispiel:

Class testStateChanges extends TestCase

public void testCreateObjectPlacesTheObjectInStateA()
public void testTransitionToStateBAndValidateStateB()
public void testTransitionToStateCAndValidateStateC()
public void testTryToDeleteObjectinStateCAndValidateObjectStillExists()
public void testTransitionToStateAAndValidateStateA()
public void testDeleteObjectInStateAAndObjectDoesNotExist()
public void cleanupIfAnythingWentWrong()

Jede Testmethode bestätigt und meldet ihre eigenen separaten Pass/Fail-Kriterien. Wenn Sie dies zu "einer großen Testmethode" zusammenfassen, wird die Granularität der Pass/Fail-Kriterien für jeden "Schritt" im JUnit-Übersichtsbericht verloren. ... und das stört meine Manager. Sie fordern derzeit eine andere Alternative.

Kann jemand erklären, wie eine JUnit mit verschlüsselter Testmethode separate Pass/Fail-Kriterien für jeden sequentiellen Testschritt unterstützt, wie oben beschrieben und von meinem Management gefordert?

Unabhängig von der Dokumentation sehe ich dies als eine ernste Regression im Rahmen von JUnit, die vielen Testentwicklern das Leben schwer macht.

6

JUnit erlaubt derzeit die Reihenfolge der Testmethoden unter Verwendung von Klassenanmerkungen:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FixMethodOrder(MethodSorters.JVM)
@FixMethodOrder(MethodSorters.DEFAULT)

Standardmäßig werden Testmethoden in alphabetischer Reihenfolge ausgeführt. Um bestimmte Methodenreihenfolgen festzulegen, können Sie sie wie folgt benennen:

a_TestWorkUnit_WithCertainState_ShouldDoSomething b_TestWorkUnit_WithCertainState_ShouldDoSomething c_TestWorkUnit_WithCertainState_ShouldDoSomething

Beispiele finden Sie hier .

5
Zon

Was Sie wollen, ist absolut sinnvoll, wenn Testfälle als Suite ausgeführt werden.

Leider keine Zeit für eine Komplettlösung, aber schauen Sie sich die Klasse an: 

org.junit.runners.Suite

Damit können Sie Testfälle (aus einer beliebigen Testklasse) in einer bestimmten Reihenfolge aufrufen.

Diese können verwendet werden, um Funktions-, Integrations- oder Systemtests zu erstellen.

Dadurch bleiben Ihre Unit-Tests ohne bestimmte Reihenfolge (wie empfohlen), unabhängig davon, ob Sie sie so ausführen oder nicht, und die Tests anschließend als Teil eines größeren Bildes verwenden.

Wir verwenden/erben denselben Code erneut für Unit-, Integrations- und Systemtests, manchmal datengesteuert, manchmal Commit-gesteuert und manchmal als Suite ausgeführt.

3
CharlieS

Nicht sicher Ich stimme zu Ich stimme zu: Wenn ich "Datei-Upload" testen und dann "Durch Datei-Upload eingefügte Daten" testen möchte, warum sollte ich dann nicht wollen, dass diese voneinander unabhängig sind? Absolut vernünftig denke ich, dass ich sie separat ausführen kann, anstatt beides in einem Goliath-Testfall zu haben. 

3
Mattk

Sehen Sie sich meine Lösung hier an: "Junit und Java 7."

In diesem Artikel beschreibe ich, wie man Junit-Tests in der Reihenfolge ausführt - "wie im Quellcode" . Tests werden ausgeführt, in der Reihenfolge, in der Ihre Testmethoden in der Klassendatei angezeigt werden.

http://intellijava.blogspot.com/2012/05/junit-and-Java-7.html

Aber wie Pascal Thivent sagte, ist dies keine gute Praxis.

2
kornero

Ich habe ein paar Antworten gelesen und bin damit einverstanden, dass dies nicht die beste Methode ist, aber der einfachste Weg, Ihre Tests zu bestellen - und die Art, wie JUnit Tests standardmäßig ausführt, ist der alphabetische Name aufsteigend. 

Benennen Sie Ihre Tests einfach in der gewünschten alphabetischen Reihenfolge. Beachten Sie auch, dass der Testname Mit dem Word-Test beginnen muss. Achten Sie einfach auf Zahlen

test12 wird vor test2 ausgeführt

so:

testA_MyFirstTest testC_ThirdTest testB_ATestThatRunsSecond

1
pstorli

Mit JUnit 5.4 können Sie die Reihenfolge festlegen:

@Test
@Order(2)
public void sendEmailTestGmail() throws MessagingException {

sie müssen nur Ihre Klasse mit Anmerkungen versehen

@TestMethodOrder(OrderAnnotation.class)

https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-execution-order

ich benutze dies in meinem Projekt und es funktioniert sehr gut!

0
Walid

Bitte sehen Sie sich diese an: https://github.com/TransparentMarket/junit . Der Test wird in der Reihenfolge ausgeführt, in der sie angegeben sind (in der kompilierten Klassendatei definiert). Außerdem enthält es eine AllTests-Suite, um Tests auszuführen, die zuerst durch ein Unterpaket definiert wurden. Mit der AllTests-Implementierung kann die Lösung auch in der Filterung nach Eigenschaften erweitert werden (wir haben früher @Fast-Annotationen verwendet, die jedoch noch nicht veröffentlicht wurden).

0
Martin Kersten

Hier ist eine Erweiterung von JUnit, die das gewünschte Verhalten erzeugen kann: https://github.com/aafuks/aaf-junit

Ich weiß, dass dies gegen die Autoren der JUnit-Philosophie ist, aber wenn Sie JUnit in Umgebungen einsetzen, in denen keine strengen Unit-Tests (wie in Java) praktiziert werden, kann dies sehr hilfreich sein. 

0
shlomi33

sie können einen der folgenden Codes verwenden:

@FixMethodOrder(MethodSorters.JVM)OR `@FixMethodOrder(MethodSorters.DEFAULT)` OR `@FixMethodOrder(MethodSorters.NAME_ASCENDING)` before your test class like this:


@FixMethodOrder(MethodSorters.NAME_ASCENDING)


public class BookTest { ...}
0

Ich endete hier und dachte, dass meine Tests nicht in der richtigen Reihenfolge liefen, aber die Wahrheit ist, dass das Durcheinander in meinen asynchronen Jobs lag. Wenn Sie mit Parallelität arbeiten, müssen Sie auch Parallelitätsprüfungen zwischen Ihren Tests durchführen .. In meinem Fall teilen Jobs und Tests ein Semaphor, so dass die nächsten Tests so lange hängen bleiben, bis der laufende Job die Sperre aufhebt.

Ich weiß, dass dies nicht vollständig mit dieser Frage zusammenhängt, könnte aber vielleicht helfen, das richtige Problem anzugehen

0
McCoy