Frage Einfache Möglichkeit, denselben Junit-Test immer wieder auszuführen?


Wie der Titel sagt, suche ich nach einer einfachen Möglichkeit, JUnit 4.x-Tests mehrmals hintereinander automatisch mit Eclipse auszuführen.

Ein Beispiel wäre, den gleichen Test 10 Mal hintereinander auszuführen und das Ergebnis zurückzumelden.

Wir haben bereits eine komplexe Methode, dies zu tun, aber ich suche nach einer einfachen Methode, so dass ich sicher gehen kann, dass der flockige Test, den ich zu beheben versuche, behoben wird.

Eine ideale Lösung wäre ein Eclipse Plugin / Einstellung / Feature, das mir nicht bekannt ist.


75
2017-09-29 14:20


Ursprung


Antworten:


Der einfachste Weg, dies zu tun, ist, den Test als parametrisierten Test auszuführen (mit einem Kommentar versehen) @RunWith(Parameterized.class) und fügen Sie eine Methode hinzu, um 10 leere Parameter bereitzustellen. Auf diese Weise wird das Framework den Test 10 Mal durchführen.

Dieser Test müsste der einzige Test in der Klasse sein, oder besser gesagt sollten alle Testmethoden 10 Mal in der Klasse ausgeführt werden.

Hier ist ein Beispiel:

@RunWith(Parameterized.class)
public class RunTenTimes {

    @Parameterized.Parameters
    public static Object[][] data() {
        return new Object[10][0];
    }

    public RunTenTimes() {
    }

    @Test
    public void runsTenTimes() {
        System.out.println("run");
    }
}

Mit dem Obigen ist es sogar möglich, dies mit einem parameterlosen Konstruktor zu tun, aber ich bin mir nicht sicher, ob die Framework-Autoren das beabsichtigt haben oder ob das in Zukunft brechen wird.

Wenn Sie Ihren eigenen Läufer implementieren, können Sie den Läufer 10 Mal den Test durchführen lassen. Wenn Sie einen Drittanbieter-Runner verwenden, können Sie mit 4.7 den neuen Runner verwenden @Rule Annotation und Umsetzung der MethodRule Schnittstelle, so dass es die Anweisung nimmt und es 10 mal in einer for-Schleife ausführt. Der derzeitige Nachteil dieses Ansatzes ist der @Before und @After laufe nur einmal. Dies wird sich wahrscheinlich in der nächsten Version von JUnit ändern (der @Before wird nach dem laufen @Rule), aber unabhängig davon werden Sie auf die gleiche Instanz des Objekts (etwas, was nicht wahr ist) handeln Parameterized Läufer). Dies setzt voraus, dass der Runner, mit dem die Klasse ausgeführt wird, den Wert korrekt erkennt @Rule Anmerkungen. Das ist nur der Fall, wenn es an die JUnit-Läufer delegiert wird.

Wenn Sie mit einem benutzerdefinierten Runner arbeiten, der den @Rule Annotation, dann bist du wirklich damit beschäftigt, deinen eigenen Läufer zu schreiben, der entsprechend an diesen Runner delegiert und ihn 10 Mal ausführt.

Beachten Sie, dass es andere Möglichkeiten gibt, dies zu lösen (z. B. den Theories-Runner), aber alle benötigen einen Runner. Leider unterstützt JUnit derzeit keine Läuferschichten. Das ist ein Läufer, der andere Läufer kettet.


97
2017-09-29 15:01



Ich habe festgestellt, dass die wiederholte Annotation von Spring für solche Dinge nützlich ist:

@Repeat(value = 10)

Neueste (Spring Framework 4.3.11.RELEASE API) doc:


51
2017-09-29 14:24



Angespornt an diese Lösung:

Benutzen @Repeat Anmerkung wie folgt:

public class MyTestClass {

    @Rule
    public RepeatRule repeatRule = new RepeatRule();

    @Test
    @Repeat(10)
    public void testMyCode() {
        //your test code goes here
    }
}

Sie benötigen nur diese zwei Klassen:

Wiederholen.java:

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention( RetentionPolicy.RUNTIME )
@Target({ METHOD, ANNOTATION_TYPE })
public @interface Repeat {
    int value() default 1;
}

RepeatRule.java:

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class RepeatRule implements TestRule {

    private static class RepeatStatement extends Statement {
        private final Statement statement;
        private final int repeat;    

        public RepeatStatement(Statement statement, int repeat) {
            this.statement = statement;
            this.repeat = repeat;
        }

        @Override
        public void evaluate() throws Throwable {
            for (int i = 0; i < repeat; i++) {
                statement.evaluate();
            }
        }

    }

    @Override
    public Statement apply(Statement statement, Description description) {
        Statement result = statement;
        Repeat repeat = description.getAnnotation(Repeat.class);
        if (repeat != null) {
            int times = repeat.value();
            result = new RepeatStatement(statement, times);
        }
        return result;
    }
}

2016-10-25 Bearbeiten: Um diese Lösung bei der Verwendung zu verwenden @RunWith(PowerMockRunner.class), aktualisieren zu Powermock 1.6.5 (welches beinhaltet dieser Patch).


26
2018-02-05 13:56



Mit IntelliJ können Sie dies über die Testkonfiguration tun. Sobald Sie dieses Fenster geöffnet haben, können Sie den Test beliebig oft ausführen.

enter image description here

Wenn Sie den Test ausführen, führt Intellij alle Tests aus, die Sie für die angegebene Anzahl von Tests ausgewählt haben.

Beispiel läuft 624 Tests 10 mal: enter image description here


25
2017-09-13 20:34



Mit JUnit 5 konnte ich dies mit Hilfe der @RepeatedTest Anmerkung:

@RepeatedTest(10)
public void testMyCode() {
    //your test code goes here
}

Beachten Sie, dass @Test Annotation sollte nicht mit verwendet werden @RepeatedTest.


12
2017-07-26 08:37



Irgendetwas stimmt nicht mit:

@Test
void itWorks() {
    // stuff
}

@Test
void itWorksRepeatably() {
    for (int i = 0; i < 10; i++) {
        itWorks();
    }
}

Im Gegensatz zu dem Fall, in dem Sie jeweils ein Array von Werten testen, ist es nicht besonders wichtig, welcher Lauf fehlgeschlagen ist.

Sie müssen nicht in der Konfiguration oder Anmerkung tun, was Sie im Code tun können.


9
2017-09-30 13:30



Das funktioniert viel einfacher für mich.

public class RepeatTests extends TestCase {

    public static Test suite() {
        TestSuite suite = new TestSuite(RepeatTests.class.getName());

        for (int i = 0; i < 10; i++) {              
        suite.addTestSuite(YourTest.class);             
        }

        return suite;
    }
}

7
2017-08-21 08:30



Es gibt eine intermittierende Anmerkung in der Die Zeit flieht Bibliothek, die mit JUnit 4.7 funktioniert @Rule um einen Test mehrmals oder mit zu wiederholen @RunWith.

Beispielsweise,

@RunWith(IntermittentTestRunner.class)
public class IntermittentTestRunnerTest {

   private static int testCounter = 0;

   @Test
   @Intermittent(repition = 99)
   public void annotatedTest() {
      testCounter++;
   }
}

Nachdem der Test ausgeführt wurde (mit dem IntermittentTestRunner in der @RunWith), testCounter wäre gleich 99.


7
2017-12-16 20:39



Ich baue ein Modul, das diese Art von Tests ermöglicht. Aber es konzentriert sich nicht nur auf Wiederholung. Aber in Garantie, dass ein Stück Code Thread sicher ist.

https://github.com/anderson-marques/concurrent-testing

Maven Abhängigkeit:

<dependency>
    <groupId>org.lite</groupId>
    <artifactId>concurrent-testing</artifactId>
    <version>1.0.0</version>
</dependency>

Anwendungsbeispiel:

package org.lite.concurrent.testing;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import ConcurrentTest;
import ConcurrentTestsRule;

/**
 * Concurrent tests examples
 */
public class ExampleTest {

    /**
     * Create a new TestRule that will be applied to all tests
     */
    @Rule
    public ConcurrentTestsRule ct = ConcurrentTestsRule.silentTests();

    /**
     * Tests using 10 threads and make 20 requests. This means until 10 simultaneous requests.
     */
    @Test
    @ConcurrentTest(requests = 20, threads = 10)
    public void testConcurrentExecutionSuccess(){
        Assert.assertTrue(true);
    }

    /**
     * Tests using 10 threads and make 20 requests. This means until 10 simultaneous requests.
     */
    @Test
    @ConcurrentTest(requests = 200, threads = 10, timeoutMillis = 100)
    public void testConcurrentExecutionSuccessWaitOnly100Millissecond(){
    }

    @Test(expected = RuntimeException.class)
    @ConcurrentTest(requests = 3)
    public void testConcurrentExecutionFail(){
        throw new RuntimeException("Fail");
    }
}

Dies ist ein Open-Source-Projekt. Fühlen Sie sich frei, sich zu verbessern.


0
2018-05-30 13:30



Sie können Ihren JUnit-Test mit einer Hauptmethode ausführen und so oft wiederholen, wie Sie möchten:

package tests;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.Result;

public class RepeatedTest {

    @Test
    public void test() {
        fail("Not yet implemented");
    }

    public static void main(String args[]) {

        boolean runForever = true;

        while (runForever) {
            Result result = org.junit.runner.JUnitCore.runClasses(RepeatedTest.class);

            if (result.getFailureCount() > 0) {
                runForever = false;
               //Do something with the result object

            }
        }

    }

}

0
2017-09-06 06:52