Тест JUnit з динамічною кількістю тестів


95

У нашому проекті у мене є кілька тестів JUnit, які, наприклад, беруть кожен файл із каталогу та запускають на ньому тест. Якщо я застосую testEveryFileInDirectoryметод у цьому, TestCaseце відображатиметься лише як один тест, який може провалитися або бути успішним. Але мене цікавлять результати кожного окремого файлу. Як я можу написати TestCase/ TestSuiteтаке, щоб кожен файл відображався як окремий тест, наприклад, у графічному TestRunner Eclipse? (Кодування явного методу тестування для кожного файлу не є можливим.)

Порівняйте також питання 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 4 кращий, ніж метод JUnit 3, наведений в іншій відповіді, оскільки JUnit 3 плутає запуску тесту eclipse, а за допомогою методу JUnit 4 ви можете повторно виконати тести тощо. Мені тільки цікаво, як я можу мати eclipse, щоб показати назва тесту - воно показує лише [0], [1] тощо
Hans-Peter Störr

@hstoerr, схоже, це буде в наступному випуску JUnit :-) github.com/KentBeck/junit/commit/…
rescdsk

Як би ви це перетворили, якщо хочете, щоб кожен запуск [з іншою комбінацією даних] змінював назву тестового запуску? [Тобто файл Path1 тестуватиметься як: test1Path1, test2Path?
monksy


27

ТОП 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 також підтримує це через поняття a DynamicTest, яке має бути сформовано в a @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), будуть відображатися таким чином:

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

Проект JUnitParams додає новий бігун до JUnit та забезпечує набагато простіші та читабельніші параметризовані тести для JUnit> = 4,6.

Основні відмінності від стандартного бігуна JUnit Parametrised:

  • більш чітке - параметри знаходяться у параметрах методу тестування, а не в полях класу
  • менше коду - для налаштування параметрів вам не потрібен конструктор
  • Ви можете поєднувати параметризовані з непараметризованими методами в одному класі
  • params можна передавати як рядок CSV або з класу постачальника параметрів
  • клас постачальника параметрів може мати скільки завгодно методів, що надають параметри, так що ви можете групувати різні випадки
  • ви можете мати метод тестування, який надає параметри (більше немає зовнішніх класів чи статики)
  • ви можете бачити фактичні значення параметрів у своїй IDE (у JUnit's Parametrised це лише послідовні номери параметрів)

1

Якщо ви можете вибрати TestNG , ви можете використовувати параметри з DataProviders .

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

Ця поведінка відрізняється від теорій JUnit , в яких всі результати поєднуються під одним входом "теорії" і враховуються лише як 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
===============================================

Я не знаю про теорії, але параметризовані тести в JUnit відображаються окремо в затемненні, а не в сукупності.
Hans-Peter Störr

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.