it-swarm.com.de

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

Wie der Titel schon 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 zehnmal hintereinander auszuführen und das Ergebnis zu melden.

Wir haben bereits einen komplexen Weg, dies zu tun, aber ich suche nach einem einfachen Weg, damit ich sicher sein kann, dass der flockige Test, den ich versucht habe zu reparieren, unverändert bleibt.

Eine ideale Lösung wäre ein Eclipse-Plugin/eine Einstellung/Funktion, die ich nicht kenne.

89
Stefan Thyberg

Der einfachste Weg (dies ist die geringste Menge an neuem Code), besteht darin, den Test als parametrisierten Test auszuführen (Annotieren mit @RunWith(Parameterized.class) und Hinzufügen einer Methode, um 10 leere Parameter bereitzustellen). Auf diese Weise führt das Framework den Test zehnmal aus.

Dieser Test muss der einzige Test in der Klasse sein, oder besser, alle Testmethoden sollten in der Klasse zehnmal 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 oben genannten ist es sogar möglich, einen parameterlosen Konstruktor zu verwenden, aber ich bin nicht sicher, ob die Framework-Autoren das beabsichtigen oder ob dies in der Zukunft brechen wird.

Wenn Sie einen eigenen Läufer implementieren, kann der Läufer den Test zehnmal ausführen. Wenn Sie einen Drittanbieter-Läufer verwenden, können Sie mit 4.7 die neue Annotation @Rule verwenden und die MethodRule-Schnittstelle implementieren, sodass die Anweisung 10-mal in einer for-Schleife ausgeführt wird. Der gegenwärtige Nachteil dieses Ansatzes ist, dass @Before und @After nur einmal ausgeführt werden. Dies wird sich wahrscheinlich in der nächsten Version von JUnit ändern (der @Before wird nach dem @Rule ausgeführt), aber unabhängig davon, dass Sie mit derselben Instanz des Objekts arbeiten (etwas, das nicht für den Parameterized-Runner gilt). Dies setzt voraus, dass der Läufer, mit dem Sie die Klasse ausführen, die @Rule-Anmerkungen korrekt erkennt. Dies ist nur der Fall, wenn an die JUnit-Läufer delegiert wird.

Wenn Sie mit einem benutzerdefinierten Läufer laufen, der die @Rule-Annotation nicht erkennt, müssen Sie wirklich einen eigenen Läufer schreiben, der entsprechend an diesen Läufer delegiert und ihn zehnmal ausführt.

Beachten Sie, dass es andere Möglichkeiten gibt, dieses Problem möglicherweise zu lösen (z. B. Theories Runner), aber alle erfordern einen Runner. Leider unterstützt JUnit derzeit keine Läuferschichten. Das ist ein Läufer, der andere Läufer kettet.

111
Yishai

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

@Repeat(value = 10)

Aktuelles (Spring Framework 4.3.11.RELEASE-API) -Dokument:

57
laura

Mit IntelliJ können Sie dies über die Testkonfiguration tun. Nachdem 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 von Ihnen ausgewählten Tests für die angegebene Anzahl von Malen aus.

Beispiel mit 624 Tests 10 Mal: ​​  enter image description here

48
smac89

Inspiriert von dieser Lösung :

Verwenden Sie @Repeat-Annotation 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 beiden Klassen:

Repeat.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 Edit: Um diese Lösung bei Verwendung von @RunWith(PowerMockRunner.class) zu verwenden, aktualisieren Sie auf Powermock 1.6.5 (das dieses Patch enthält .

30
R. Oosterholt

Mit JUnit 5 konnte ich dies mit der Annotation @RepeatedTest lösen:

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

Beachten Sie, dass die @Test-Anmerkung nicht zusammen mit @RepeatedTest verwendet werden sollte.

18
César Alberca

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 jeden Wertebereich testen, ist es Ihnen egal, welcher Lauf fehlgeschlagen ist. 

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

10
soru

In der Bibliothek tempus-fugit gibt es eine intermittierende Anmerkung, die mit @Rule von JUnit 4.7 zusammenarbeitet, um einen Test mehrmals oder mit @RunWith zu wiederholen.

Zum Beispiel,

@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 im @RunWith), wäre testCounter gleich 99.

7
Toby

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
Qualk

Ich baue ein Modul, das diese Art von Tests ermöglicht. Es ist aber nicht nur auf Wiederholung fokussiert. Aber in der 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 zu verbessern. 

0

Sie können Ihren JUnit-Test über eine Hauptmethode ausführen und so oft wiederholen, wie Sie es benötigen:

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
silver_mx

Dies ist im Wesentlichen die Antwort, die Yishai oben in Kotlin geschrieben hat:

@RunWith(Parameterized::class)
class MyTest {

    companion object {

        private const val numberOfTests = 200

        @JvmStatic
        @Parameterized.Parameters
        fun data(): Array<Array<Any?>> = Array(numberOfTests) { arrayOfNulls<Any?>(0) }
    }

    @Test
    fun testSomething() { }
}
0
mark