[java] 동일한 junit 테스트를 반복해서 실행하는 쉬운 방법?

제목에서 알 수 있듯이 Eclipse를 사용하여 JUnit 4.x 테스트를 연속으로 여러 번 실행하는 간단한 방법을 찾고 있습니다.

예를 들어 동일한 테스트를 10 번 연속 실행하고 결과를보고합니다.

우리는 이미이 작업을 수행하는 복잡한 방법을 가지고 있지만, 제가 고치려고했던 비정상적인 테스트가 고정 된 상태로 유지 될 수 있도록 간단한 방법을 찾고 있습니다.

이상적인 솔루션은 내가 알지 못하는 Eclipse 플러그인 / 설정 / 기능입니다.



답변

이를 수행하는 가장 쉬운 방법 (최소한의 새 코드 필요)은 테스트를 매개 변수화 된 테스트로 실행하는 것 @RunWith(Parameterized.class)입니다. 이렇게하면 프레임 워크가 테스트를 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");
    }
}

위의 경우 매개 변수없는 생성자로도 할 수 있지만 프레임 워크 작성자가 의도 한 것인지 아니면 향후 중단 될 것인지 확신 할 수 없습니다.

자체 러너를 구현하는 경우 러너가 테스트를 10 번 실행하도록 할 수 있습니다. 타사 실행기를 사용하는 경우 4.7에서는 새 @Rule주석을 사용 하고 MethodRule인터페이스를 구현 하여 문을 가져 와서 for 루프에서 10 번 실행하도록 할 수 있습니다. 이 방법의 현재 단점은 것입니다 @Before그리고 @After한 번만 실행하세요. 이것은 JUnit의 다음 버전에서 변경 될 가능성이 있지만 (는 @Before이후에 실행될 것입니다 @Rule),하지만 객체의 동일한 인스턴스 (실행자에게는 사실이 아닌 것)에서 작동하게 될 것입니다 Parameterized. 이것은 클래스를 실행하는 주자가 @Rule주석 을 올바르게 인식한다고 가정합니다 . JUnit 실행자에게 위임하는 경우에만 해당됩니다.

@Rule주석을 인식하지 않는 사용자 지정 러너로 실행하는 경우 해당 러너에게 적절하게 위임하고 10 번 실행하는 자체 러너를 작성해야하는 데 정말 고착됩니다.

이 문제를 잠재적으로 해결할 수있는 다른 방법 (예 : Theories 러너)이 있지만 모두 러너가 필요합니다. 불행히도 JUnit은 현재 러너 레이어를 지원하지 않습니다. 그것은 다른 주자를 묶는 주자입니다.


답변

IntelliJ를 사용하면 테스트 구성에서이를 수행 할 수 있습니다. 이 창을 열면 원하는 횟수만큼 테스트를 실행하도록 선택할 수 있습니다.

여기에 이미지 설명 입력

테스트를 실행하면 intellij는 지정한 횟수만큼 선택한 모든 테스트를 실행합니다.

624 개의 테스트를 10 번 실행 한 예 :
여기에 이미지 설명 입력


답변

나는 Spring의 반복 주석이 그런 종류의 일에 유용하다는 것을 발견했습니다.

@Repeat(value = 10)

최신 (Spring Framework 4.3.11.RELEASE API) 문서 :


답변

다음 리소스에서 영감을 얻었습니다.

다음과 @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;
    }
}

PowerMock

이 솔루션을 @RunWith(PowerMockRunner.class)에서 사용하려면 Powermock 1.6.5 ( 패치 포함) 업데이트해야합니다 .


답변

JUnit 5에서는 @RepeatedTest 주석을 사용 하여이 문제를 해결할 수있었습니다 .

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

참고 @Test주석과 함께 사용할 수 없습니다 @RepeatedTest.


답변

문제가있는 경우 :

@Test
void itWorks() {
    // stuff
}

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

각 값 배열을 테스트하는 경우와 달리 어떤 실행이 실패했는지 특별히 신경 쓰지 않습니다.

코드에서 수행 할 수있는 작업을 구성 또는 주석에서 수행 할 필요가 없습니다.


답변

이것은 나를 위해 훨씬 쉽게 작동합니다.

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