Test JUnit z dynamiczną liczbą testów

W naszym projekcie mam kilka testów JUnit , które np. pobierają każdy plik z katalogu i uruchamiają na nim test. Jeśli zaimplementuję metodę testEveryFileInDirectory w TestCase to pokazuje się jako tylko jeden test, który może się nie powieść lub odnieść sukces. Ale jestem zainteresowany wynikami KAŻDEGO pliku. Jak mogę napisać TestCase / TestSuite taki, że każdy plik pojawia się jako osobny test np. w graficznym teście Eclipse? (Kodowanie jawnej metody testowania dla każdego pliku nie jest opcją.)

Porównaj również pytanie Parametryzowało test z nazwą w Eclipse Testrunner .

Author: Community, 2008-12-11

7 answers

Spójrz na sparametryzowane testy W JUnit 4.

Właściwie to zrobiłem to kilka dni temu. Postaram się wyjaśnić ...

Najpierw Zbuduj swoją klasę testową normalnie, jak w przypadku testów z jednym plikiem wejściowym. Udekoruj swoją klasę:

@RunWith(Parameterized.class)

Zbuduj jeden konstruktor, który pobiera dane wejściowe, które zmienią się w każdym wywołaniu testowym (w tym przypadku może to być sam plik)

Następnie zbuduj statyczną metodę, która zwróci Collection tablic. Każda tablica w zbiorze będzie zawierać argumenty wejściowe dla konstruktora klasy, np. plik. Udekoruj tą metodą:

@Parameters
Oto przykładowe zajęcia.
@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;
    }
}

Sprawdź również ten przykład

 95
Author: bruno conde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-14 09:24:22

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

}
 27
Author: McDowell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-11 11:04:15

Junit 5 Testy Parametryzowane

JUnit 5 sparametryzowane testy wspierają to, umożliwiając użycie metody jako źródła danych :

@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 wspiera to również poprzez pojęcie DynamicTest, które ma być generowane w @TestFactory, za pomocą metody statycznej 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 */ }));
}

Testy uruchamiane w Twoim IDE (IntelliJ tutaj) będą wyświetlane w następujący sposób:

Wyjście w IntelliJ

 6
Author: avandeursen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-08 17:26:10

Powinno być możliwe w JUnit 3 poprzez dziedziczenie z TestSuite i nadpisywanie metody tests() do listy plików i dla każdego zwracania instancji podklasy TestCase, która przyjmuje nazwę pliku jako parametr konstruktora i ma metodę testową, która testuje plik podany w konstruktorze.

W JUnit 4 może być jeszcze łatwiej.
 3
Author: Michael Borgwardt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-11 10:16:57

Możesz rozważyć użycie JUnitParams library , więc będziesz miał jeszcze kilka (czystszych) opcji:

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

Możesz zobaczyć więcej próbek użycia tutaj .

Dodatkowo o JUnitParams, dlaczego pisanie parametryzowanych testów z nim jest łatwiejsze i czytelniejsze:

Projekt JUnitParams dodaje nowego biegacza do JUnit i zapewnia wiele Å‚atwiejsze i czytelne parametryzowane testy dla JUnit > = 4.6.

Główne różnice w stosunku do standard JUnit Parametryzowany biegacz:

  • bardziej jednoznaczne-params sÄ… w metodzie testowej params, Nie pola klasy
  • mniej kodu - nie potrzebujesz konstruktora, aby ustawić parametry
  • możesz mieszać parametryzowane z nieparametryzowanymi metodami w jednej klasie
  • W przeciwieÅ„stwie do innych formatów, nie można ich używać.]}
  • parameters provider class może mieć tyle parametrów dostarczajÄ…cych metody, ile chcesz, dziÄ™ki czemu możesz grupować różne przypadki
  • możesz mieć metodÄ™ testowÄ…, która dostarcza parametrów (nie ma już zewnÄ™trznych klas ani statyki)
  • możesz zobaczyć rzeczywiste wartoÅ›ci parametrów w IDE (w Parametryzowanym JUnit jest to tylko kolejne liczby parametrów)
 2
Author: falsarella,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-20 21:09:28

Jeśli TestNG jest opcją, możesz użyć parametrów z Dataproviderami .

Test KAŻDEGO pliku będzie miał swój wynik pokazany w raporcie tekstowym lub interfejsie wtyczki TestNG Eclipse. Liczba wszystkich przeprowadzonych testów będzie liczyć każdy z plików osobno.

To zachowanie różni się od teorii JUnit , w której wszystkie wyniki są sumowane pod jednym wpisem "teorii" i liczone tylko jako 1 test. Jeśli chcesz mieć oddzielne raportowanie wyników w JUnit, możesz spróbować Testy Parametryzowane .

Test i wejścia

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

Przykładowe wyjście

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

===============================================
    Default test
    Tests run: 2, Failures: 0, Skips: 0
===============================================
 1
Author: Ben Hutchison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-18 20:07:12

Miałem podobny problem i skończyło się na napisaniu prostego JUnit 4 runner, który pozwala med dynamicznie generować testy.

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

 0
Author: Kimble,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-08 19:04:29