JUnit Paraméteres teszt példával a @Parameters használatával

⚡ Okos összefoglaló

Paraméterezett tesztek JUnit ugyanazt a tesztmetódust többször is futtatni különböző bemeneti értékekkel, így egy módszer számos forgatókönyvet lefed. A @RunWith és @Parameters annotációk minden iterációhoz biztosítják az adathalmazt.

  • 🔘 Adatforrás: Egy statikus @Parameters metódus tömbök egy gyűjteményét adja vissza, és minden tömb egy teszt iterációvá válik.
  • ☑️ Futó: A @RunWith(Parameterized.class) lecseréli az alapértelmezett blokkotJUnit4ClassRunner és adatsoronként egyszer újraépíti az osztályt.
  • Építész: Egy nyilvános konstruktor egyetlen sornyi adatot tárol a tesztmetódus által ellenőrzött példánymezőkben.
  • 🧪 Működő példa: Öt bemeneti sor vezérli a sum() tesztet, és a JUnit jelentések megtekintése 5/5-én lefut, nulla hibával.
  • 🇧🇷 JUnit 5: A @ParameterizedTest a @ValueSource, @CsvSource vagy @MethodSource metódussal eltávolítja mind a futtatót, mind a konstruktort.
  • 📌 Buktatók: Egy nem statikus @Parameters metódus, két nyilvános konstruktor vagy egy hiányzó junit-jupiter-params függőség leállítja a futást.

JUnit paraméteres teszt @RunWith és @Parameters annotációk használatával

Mi az a paraméteres teszt? JUnit?

A paraméterezett teszt egy olyan teszt, amely ugyanazt a tesztmetódust futtatja újra és újra különböző értékekkel. Segít a fejlesztőknek időt megtakarítani, amikor olyan teszteket írnak, amelyek csak a bemeneti adatokban és a várható eredményekben különböznek.

Paraméteres teszt segítségével beállítható egy tesztmetódus, amely adatokat kér le valamilyen adatforrásból. Ez teszi a legegyszerűbb formájává adatvezérelt tesztelés belül elérhető JUnit önmagában, külső könyvtár nélkül.

Tekintsünk egy egyszerű tesztet, amely különböző számokat összegez. A kód így nézhet ki:

JUnit A tesztmetódus háromszori assertEquals hívását adja meg a sum metódushoz

A fenti megközelítés sok redundanciához vezet. Minden új számpárhoz egy újabb assert utasításra van szükség ugyanazon a metóduson belül, és az első assertáció hibája elrejti az azt követő összes többit.

Egyszerűbb megközelítésre van szükség. Paraméteres teszt használatával hozzáadhatsz egyetlen metódust, amely tíz adatbemenetet biztosít, és a teszt automatikusan tízszer fog lefutni.

A paraméterezett létrehozásának lépései JUnit Tesztelés

A következő kód egy paraméteres teszt példáját mutatja be. Az Airthematic osztály sum() metódusát teszteli, amelyet a példaprojektben is használtunk.

Step 1) Hozz létre egy osztályt. Ebben a példában két számot fogunk beírni a sum(int, int) metódussal, amely a megadott számok összegét adja vissza.

Airthematic osztály, amely egy public sum metódust deklarál, amely két int argumentumot ad össze

Step 2) Hozz létre egy paraméteres tesztosztályt.

Teszt osztály fejléce @RunWith(Parameterized.class) és négy privát mezővel annotálva

Code Magyarázat

  • Code 11 vonal: A tesztosztályodat a @RunWith(Parameterized.class) használatával annotálhatod.
  • Code 13 vonal: A 'firstNumber' változó privátként való deklarálása, a típus pedig int.
  • Code 14 vonal: A 'secondNumber' változót privátként deklaráljuk, és int típusúra írjuk.
  • Code 15 vonal: A „várható eredmény” változó privátként való deklarálása és int típusúként való típusa.
  • Code 16 vonal: Az „airthematic” változó privátként való deklarálása és Airthematic típusként való beállítása.

@RunWith(osztály_neve.osztály): a @RunWith Az annotáció a futtatóosztály nevének megadására szolgál. Ha nem adunk meg típust paraméterként, a futtatókörnyezet a következőt fogja választani: BlokkJUnit4ClassRunner alapértelmezés szerint.

Ez az osztály felelős a tesztek új tesztpéldánnyal történő futtatásáért. Felelős a következő meghívásáért: JUnit életciklus-módszerek, mint például a beállítás (társított erőforrások) és a lebontás (erőforrások felszabadítása), amelyeket a JUnit tesztberendezés tutorial.

A paraméterezéshez a @RunWith használatával kell annotálni az osztályt, és átadni a teszteléshez szükséges .class-t.

Step 3) Hozz létre egy konstruktort, amely a tesztadatokat tárolja. 3 változót tárol.

Paraméterezett tesztkonstruktor, amely három egész argumentumot rendel a példánymezőkhöz

Step 4) Hozzon létre egy statikus metódust, amely tesztadatokat generál és visszaad.

Statikus beviteli metódus, @Parameterized.Parameters annotációval, kétdimenziós objektumtömböt ad vissza

Code 32,33 vonal: Kétdimenziós tömb létrehozása (bemeneti paraméterek megadásával az összeadáshoz). Az asList metódus segítségével List típusúvá alakítjuk az adatokat, mivel a bemeneti metódus visszatérési típusa Collection.

Code 30 vonal: az @Paraméterek megjegyzést, hogy létrehozzon egy bemeneti adatkészletet a teszt futtatásához.

A @Parameters annotáció által azonosított statikus metódus egy Gyűjteményt ad vissza, ahol a Gyűjtemény minden egyes bejegyzése a teszt egy iterációjának bemeneti adata lesz. Tekintsük az {1,2,3} elemet. Itt:

  • elsőSzám = 1
  • másodikSzám = 2
  • vártEredmény = 3

Itt minden tömbelem egyenként kerül átadásra a konstruktornak, mivel az osztály többször is példányosodik. A példában deklarált öt tömb tehát a következő öt futtatást eredményezi:

Ismétlés elsőszám második szám várható eredmény Konzol sor
[0] 1 2 3 Összeg Numbers = : 3
[1] 11 22 33 Összeg Numbers = : 33
[2] 111 222 333 Összeg Numbers = : 333
[3] 10 9 19 Összeg Numbers = : 19
[4] 100 9 109 Összeg Numbers = : 109

Step 5) A teljes kód.

Teljes AirthematicTest lista importálással, konstruktorral, @Parameters metódussal és @Test metódussal

Code Magyarázat:

  • Code 25 vonal: A @Before annotáció használata az erőforrások beállításához (itt az Airthematic.class). A @Before annotációt itt minden teszteset előtt futtatjuk. Ez tartalmazza a teszt előfeltételét.
  • Code 36 vonal: A @Test annotáció használata a teszt létrehozásához.
  • Code 39 vonal: Létrehozása állítás hogy ellenőrizzük, hogy az összegünk megegyezik-e a várttal.

Step 6) Hozz létre egy tesztfuttató osztályt a paraméteres teszt futtatásához:

A TestRunner osztály átadja az AirthematicTest.class-t a következőnek: JUnitCore.runClasses és nyomtatási hibák

Code Magyarázat:

  • Code 8 vonal: A Test osztály main metódusának deklarálása, amely futtatni fogja a következőt: JUnit teszt.
  • Code 9 vonal: Tesztesetek végrehajtása a következő használatával: JUnitCore.runClasses, amely paraméterként fogadja a tesztosztály nevét (a példánkban az AirthematicTest.class-t használjuk).
  • Code 11 vonal: Az eredmény feldolgozása egy for ciklus segítségével és a sikertelen eredmény kinyomtatása.
  • Code 13 vonal: A sikeres eredmény kinyomtatása.

output:

Itt látható a kimenet, amely egy sikeres tesztet mutat hibák nélkül trace, az alábbiak szerint. Vegye figyelembe, hogy a JUnit A nézet adatsoronként egy bejegyzést listáz egyetlen teszt helyett:

Eclipse JUnit jelentéskészítés nézete 5/5-én fut 0 hibával és 0 meghibásodással a paraméterezett osztály esetében

Nézd meg az eredményt a konzolon, amely a két szám összeadását mutatja:

Eclipse konzol egyet nyomtat Összeg Numbers sor mind az öt paramétersorhoz

Paraméterezett tesztek JUnit 5 a @ParameterizedTest segítségével

A fenti példa erre íródott JUnit 4. JUnit Az 5-ös (Jupiter) teljesen elveti a futómodellt, így a @RunWith(Parameterized.class), az adatkonstruktor és a példánymezők is eltűnnek. JUnit A fent látható 4-es kód nem elavult: változatlanul fut a következőn: JUnit Platform a vintage motoron keresztül. Az új teszteket azonban általában a @ParameterizedTest segítségével írják.

Két függőség szükséges: a junit-jupiter-api a tesztannotációkhoz és a junit-jupiter-paraméterek a paraméteres támogatáshoz. A második műtermék nélkül a forrásmegjegyzések egyáltalán nem oldódnak fel.

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

class AirthematicTest {

    // one row per iteration, no constructor and no runner
    @ParameterizedTest(name = "{0} + {1} = {2}")
    @CsvSource({"1, 2, 3", "11, 22, 33", "111, 222, 333", "10, 9, 19", "100, 9, 109"})
    void sumOfTwoNumbers(int firstNumber, int secondNumber, int expectedResult) {
        assertEquals(expectedResult, new Airthematic().sum(firstNumber, secondNumber));
    }
}

A Jupiter számos argumentumforrást kínál, és a megfelelő kiválasztása az adatok alakjától függ:

Forrásmegjegyzés Készletek Használd, amikor
@ValueSource Egyetlen literálokból álló oszlop A teszt pontosan egy argumentumot fogad el
@CsvSource Vesszővel elválasztott sorok egymásba ágyazva A fájlban tisztán olvasható kis szám- és karakterlánctáblázatok
@CsvFileSource CSV-ből beolvasott sorok a teszt osztályútvonalon Az adathalmaz nagy, vagy a kódon kívül van karbantartva.
@MethodSource Egy statikus gyár, amely argumentumok folyamát adja vissza Valós tárgyakra, számított értékekre vagy véletlenszerű adatokra van szükség
@EnumSource Egy felsorolás állandói Minden enum értéket gyakorolni kell

Két szabály a legtöbb kezdő számára hasznos. Egy egyszerű @Test metódusra helyezett forrásmegjegyzést a rendszer csendben figyelmen kívül hagy, így a metódusnak @ParameterizedTest paramétert kell tartalmaznia. A @CsvSource-ban lévő idézőjelek nélküli üres értéket nullként, míg az idézőjelek között lévő üres értéket üres karakterláncként olvassa be.

Az JUnit A cikkben használt 4 annotáció a Jupiterre a következőképpen vonatkozik: a @RunWith(Parameterized.class) @ParameterizedTest plusz egy forrás-annotáció lesz, a @Parameters @MethodSource vagy @CsvSource lesz, a @Before pedig @BeforeEach. A teljes lista a következőben található: JUnit annotációk tutorial.

A paraméteres tesztek előnyei és korlátai

A paraméterezés nem ingyenes. Eltávolítja a duplikációt, de korlátozza a tesztírás módját is, ezért érdemes mindkét oldalt ismerni egy meglévő csomag konvertálása előtt.

Előnyök

  • Less másolás: Az egyik metódus egy közel azonos assert utasításokból álló blokkot helyettesít, ahogy az a cikk első képernyőképén is látható.
  • Olcsóbb biztosítás: Egy peremhelyzet hozzáadása egy plusz adatsorba kerül egy teljesen új helyett próbaper módszer.
  • Pontos jelentéskészítés: Minden iterációt külön jelentünk, így a JUnit A nézet pontosan azonosítja, hogy melyik sor hibázott, ahelyett, hogy egyetlen összesített hibát azonosítana.
  • Központosított adatok: A bemenetek egyetlen metódusban tárolódnak, és később áthelyezhetők egy CSV-fájlba vagy egy gyárba az assertions (állítások) megérintése nélkül.

korlátozások

  • Az állítás egyik formája: Minden sor ugyanazokat az állításokat futtatja, így egy olyan forgatókönyvhöz, amely különböző ellenőrzéseket igényel, továbbra is szüksége van saját tesztelési metódusra.
  • Osztályszintű hatókör JUnit 4: A futtató paraméterezi az egész osztályt, így az adott osztályon belüli, egymással nem összefüggő @Test metódusok is soronként egyszer futnak.
  • Olvashatatlan jelentések: Névsablon nélkül a hibák testAirthematicTest[3] néven jelennek meg, ami semmit sem árul el a hibás adatokról.
  • Terjedelmes beágyazott adatok: A nagy tömbök kiszorítják a tesztlogikát; helyezd át őket inkább a @CsvFileSource vagy egy @MethodSource factory-ba.

Gyakori hibák a JUnit Paraméterezett tesztek

A legtöbb paraméteres hiba inicializálási hiba, amely egyetlen állítás végrehajtása előtt keletkezik. Az alábbi táblázat felsorolja a leggyakrabban megjelenő üzeneteket és azok kiváltó okát.

Üzenet Okoz Rögzít
A tesztosztálynak pontosan egy nyilvános konstruktorral kell rendelkeznie Az osztály nem deklarál nyilvános konstruktort, vagy csak kettőt deklarál. Tartson meg egy nyilvános konstruktort, amelynek paraméterei megegyeznek az adatoszlopokkal
Nincs nyilvános statikus paraméterekkel rendelkező metódus az osztályon A @Parameters metódus nem nyilvános statikus, vagy rossz típust ad vissza. Deklaráld nyilvános statikus gyűjteményként, és add vissza az Arrays.asList(…) értéket.
IllegalArgumentException: rossz számú argumentum Egy sor szélesebb vagy keskenyebb, mint a konstruktor paraméterlistája A Collection minden tömbjének szélessége legyen azonos a konstruktor szélességével.
Konfigurációs hiba: nincs argumentumszolgáltató Egy Jupiter teszt @ParameterizedTest-et tartalmaz forrásmegjegyzés nélkül Adja hozzá a @ValueSource, @CsvSource, @CsvFileSource, @MethodSource vagy @EnumSource értékeket.
A forrásmegjegyzés látszólag semmit sem csinál A metódus @Test annotációval van ellátva @ParameterizedTest helyett Cserélje le a @Test értéket @ParameterizedTest értékre, és importálja a junit-jupiter-params értéket.

Egy további csapda a megosztott állapot. Mivel JUnit soronként új példányt hoz létre, a statikus mezőben tárolt bármi túléli az összes iterációt, és a [0] sor által írt érték észrevétlenül megváltoztathatja a [4] sor eredményét. Tartsa meg a soronkénti állapotot a példánymezőkben, és állítsa vissza a megosztott erőforrásokat a @Before vagy @BeforeEach metódusban. Az izolációs tesztekre vonatkozó általános útmutatást a [4] dokumentum tartalmazza. egység tesztelés tutorial.

GYIK

TestNG A sorokat egy tesztmetódusonként hivatkozott @DataProvider metóduson keresztül látja el, így az osztályon belüli, egymással nem összefüggő tesztek változatlanok maradnak. JUnit A 4-es a teljes osztályt a futtatóján keresztül paraméterezi. JUnit Az 5-ös verzió a metódusonkénti @ParameterizedTest segítségével küszöböli ki ezt a rést.

Igen. JUnit A 4-es típus elfogadja a @Parameters(name = “{index}: sum({0},{1})={2}”) értékeket, a Jupiter pedig a @ParameterizedTest(name = “…”) értékeket. A helyőrzők futásidőben lecserélődnek, így a hibajelentés a hibás sort nevezi meg ahelyett, hogy egy üres indexet jelenítene meg.

Igen. JUnit A 4-es osztály támogatja a @Parameter(0) és @Parameter(1) metódusokat nyilvános, nem statikus mezőkön, és az osztály ezután az alapértelmezett konstruktorra támaszkodik. A mezőbefecskendezés és az adatkonstruktor kombinálása az „egyetlen nyilvános konstruktor” hibát váltja ki.

JUnit A 4-esnek csak a junit artefaktumra van szüksége, mivel a paraméteres futtató abban található. JUnit Az 5-ös verziónak a junit-jupiter-params függvényre van szüksége a junit-jupiter-api mellett; enélkül a @ParameterizedTest és minden forrásmegjegyzés feloldása sikertelen.

A Jupiter biztosítja a @CsvFileSource(resources = “/data.csv”, numLinesToSkip = 1) metódust, amely a teszt osztályútvonalból olvassa be a sorokat. JUnit A 4-esnek nincs beépített megfelelője, így a @Parameters metódusnak meg kell nyitnia és elemeznie a fájlt, mielőtt visszaadná a Collection-t.

In JUnit 4-es esetben lehetséges, de a futtatóprogram paraméterezi az egész osztályt, így minden metódus adatsoronként egyszer fut le. A Jupiter paraméterezi az egyes metódusokat, így az ugyanabban az osztályban lévő sima @Test metódusok is pontosan egyszer futnak le.

A mesterséges intelligencia asszisztensek beolvassák a metódus szignatúráját, és olyan határ sorokat javasolnak, mint a nulla, negatív, maximum és túlcsordulás bemenetek, amelyeket egy kézzel írott táblázat gyakran nem tartalmaz. RevTekintse meg az összes generált várható eredményt, mivel egy modell előállíthat egy hihető sort rossz válasszal.

GitHub másodpilóta gyorsan előállítja az állványzatot, de gyakran keveredik JUnit A 4-es és a Jupiter importál, és néha forrásmegjegyzést hagy egy egyszerű @Test metóduson. A csomag futtatása előtt ellenőrizze az importálásokat.

Foglald össze ezt a bejegyzést a következőképpen: