Útmutató a dinamikus tesztekhez, Junit 5

1. Áttekintés

A dinamikus tesztelés egy új programozási modell, amelyet a JUnit 5 vezetett be. Ebben a cikkben megnézzük, hogy pontosan mi a dinamikus teszt, és hogyan lehet létrehozni.

Ha még nem ismeri a JUnit 5 alkalmazást, érdemes megnéznie a JUnit 5 előnézetét és elsődleges útmutatónkat.

2. Mi az a DynamicTest?

A standard tesztek a következővel lettek kiegészítve: @Teszt az annotáció statikus teszt, amelyet a fordítás idején teljesen meghatároznak. A DynamicTest futás közben generált teszt. Ezeket a teszteket egy gyári módszerrel állítják elő, amelyhez a @TestFactory annotáció.

A @TestFactory metódusnak vissza kell adnia a Folyam, Gyűjtemény, Iterálható, vagy Iterátor nak,-nek DynamicTest példányok. Ha bármi mást ad vissza, akkor a JUnitException mivel az érvénytelen visszatérési típusokat nem lehet felismerni fordításkor. Ettől eltekintve a @TestFactory módszer nem lehet állhatatosc vagy magán.

A DynamicTests másként hajtják végre, mint a szabvány @Teszts nem támogatják az életciklus-visszahívásokat. Vagyis a @BeforeEach és a @AfterEach módszerek nem lesznek meghívva a DynamicTests.

3. Teremtés DynamicTests

Először vessünk egy pillantást a létrehozás különböző módjaira DynamicTests.

Az itt szereplő példák nem dinamikus jellegűek, de jó kiindulópontot jelentenek az igazán dinamikus példák létrehozásához.

Létrehozunk egy Gyűjtemény nak,-nek DynamicTest:

@TestFactory Collection dynamicTestsWithCollection () {return Arrays.asList (DynamicTest.dynamicTest ("Teszt hozzáadása", () -> assertEquals (2, Math.addExact (1, 1))), DynamicTest.dynamicTest ("Testsorozat", ) -> assertEquals (4, Math.multiplyExact (2, 2)))); }

A @TestFactory A módszer azt mondja a JUnitnek, hogy ez egy gyár dinamikus tesztek létrehozására. Mint láthatjuk, csak a Gyűjtemény nak,-nek DynamicTest. Mindegyik DynamicTest két részből áll, a teszt vagy a megjelenítendő névből, és egy Végrehajtható.

A kimenet tartalmazza a megjelenítési nevet, amelyet átadtunk a dinamikus teszteknek:

Teszt hozzáadása (dynamicTestsWithCollection ()) Szorzás teszt (dynamicTestsWithCollection ())

Ugyanez a teszt módosítható az Iterálható, Iterátor, vagy a Folyam:

@TestFactory Iterable dynamicTestsWithIterable () {return Arrays.asList (DynamicTest.dynamicTest ("Add test", () -> assertEquals (2, Math.addExact (1, 1))), DynamicTest.dynamicTest ("Multiply Test", ( ) -> assertEquals (4, Math.multiplyExact (2, 2)))); } @TestFactory Iterator dynamicTestsWithIterator () {return Arrays.asList (DynamicTest.dynamicTest ("Teszt hozzáadása", () -> assertEquals (2, Math.addExact (1, 1))), DynamicTest.dynamicTest ("Szorzás teszt", () -> assertEquals (4, Math.multiplyExact (2, 2)))) .iterátor (); } @TestFactory Stream dynamicTestsFromIntStream () {return IntStream.iterate (0, n -> n + 2) .limit (10) .mapToObj (n -> DynamicTest.dynamicTest ("test" + n, () -> assertTrue (n % 2 == 0))); }

Felhívjuk figyelmét, hogy ha a @TestFactory visszatér a Folyam, majd az összes teszt végrehajtása után automatikusan bezáródik.

A kimenet nagyjából megegyezik az első példával. Ez tartalmazza a megjelenítési nevet, amelyet átadunk a dinamikus tesztnek.

4. A. Létrehozása Folyam nak,-nek DynamicTests

A bemutató céljából vegye fontolóra a DomainNameResolver amely IP-címet ad vissza, amikor a domain nevet átadjuk bemenetként.

Az egyszerűség kedvéért vessünk egy pillantást gyári módszerünk magas szintű csontvázára:

@TestFactory Stream dynamicTestsFromStream () {// minta bemenet és kimenet List inputList = Arrays.asList ("www.somedomain.com", "www.anotherdomain.com", "www.yetanotherdomain.com"); List outputList = Arrays.asList ("154.174.10.56", "211.152.104.132", "178.144.120.156"); // bemeneti generátor, amely bemeneteket generál az inputList /*...code használatával ... * / // egy olyan megjelenítési név generátor, amely // más nevet hoz létre a bemenet alapján // a teszt végrehajtója, amelynek valójában megvan a // logikája a teszteset végrehajtásához /*...code itt ... * / // mindent összevonva ad vissza egy Stream of DynamicTest /*...code ide ... * /}

Nem sok kód kapcsolódik a következőhöz: DynamicTest itt eltekintve a @TestFactory annotáció, amelyet már ismerünk.

A két Tömb listas lesz felhasználva bemenetként a DomainNameResolver illetve a várható kibocsátás.

Most nézzük meg a bemeneti generátort:

Iterátor inputGenerator = inputList.iterator ();

A bemeneti generátor nem más, mint egy Iterátor nak,-nek Húr. Használja a mi inputList és egyesével adja vissza a domain nevet.

A megjelenített név generátor meglehetősen egyszerű:

Funkció displayNameGenerator = (bemenet) -> "Megoldás:" + bemenet;

A megjelenítési név generátorának csak az a feladata, hogy megjelenítési nevet adjon a tesztesethez, amelyet a JUnit jelentésekben vagy az IDE JUnit lapján fognak használni.

Itt csak a domain nevet használjuk egyedi nevek előállításához az egyes tesztekhez. Nem szükséges egyedi neveket létrehozni, de bármilyen hiba esetén segítséget nyújt. Ennek birtokában meg tudjuk mondani azt a domain nevet, amelynek sikertelen volt a tesztesete.

Most nézzük meg a tesztünk központi részét - a teszt végrehajtási kódját:

DomainNameResolver resolver = új DomainNameResolver (); ThrowingConsumer testExecutor = (input) -> {int id = inputList.indexOf (input); assertEquals (outputList.get (id), resolver.resolveDomain (input)); };

Használtuk a DobásFogyasztó, ami a @FunctionalInterface a teszteset megírásához. Az adatgenerátor által generált minden bemenetre lekérjük a várt kimenetet a outputList és a tényleges kimenet egy DomainNameResolver.

Az utolsó rész egyszerűen az összes darab összeállítása és visszatérés a Folyam nak,-nek DynamicTest:

return DynamicTest.stream (inputGenerator, displayNameGenerator, testExecutor);

Ez az. A teszt futtatása megjeleníti a megjelenítési név-generátor által meghatározott neveket tartalmazó jelentést:

Megoldás: www.somedomain.com (dynamicTestsFromStream ()) Megoldás: www.anotherdomain.com (dynamicTestsFromStream ()) Megoldás: www.yetanotherdomain.com (dynamicTestsFromStream ())

5. A DynamicTest A Java 8 szolgáltatások használata

Az előző szakaszban írt tesztgyár drasztikusan javítható a Java 8 szolgáltatásainak használatával. A kapott kód sokkal tisztább lesz, és kevesebb sorban írható:

@TestFactory Stream dynamicTestsFromStreamInJava8 () {DomainNameResolver resolver = new DomainNameResolver (); List domainNames = Arrays.asList ("www.somedomain.com", "www.anotherdomain.com", "www.yetanotherdomain.com"); List outputList = Arrays.asList ("154.174.10.56", "211.152.104.132", "178.144.120.156"); return inputList.stream () .map (dom -> DynamicTest.dynamicTest ("Feloldás:" + dom, () -> {int id = inputList.indexOf (dom); assertEquals (outputList.get (id), resolver.resolveDomain (dom));})); }

A fenti kódnak ugyanaz a hatása, mint amit az előző szakaszban láttunk. A inputList.stream (). map () biztosítja a bemenetek áramát (bemeneti generátor). Az első érv a dynamicTest () a megjelenített név generátorunk ("Megoldás:" + dom), míg a második érv, a lambda, a teszt végrehajtónk.

A kimenet ugyanaz lesz, mint az előző szakaszban.

6. További példa

Ebben a példában tovább vizsgáljuk a dinamikus tesztek erejét a bemenetek szűrésére a tesztesetek alapján:

@TestFactory Stream dynamicTestsForEmployeeWorkflows () {List inputList = Arrays.asList (új alkalmazott (1, "Fred"), új alkalmazott (2), új alkalmazott (3, "John")); EmployeeDao dao = új EmployeeDao (); Stream saveEmployeeStream = inputList.stream () .map (emp -> DynamicTest.dynamicTest ("saveEmployee:" + emp.toString (), () -> {Employee return = dao.save (emp.getId ()); assertEquals ( return.getId (), emp.getId ());})); Stream saveEmployeeWithFirstNameStream = inputList.stream () .filter (emp ->! Emp.getFirstName (). IsEmpty ()) .map (emp -> DynamicTest.dynamicTest ("saveEmployeeWithName" + emp.toString (), () -> { Visszatérő alkalmazott = dao.save (emp.getId (), emp.getFirstName ()); assertEquals (return.getId (), emp.getId ()); assertEquals (return.getFirstName (), emp.getFirstName ()); })); return Stream.concat (saveEmployeeStream, saveEmployeeWithFirstNameStream); }

A mentés (hosszú) módszer csak a munkavállalói azonosító. Ezért felhasználja az összes Munkavállaló példányok. A mentés (hosszú, karakterlánc) módszer igényeinek keresztnév eltekintve a munkavállalói azonosító. Ezért kiszűri a Munkavállaló példányok nélkül keresztnév.

Végül egyesítjük mindkét adatfolyamot, és az összes tesztet egyetlenként adjuk vissza Folyam.

Most nézzük meg a kimenetet:

saveEmployee: Employee [id = 1, keresztnév = Fred] (dynamicTestsForEmployeeWorkflows ()) saveEmployee: Employee [id = 2, firstName =] (dynamicTestsForEmployeeWorkflows ()) saveEmployee: Employee [id = 3, firstName = Johnflow (dinamikusTesztek) saveEmployeeWithNameEmployee [id = 1, keresztnév = Fred] (dynamicTestsForEmployeeWorkflows ()) saveEmployeeWithNameEmployee [id = 3, keresztnév = John] (dynamicTestsForEmployeeWorkflows ())

7. Következtetés

A paraméterezett tesztek a cikk számos példáját felválthatják. A dinamikus tesztek azonban eltérnek a paraméterezett tesztektől, mivel támogatják a teljes teszt életciklust, míg a paraméterezett tesztek nem.

Ezenkívül a dinamikus tesztek nagyobb rugalmasságot biztosítanak a bemenet létrehozásának és a tesztek végrehajtásának módjában.

A JUnit 5 a kiterjesztéseket részesíti előnyben a funkciók helyett. Ennek eredményeként a dinamikus tesztek fő célja egy kiterjesztési pont biztosítása harmadik fél keretrendszereihez vagy kiterjesztéseihez.

Az 5. JUnit egyéb funkcióiról az 5. JUnit ismételt tesztjeiről szóló cikkünkben olvashat bővebben.

Ne felejtse el megnézni a cikk teljes forráskódját a GitHubon.


$config[zx-auto] not found$config[zx-overlay] not found