Gyors JUnit vs TestNG összehasonlítás

1. Áttekintés

A JUnit és a TestNG kétségtelenül a két legnépszerűbb egységteszt-keretrendszer a Java ökoszisztémában. Míg a JUnit maga inspirálja a TestNG-t, megadja annak megkülönböztető jellemzőit, és a JUnittel ellentétben funkcionális és magasabb szintű tesztelésre szolgál.

Ebben a bejegyzésben megvitatjuk és összehasonlítjuk ezeket a keretrendszereket, áttekintve azok jellemzőit és általános használati eseteit.

2. Tesztelje a telepítést

Tesztesetek írása közben gyakran végrehajtani kell néhány konfigurációs vagy inicializálási utasítást a tesztfuttatások előtt, és némi tisztítást is a tesztek befejezése után. Értékeljük ezeket mindkét keretben.

A JUnit két szinten kínál inicializálást és tisztítást, minden módszer és osztály előtt és után. Nekünk van @BeforeEach, @AfterEach - annotációk módszer szinten és @BeforeAll és @Végül osztály szinten:

public class SummationServiceTest {privát statikus Lista számok; @BeforeAll public static void inicializálja () {számok = új ArrayList (); } @AfterAll nyilvános statikus void tearDown () {számok = null; } @BeforeEach public void runBeforeEachTest () {számok.add (1); számok.add (2); számok.add (3); } @AfterEach public void runAfterEachTest () {számok.clear (); } @Test public void givenNumbers_sumEquals_thenCorrect () {int összeg = számok.folyam (). Csökkent (0, Egész szám :: összeg); assertEquals (6, összeg); }}

Ne feledje, hogy ez a példa a JUnit 5-öt használja. Az előző JUnit 4 verzióban a @Előtt és @Utána jelöléssel, amelyek egyenértékűek a @BeforeEach és @AfterEach. Hasonlóképpen, @BeforeAll és @Végül a JUnit 4 helyettesítői @Óra előtt és @Óra után.

Hasonló a JUnithez, A TestNG inicializálást és tisztítást is biztosít módszer és osztály szinten. Míg @Óra előtt és @Óra után osztály szinten változatlanok maradnak, a metódus szintű kommentárok @BeforeMethod és @AfterMethod:

@BeforeClass public void inicializálás () {számok = új ArrayList (); } @AfterClass public void tearDown () {számok = null; } @BeforeMethod public void runBeforeEachTest () {számok.add (1); számok.add (2); számok.add (3); } @AfterMethod public void runAfterEachTest () {számok.clear (); }

A TestNG a következőket is kínálja: @BeforeSuite, @AfterSuite, @BeforeGroup és @AfterGroup kommentárok a csomag- és csoportszintű konfigurációkhoz:

@BeforeGroups ("pozitív_tesztek") public void runBeforeEachGroup () {számok.add (1); számok.add (2); számok.add (3); } @AfterGroups ("negatív_tesztek") public void runAfterEachGroup () {számok.clear (); }

Használhatjuk a @BeforeTest és @AfterTest ha bármilyen konfigurációra van szükségünk a tag a TestNG XML konfigurációs fájlban:

Ne feledje, hogy a @Óra előtt és @Óra után A metódusnak statikusnak kell lennie a JUnit-ben. Összehasonlításképpen: a TestNG metódus deklarációban nincsenek ezek a korlátozások.

3. A tesztek figyelmen kívül hagyása

Mindkét keret támogatja a tesztesetek figyelmen kívül hagyását, bár egészen másképp csinálják. A JUnit felajánlja a @Figyelmen kívül hagyni kommentár:

@Ignore @Test public void givenNumbers_sumEquals_thenCorrect () {int összeg = számok.folyam (). Csökkent (0, Egész szám :: összeg); Assert.assertEquals (6, összeg); }

míg a TestNG használja @Teszt logikai értékű „engedélyezett” paraméterrel igaz vagy hamis:

@ Teszt (engedélyezett = hamis) public void givenNumbers_sumEquals_thenCorrect () {int összeg = számok.folyam.reduce (0, Egész szám :: összeg); Assert.assertEquals (6, összeg); }

4. Együtt futó tesztek

A tesztek együttes futtatása mindkettőben lehetséges JUnit és a TestNG, de különböző módon csinálják.

Használhatjuk a @RunWith,@SelectPackages, és @SelectClasses kommentárok a tesztesetek csoportosításához és futtatásához csomagként JUnit 5. A csomag olyan tesztesetek gyűjteménye, amelyeket csoportosítva összeállíthatunk és egyetlen tesztként futtathatunk.

Ha különféle csomagok teszteseteit akarjuk csoportosítani, hogy az a-n belül fussanak együtt Lakosztály szükségünk van a @SelectPackages kommentár:

@RunWith (JUnitPlatform.class) @SelectPackages ({"org.baeldung.java.suite.childpackage1", "org.baeldung.java.suite.childpackage2"}}) public class SelectPackagesSuiteUnitTest {}

Ha azt akarjuk, hogy meghatározott tesztosztályok futjanak együtt, JUnit 5 biztosítja a rugalmasságot @SelectClasses:

@RunWith (JUnitPlatform.class) @SelectClasses ({Class1UnitTest.class, Class2UnitTest.class}) nyilvános osztály SelectClassesSuiteUnitTest {}

Korábban használta JUnit 4, elértük a tesztek csoportosítását és futtatását @Lakosztály kommentár:

@RunWith (Suite.class) @ Suite.SuiteClasses ({RegistrationTest.class, SignInTest.class}) nyilvános osztály SuiteTest {}

A TestNG-ben XML fájl segítségével csoportosíthatjuk a teszteket:

Ez azt jelzi RegistrationTest és SignInTest együtt fognak futni.

Az osztályok csoportosítása mellett a TestNG metódusokat is csoportosíthat a @ használatávalTeszt (csoportok = „csoportNév”) kommentár:

@Test (groups = "regresszió") public void givenNegativeNumber_sumLessthanZero_thenCorrect () {int összeg = számok.folyam (). Csökkent (0, Egész szám :: összeg); Assert.assertTrue (összeg <0); }

Használjunk XML-t a csoportok végrehajtásához:

Ez végrehajtja a csoporthoz címkézett vizsgálati módszert regresszió.

5. Kivételek tesztelése

A megjegyzésekkel történő kivételes tesztelés funkciója elérhető a JUnit és a TestNG egyaránt.

Először hozzunk létre egy osztályt egy olyan módszerrel, amely kivételt hoz:

public class Calculator {public double divide (double a, double b) {if (b == 0) {dobj új DivideByZeroException-t ("Az osztó nem lehet egyenlő nullával!"); } return a / b; }}

Ban ben 5. JUnit használhatjuk a assertThrows API a kivételek teszteléséhez:

@Test public void whenDividerIsZero_thenDivideByZeroExceptionIsThrown () {Számológép kalkulátor = új Számológép (); assertThrows (DivideByZeroException.class, () -> calculator.divide (10, 0)); }

Ban ben JUnit 4, segítségével elérhetjük ezt @Test (várható = DivideByZeroException.class) a teszt API-n keresztül.

És a TestNG segítségével ugyanazt is megvalósíthatjuk:

@Test (várhatóExceptions = ArithmeticException.class) public void givenNumber_whenThrowsException_thenCorrect () {int i = 1/0; }

Ez a szolgáltatás azt jelenti, hogy milyen kivétel van a kódrészletből, ez egy teszt része.

6. Paraméteres tesztek

A paraméterezett egységtesztek hasznosak ugyanazon kód teszteléséhez több feltétel mellett. A paraméterezett egységtesztek segítségével felállíthatunk egy vizsgálati módszert, amely valamilyen adatforrásból nyeri az adatokat. A fő gondolat az, hogy az egység tesztmódszerét újrafelhasználhatóvá tegye, és más bemeneti készlettel teszteljen.

Ban ben 5. JUnit, az az előnyünk, hogy a tesztelési módszerek közvetlenül a konfigurált forrásból fogyasztanak argumentumokat. Alapértelmezés szerint az 5. JUnit nyújt néhányat forrás kommentárok, például:

  • @ValueSource: ezt egy típusú értéktömbdel használhatjuk Rövid, Byte, Int, Long, Float, Double, Char, és Húr:
@ParameterizedTest @ValueSource (stringek = {"Hello", "World"}) void givenString_TestNullOrNot (String szó) {assertNotNull (word); }
  • @EnumSource - passzok Enum konstansok a vizsgálati módszer paramétereként:
@ParameterizedTest @EnumSource (érték = PizzaDeliveryStrategy.class, nevek = {"EXPRESS", "NORMAL"}) érvénytelen adottEnum_TestContainsOrNot (PizzaDeliveryStrategy timeUnit) {assertTrue (EnumSet.of (PizzaDeliveryStrategy.PizzaDeliveryStrategy). ; }
  • @MethodSource - ppatakokat generáló külső módszereket elemez:
statikus adatfolyam WordDataProvider () {return Stream.of ("foo", "bar"); } @ParameterizedTest @MethodSource ("wordDataProvider") void givenMethodSource_TestInputStream (String argumentum) {assertNotNull (argumentum); }
  • @CsvSource - CSV-értékeket használ a paraméterek forrásaként:
@ParameterizedTest @CsvSource ({"1, autó", "2, ház", "3, vonat"}) érvénytelen adottCSVSource_TestContent (int id, karakterlánc szó) {assertNotNull (id); assertNotNull (szó); }

Hasonlóképpen vannak más forrásaink is @CsvFileSource ha el kell olvasnunk egy CSV fájlt a classpath és @ArgumentSource egyedi, újrafelhasználható megadásához ArgumentProvider.

Ban ben JUnit 4, a teszt osztályt meg kell jelölni @RunWith hogy paraméterezett osztály legyen és @Paraméter hogy jelölje a paraméterértékeket az egység tesztnél.

A TestNG-ben a @ segítségével paraméterezhetjük a teszteketParaméter vagy @DataProvider annotációk. Az XML fájl használata közben jelölje meg a vizsgálati módszert @ -valParaméter:

@Test @Parameters ({"value", "isEven"}) public void givenNumberFromXML_ifEvenCheckOK_thenCorrect (int érték, logikai isEven) {Assert.assertEquals (isEven, érték% 2 == 0); }

és adja meg az adatokat az XML fájlban:

Bár az információk felhasználása az XML fájlban egyszerű és hasznos, bizonyos esetekben összetettebb adatokat kell megadnia.

Ehhez használhatjuk a @DataProvider annotáció, amely lehetővé teszi számunkra a tesztelési módszerek összetett paramétertípusainak feltérképezését.

Itt van egy példa a használatra @DataProvider primitív adattípusok esetében:

@DataProvider (név = "számok") nyilvános statikus objektum [] [] evenNumbers () {return new Object [] [] {{1, false}, {2, true}, {4, true}}; } @Test (dataProvider = "számok") public void givenNumberFromDataProvider_ifEvenCheckOK_thenCorrect (Egész szám, logikai érték várható) {Assert.assertEquals (várható,% 2 == 0 szám); }

És @DataProvider tárgyak esetében:

@Test (dataProvider = "numbersObject") public void givenNumberObjectFromDataProvider_ifEvenCheckOK_thenCorrect (Páros szám) {Assert.assertEquals (szám.isEven (), szám.getValue ()% 2 == 0); } @DataProvider (name = "numbersObject") public Object [] [] parameterProvider () {return new Object [] [] {{new EvenNumber (1, false)}, {new EvenNumber (2, true)}, {new Páros szám (4, igaz)}}; }

Ugyanígy az adatszolgáltató segítségével minden tesztelhető objektum létrehozható és visszaadható. Ez hasznos, ha olyan keretrendszerekkel integrálódik, mint a Spring.

Figyelje meg, hogy a TestNG-ben, mivel @DataProvider a metódusnak nem kell statikusnak lennie, több adatszolgáltatói módszert is használhatunk ugyanabban a tesztosztályban.

7. Teszt időkorlátja

Az időkorlátos tesztek azt jelentik, hogy egy tesztesetnek meg kell buknia, ha a végrehajtás egy meghatározott időn belül nem fejeződik be. A JUnit és a TestNG támogatása is időzítette a teszteket. Ban ben JUnit 5 időkorlát tesztet írhatunk:

@Test public void givenExecution_takeMoreTime_thenFail () dob InterruptedException {Assertions.assertTimeout (Durill.ofMillis (1000), () -> Thread.sleep (10000)); }

Ban ben JUnit 4 és a TestNG segítségével ugyanazt a tesztet elvégezhetjük a @ használatávalTeszt (időtúllépés = 1000)

@Test (timeOut = 1000) public void givenExecution_takeMoreTime_thenFail () {while (true); }

8. Függő tesztek

A TestNG támogatja a függőségi tesztelést. Ez azt jelenti, hogy egy vizsgálati módszer halmazában, ha az első teszt kudarcot vall, akkor minden későbbi függő tesztet átugorunk, és nem jelöljük meg sikertelennek, mint a JUnit esetében.

Vessünk egy pillantást egy olyan forgatókönyvre, ahol érvényesítenünk kell az e-mailt, és ha ez sikeres, folytatjuk a bejelentkezést:

@Test public void givenEmail_ifValid_thenTrue () {logikai érték = email.contains ("@"); Assert.assertEquals (érvényes, igaz); } @Test (dependOnMethods = {"adottEmail_ifValid_thenTrue"}) public void givenValidEmail_whenLoggedIn_thenTrue () {LOGGER.info ("E-mail {} érvényes >> bejelentkezés", e-mail); }

9. A teszt végrehajtásának sorrendje

Nincs meghatározott implicit sorrend, amelyben a tesztelési módszereket a JUnit 4-ben vagy a TestNG-ben hajtják végre. A metódusokat csak a Java Reflection API visszaadja. A 4. JUnit óta determinisztikusabb, de nem kiszámítható sorrendet használ.

A nagyobb kontroll érdekében a tesztosztályt a következőkkel jelöljük @FixMethodOrder annotáció és említsen meg egy módszer válogatót:

@FixMethodOrder (MethodSorters.NAME_ASCENDING) public class SortedTests {@Test public void a_givenString_whenChangedtoInt_thenTrue () {assertTrue (Integer.valueOf ("10") Integer instance); } @Test public void b_givenInt_whenChangedtoString_thenTrue () {assertTrue (String.valueOf (10) String példánya); }}

A MethodSorters.NAME_ASCENDING A paraméter a módszer metódusát rendezi a lexikográfiai sorrend szerint. Ezen a válogatón kívül van A MethodSorter.DEFAULT és a MethodSorter.JVM is.

Míg a TestNG néhány módot is kínál az ellenőrzés ellenőrzésére a tesztmódszer végrehajtásának sorrendjében. Mi biztosítjuk a kiemelten fontos paraméter a @Teszt kommentár:

@Test (prioritás = 1) public void givenString_whenChangedToInt_thenCorrect () {Assert.assertTrue (Integer.valueOf ("10") egész szám példánya); } @Test (prioritás = 2) public void givenInt_whenChangedToString_thenCorrect () {Assert.assertTrue (String.valueOf (23) String példánya); }

Figyelje meg, hogy az elsőbbség a prioritáson alapuló vizsgálati módszereket hívja meg, de nem garantálja, hogy az egyik szint tesztjei befejeződjenek, mielőtt a következő prioritási szintre hivatkoznak.

Néha, amikor funkcionális teszteseteket írunk a TestNG-ben, előfordulhat, hogy van egy egymásra épülő teszt, ahol a végrehajtás sorrendjének minden tesztfutásnál meg kell egyeznie. Ennek eléréséhez használnunk kell a metódusoktól függ paraméter a @Teszt annotáció, amint azt a korábbi szakaszban láttuk.

10. Egyéni teszt neve

Alapértelmezés szerint, amikor tesztet futtatunk, a tesztosztály és a vizsgálati módszer neve kiírásra kerül a konzolba vagy az IDE-be. JUnit 5 egyedülálló szolgáltatást nyújt, ahol megemlíthetünk egyedi leíró neveket az osztály- és tesztmódszerek használatához @Megjelenítendő név annotáció.

Ez a megjegyzés nem nyújt vizsgálati előnyöket, de könnyen olvasható és érthető vizsgálati eredményeket nyújt egy nem technikai személy számára is:

@ParameterizedTest @ValueSource (string = {"Hello", "World"}) @DisplayName ("Tesztelési módszer annak ellenőrzésére, hogy a bemenetek nem érvénytelenek-e") void givenString_TestNullOrNot (String szó) {assertNotNull (szó); }

Amikor a tesztet lefuttatjuk, a kimenet a megjelenített nevet mutatja a metódus neve helyett.

Most, be TestNG egyéni név megadására nincs mód.

11. Következtetés

A JUnit és a TestNG is modern eszköz a Java ökoszisztémában történő teszteléshez.

Ebben a cikkben gyorsan áttekintettük a tesztek írásának különféle módszereit a két tesztkeret mindegyikével.

Az összes kódrészlet megvalósítása megtalálható a TestNG és a junit-5 Github projektben.