동적 테스트 수를 사용한 JUnit 테스트


95

우리 프로젝트 에는 디렉토리에서 모든 파일을 가져 와서 테스트를 실행하는 여러 JUnit 테스트가 있습니다. 이 testEveryFileInDirectory메서드를 구현하면 TestCase실패하거나 성공할 수있는 하나의 테스트로만 표시됩니다. 그러나 각 개별 파일의 결과에 관심이 있습니다. Eclipse의 그래픽 TestRunner에서 각 파일이 별도의 테스트로 표시되도록 TestCase/를 어떻게 작성할 수 TestSuite있습니까? (각 파일에 대한 명시적인 테스트 방법을 코딩하는 것은 옵션이 아닙니다.)

ParameterizedTest 질문 을 Eclipse Testrunner의 이름과 비교하십시오 .


답변:


102

JUnit 4의 매개 변수화 된 테스트 를 살펴보십시오 .

사실 저는 며칠 전에 이것을했습니다. 나는 설명하려고 노력할 것이다 ...

먼저 하나의 입력 파일로 테스트하는 것처럼 테스트 클래스를 정상적으로 빌드하십시오. 다음과 같이 수업을 장식하십시오.

@RunWith(Parameterized.class)

모든 테스트 호출에서 변경 될 입력을받는 하나의 생성자를 빌드합니다 (이 경우 파일 자체 일 수 있음).

그런 다음 Collection배열 을 반환하는 정적 메서드를 빌드 합니다. 컬렉션의 각 배열에는 클래스 생성자 (예 : 파일)에 대한 입력 인수가 포함됩니다. 이 방법을 다음과 같이 장식하십시오.

@Parameters

다음은 샘플 클래스입니다.

@RunWith(Parameterized.class)
public class ParameterizedTest {

    private File file;

    public ParameterizedTest(File file) {
        this.file = file;
    }

    @Test
    public void test1() throws Exception {  }

    @Test
    public void test2() throws Exception {  }

    @Parameters
    public static Collection<Object[]> data() {
        // load the files as you want
        Object[] fileArg1 = new Object[] { new File("path1") };
        Object[] fileArg2 = new Object[] { new File("path2") };

        Collection<Object[]> data = new ArrayList<Object[]>();
        data.add(fileArg1);
        data.add(fileArg2);
        return data;
    }
}

또한,이 체크


1
감사! JUnit 3이 이클립스 테스트 러너를 혼동하고 JUnit 4 메서드를 사용하면 테스트 등을 다시 실행할 수 있기 때문에 JUnit 4 메서드는 다른 답변에 제공된 JUnit 3 메서드보다 낫습니다. 이클립스를 어떻게 표시 할 수 있는지 궁금합니다. 테스트 이름-[0], [1] 등 만 표시됩니다.
Hans-Peter Störr

@hstoerr, JUnit의 다음 릴리스에있을 것 같습니다. :-) github.com/KentBeck/junit/commit/…
rescdsk

[다른 데이터 조합을 사용하는] 각 실행에서 테스트 실행의 이름을 수정하려면 어떻게 변환할까요? [즉, Path1 파일은 test1Path1, test2Path?
monksy


27

JUnit 3

public class XTest extends TestCase {

    public File file;

    public XTest(File file) {
        super(file.toString());
        this.file = file;
    }

    public void testX() {
        fail("Failed: " + file);
    }

}

public class XTestSuite extends TestSuite {

    public static Test suite() {
        TestSuite suite = new TestSuite("XTestSuite");
        File[] files = new File(".").listFiles();
        for (File file : files) {
            suite.addTest(new XTest(file));
        }
        return suite;
    }

}

JUnit 4

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class TestY {

    @Parameters
    public static Collection<Object[]> getFiles() {
        Collection<Object[]> params = new ArrayList<Object[]>();
        for (File f : new File(".").listFiles()) {
            Object[] arr = new Object[] { f };
            params.add(arr);
        }
        return params;
    }

    private File file;

    public TestY(File file) {
        this.file = file;
    }

    @Test
    public void testY() {
        fail(file.toString());
    }

}

11

Junit 5 매개 변수화 된 테스트

JUnit 5 매개 변수화 된 테스트는 메소드를 데이터 소스로 사용할 수 있도록하여이를 지원합니다 .

@ParameterizedTest
@MethodSource("fileProvider")
void testFile(File f) {
    // Your test comes here
}

static Stream<File> fileProvider() {
    return Arrays.asList(new File(".").list()).stream();
}

JUnit 5 DynamicTests

JUnit 5 는 또한 정적 메소드를 DynamicTest통해에서 생성되는 a 개념을 통해이를 지원합니다 .@TestFactorydynamicTest

import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;

import java.util.stream.Stream;

@TestFactory
public Stream<DynamicTest> testFiles() {
    return Arrays.asList(new File(".").list())
            .stream()
            .map((file) -> dynamicTest(
                    "Test for file: " + file,
                    () -> { /* Your test comes here */ }));
}

IDE (여기서 IntelliJ)에서 실행되는 테스트는 다음과 같이 표시됩니다.

IntelliJ의 출력


3

JUnit 3 에서는 파일을 나열 TestSuite하는 tests()메서드를 상속 하고 재정 의하여 가능해야하며 , 각각의 하위 클래스 인스턴스를 반환 할 TestCase때 생성자 매개 변수로 파일 이름을 사용하고 생성자에 제공된 파일을 테스트하는 테스트 메서드가 있어야합니다.

JUnit 4에서는 더 쉬울 수 있습니다.


2

JUnitParams 라이브러리 사용을 고려할 수 있으므로 몇 가지 더 깨끗한 옵션이 있습니다.

@org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class)
public class ParameterizedTest {

    @org.junit.Test
    @junitparams.Parameters(method = "data")
    public void test1(File file) throws Exception {  }

    @org.junit.Test
    @junitparams.Parameters(method = "data")
    public void test2(File file) throws Exception {  }

    public static File[] data() {
        return new File[] { new File("path1"), new File("path2") };
    }
}

@org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class)
public class ParameterizedTest {

    @org.junit.Test
    @junitparams.Parameters(value = { "path1", "path2" })
    public void test1(String path) throws Exception {
        File file = new File(path);
    }

    @org.junit.Test
    @junitparams.Parameters(value = { "path1", "path2" })
    public void test2(String path) throws Exception {
        File file = new File(path);
    }
}

여기에서 더 많은 사용 샘플을 볼 수 있습니다 .

또한 JUnitParams에 대한, 그것으로 파라미터 테스트를을 writting 이유 것은 더 쉽고 읽을 수 :

JUnitParams 프로젝트는 JUnit에 새로운 실행기를 추가하고 JUnit> = 4.6에 대해 훨씬 쉽고 읽기 쉬운 매개 변수 테스트를 제공합니다.

표준 JUnit Parametrised 러너와의 주요 차이점 :

  • 보다 명시 적-매개 변수는 클래스 필드가 아닌 테스트 메소드 매개 변수에 있습니다.
  • 적은 코드-매개 변수를 설정하기 위해 생성자가 필요하지 않습니다.
  • 한 클래스에서 매개 변수화되지 않은 메소드와 매개 변수화되지 않은 메소드를 혼합 할 수 있습니다.
  • 매개 변수는 CSV 문자열 또는 매개 변수 제공자 클래스에서 전달할 수 있습니다.
  • 매개 변수 제공자 클래스는 원하는만큼 메소드를 제공하는 매개 변수를 가질 수 있으므로 다른 케이스를 그룹화 할 수 있습니다.
  • 매개 변수를 제공하는 테스트 메소드를 가질 수 있습니다 (더 이상 외부 클래스 또는 정적 없음).
  • IDE에서 실제 매개 변수 값을 볼 수 있습니다 (JUnit의 Parametrised에서는 매개 변수의 연속 수만 표시됨)

1

TestNG가 옵션 인 경우 DataProviders와 함께 매개 변수를 사용할 수 있습니다 .

각 개별 파일의 테스트 결과는 텍스트 기반 보고서 또는 Eclipse의 TestNG 플러그인 UI에 표시됩니다. 실행 된 총 테스트 수는 각 파일을 개별적으로 계산합니다.

이 동작은 모든 결과가 하나의 "이론"항목에 집중되고 1 개의 테스트로만 계산 되는 JUnit Theories 와 다릅니다 . JUnit에서 별도의 결과보고를 원하는 경우 매개 변수화 된 테스트를 시도 할 수 있습니다. .

테스트 및 입력

public class FileTest {

    @DataProvider(name="files")
    public File[][] getFiles(){
        return new File[][] {
            { new File("file1") },
            { new File("file2") }
        };
        // or scan a directory
    }

    @Test(dataProvider="files")
    public void testFile(File file){
        //run tests on file
    }
}

예제 출력

PASSED: testFile(file1)
PASSED: testFile(file2)

===============================================
    Default test
    Tests run: 2, Failures: 0, Skips: 0
===============================================

나는 이론에 대해 잘 모르지만 JUnit의 매개 변수화 된 테스트는 함께 묶이지 않고 Eclipse에서 별도로 표시됩니다.
Hans-Peter Störr

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.