Легкий способ повторения одного и того же теста на юнитах снова и снова?

Как и в названии, я ищу несколько простых способов запуска тестов JUnit 4.x несколько раз подряд, используя Eclipse.

Пример будет выполнять один и тот же тест 10 раз подряд и сообщать результат.

У нас уже есть сложный способ сделать это, но я ищу простой способ сделать это, чтобы я мог быть уверен в том, что проверенный флай-тест, который я пытался исправить, остается фиксированным.

Идеальное решение было бы плагином/установкой/установкой Eclipse, о которой я не знаю.

Ответ 1

Самый простой (как и в случае с @RunWith(Parameterized.class) количеством нового кода) способ сделать это - запустить тест в качестве параметризованного теста (аннотировать с помощью @RunWith(Parameterized.class) и добавить метод для предоставления 10 пустых параметров). Таким образом, среда будет проходить тест 10 раз.

Этот тест должен быть единственным тестом в классе, или лучше всего использовать все методы тестирования, которые должны выполняться 10 раз в классе.

Вот пример:

@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");
    }
}

С вышесказанным можно даже сделать это с помощью конструктора без параметров, но я не уверен, что авторы фреймворка намеревались это или если это произойдет в будущем.

Если вы реализуете свой собственный бегун, то вы можете запустить runner 10 раз. Если вы используете сторонний участник, то с 4.7 вы можете использовать новую аннотацию @Rule и реализовать интерфейс MethodRule чтобы он @Rule и выполнил его 10 раз в цикле for. Нынешним недостатком такого подхода является то, что @Before и @After запускаются только один раз. Вероятно, это изменится в следующей версии JUnit (@Before будет запускаться после @Rule), но независимо от того, будете ли вы действовать в одном экземпляре объекта (что не соответствует Parameterized бегуну). Это предполагает, что любой бегун, которым вы управляете классом, правильно распознает аннотации @Rule. Это только в случае, если он делегирует бегунов JUnit.

Если вы работаете с пользовательским бегуном, который не распознает аннотацию @Rule, вы действительно застряли в том, что вам нужно написать свой собственный бегун, который соответствующим образом делегирует этому Runner и запускает его 10 раз.

Обратите внимание, что есть другие способы потенциально решить эту проблему (например, бегун Теории), но все они требуют бегуна. К сожалению, JUnit в настоящее время не поддерживает слои бегунов. Это бегун, который соединяет других бегунов.

Ответ 3

С помощью IntelliJ вы можете сделать это из тестовой конфигурации. После того как вы откроете это окно, вы можете запустить тест сколько угодно раз,

введите описание изображения здесь

когда вы запустите тест, intellij выполнит все тесты, которые вы выбрали, для количества раз, когда вы указали.

Пример: 624 теста 10 раз: введите описание изображения здесь

Ответ 4

Вдохновленный это решение:

Использовать аннотацию @Repeat следующим образом:

public class MyTestClass {

    @Rule
    public RepeatRule repeatRule = new RepeatRule();

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

Вам понадобятся только эти два класса:

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 Изменить: Чтобы использовать это решение при использовании @RunWith(PowerMockRunner.class), обновите до Powermock 1.6.5 (который включает этот патч).

Ответ 5

С JUnit 5 я смог решить эту проблему, используя аннотацию @RepeatedTest:

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

Обратите внимание, что @Test аннотация не должна использоваться вместе с @RepeatedTest.

Ответ 6

Что-то не так:

@Test
void itWorks() {
    // stuff
}

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

В отличие от случая, когда вы тестируете каждый массив значений, вам не особо важно, какой запуск завершился неудачно.

Не нужно делать в настройке или аннотации, что вы можете сделать в коде.

Ответ 7

В библиотеке tempus-fugit имеется прерывистая аннотация, которая работает с JUnit 4.7 @Rule для повторения теста несколько раз или с помощью @RunWith.

Например,

@RunWith(IntermittentTestRunner.class)
public class IntermittentTestRunnerTest {

   private static int testCounter = 0;

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

После запуска теста (с IntermittentTestRunner в @RunWith), testCounter будет равно 99.

Ответ 8

Это работает намного легче для меня.

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;
    }
}

Ответ 9

Я создаю модуль, который позволяет делать такие тесты. Но он фокусируется не только на повторении. Но в гарантии, что какой-то фрагмент кода является потокобезопасным.

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

Зависимость от Maven:

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

Пример использования:

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");
    }
}

Это проект с открытым исходным кодом. Не стесняйтесь улучшаться.

Ответ 10

Вы можете запустить свой JUnit-тест из основного метода и повторить его столько раз, сколько вам нужно:

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

            }
        }

    }

}