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.
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:
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.
Step 2) Hozz létre egy paraméteres tesztosztályt.
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.
Step 4) Hozzon létre egy statikus metódust, amely tesztadatokat generál és visszaad.
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.
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:
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:
Nézd meg az eredményt a konzolon, amely a két szám összeadását mutatja:
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.









