Тест JUnit с динамическим количеством тестов - PullRequest
91 голосов
/ 11 декабря 2008

В нашем проекте у меня есть несколько JUnit тестов, например. взять каждый файл из каталога и запустить тест на нем. Если я реализую метод testEveryFileInDirectory в TestCase, это будет выглядеть как один тест, который может быть неудачным или успешным. Но меня интересуют результаты по каждому отдельному файлу. Как я могу написать TestCase / TestSuite, чтобы каждый файл отображался как отдельный тест, например в графическом TestRunner из Eclipse? (Кодирование явного метода тестирования для каждого файла не вариант.)

Сравните также вопрос ParameterizedTest с именем в Eclipse Testrunner .

Ответы [ 7 ]

98 голосов
/ 11 декабря 2008

Взгляните на Параметризованные тесты в 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;
    }
}

Также проверьте это пример

27 голосов
/ 11 декабря 2008

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

}
8 голосов
/ 27 марта 2017

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, которое должно быть сгенерировано в @TestFactory с помощью статического метода dynamicTest.

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 здесь), будут отображаться так:

Output in IntelliJ

3 голосов
/ 11 декабря 2008

Должно быть возможно в JUnit 3 путем наследования от TestSuite и переопределения метода tests() для вывода списка файлов и для каждого возврата экземпляра подкласса TestCase, который принимает имя файла в качестве параметра конструктора и имеет тест метод, который проверяет файл, указанный в конструкторе.

В JUnit 4 это может быть даже проще.

2 голосов
/ 21 мая 2015

Вы можете рассмотреть возможность использования библиотеки 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, почему написание параметризованных тестов с ним проще и удобнее для чтения :

Проект JUnitParams добавляет нового бегуна в JUnit и предоставляет много более простые и удобочитаемые параметризованные тесты для JUnit> = 4.6.

Основные отличия от стандартного бегунка JUnit Parametrised:

  • более явно - параметры находятся в параметрах метода тестирования, а не в полях класса
  • меньше кода - вам не нужен конструктор для настройки параметров
  • вы можете смешивать параметризованные и непараметризированные методы в одном классе
  • параметры могут быть переданы в виде строки CSV или из класса поставщика параметров
  • Параметр класса провайдера может иметь столько параметров, которые предоставляют методы, сколько вы хотите, так что вы можете группировать разные случаи
  • у вас может быть метод теста, который предоставляет параметры (больше нет внешних классов или статики)
  • вы можете видеть фактические значения параметров в вашей IDE (в Parametrised JUnit это только последовательные числа параметров)
1 голос
/ 17 июля 2014

Если опция TestNG является опцией, вы можете использовать Параметры с DataProviders .

Результаты каждого отдельного файла будут отображаться в текстовом отчете или в пользовательском интерфейсе плагина Eclipse TestNG. Общее количество выполненных тестов будет подсчитывать каждый из ваших файлов в отдельности.

Это поведение отличается от JUnit Theories , в котором все результаты объединены в одну запись "теории" и считаются только 1 тестом Если вам нужна отдельная отчетность о результатах в 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
===============================================
0 голосов
/ 08 апреля 2016

У меня была похожая проблема, и в итоге я написал простой JUnit 4 runner, который позволяет med динамически генерировать тесты.

https://github.com/kimble/junit-test-factory

...