Útmutató a JUnit 5 paraméterezett tesztjeihez
1. Áttekintés
A JUnit 5, a JUnit következő generációja új és fényes funkciókkal segíti a fejlesztői tesztek megírását.
Az egyik ilyen tulajdonság az oarameterizált tesztek. Ez a funkció lehetővé teszi számunkra, hogy végezzen egyetlen vizsgálati módszert többször, különböző paraméterekkel.
Ebben az oktatóanyagban a paraméterezett teszteket vizsgáljuk meg alaposan, ezért kezdjük!
2. Függőségek
A JUnit 5 paraméterezett tesztjeinek használatához importálnunk kell a junit-jupiter-params műtárgy a JUnit Platform-tól. Ez azt jelenti, hogy a Maven használatakor a következőket adjuk hozzá pom.xml:
org.junit.jupiter junit-jupiter-params 5.7.0 teszt
Ezenkívül a Gradle használatakor kicsit másképp fogjuk megadni:
testCompile ("org.junit.jupiter: junit-jupiter-params: 5.7.0")
3. Első benyomás
Tegyük fel, hogy van egy létező segédfunkciónk, és szeretnénk biztosak lenni a viselkedésében:
public class Numbers {nyilvános statikus logikai isOdd (int szám) {visszatérési szám% 2! = 0; }}
A paraméterezett tesztek olyanok, mint a többi teszt, kivéve, hogy hozzáadjuk a @ParameterizedTest kommentár:
@ParameterizedTest @ValueSource (ints = {1, 3, 5, -3, 15, Egész.MAX_VALUE}) // hat szám érvénytelen isOdd_ShouldReturnTrueForOddNumbers (int szám) {assertTrue (Számok.isOdd (szám)); }
A JUnit 5 tesztfutó végrehajtja ezt a fenti tesztet - és ennek következtében a isOdd módszer - hatszor. És minden alkalommal más és más értéket rendel hozzá @ValueSource tömb a szám method paraméter.
Tehát ez a példa két dolgot mutat be, amelyre szükségünk van egy paraméterezett teszthez:
- érvek forrása, an int tömb, ebben az esetben
- a hozzáférés módja, ebben az esetben a szám paraméter
Van még egy dolog, ami nem nyilvánvaló ebben a példában, ezért maradjon velünk.
4. Argumentumforrások
Amint azt már tudnunk kell, egy paraméterezett teszt ugyanazt a tesztet többször, különböző argumentumokkal hajtja végre.
Remélhetőleg nem csak a számokat tehetjük meg - hát vizsgáljuk meg!
4.1. Egyszerű értékek
A ... val @ValueSource annotációval, a szó szerinti értékek tömbjét átadhatjuk a vizsgálati módszernek.
Tegyük fel például, hogy tesztelni fogjuk egyszerűségünket isBlank módszer:
public class Strings {public static logikai isBlank (String input) return input == null}
Arra számítunk, hogy ez a módszer visszatér igaz mert nulla üres húrokhoz. Tehát írhatunk egy paraméterezett tesztet, amely az alábbiak szerint állíthatja ezt a viselkedést:
@ParameterizedTest @ValueSource (stringek = {"", ""}}) void isBlank_ShouldReturnTrueForNullOrBlankStrings (String input) {assertTrue (Strings.isBlank (input)); }
Mint láthatjuk, a JUnit kétszer lefuttatja ezt a tesztet, és minden alkalommal hozzárendel egy argumentumot a tömbből a method paraméterhez.
Az értékforrások egyik korlátja, hogy csak a következő típusokat támogatják:
- rövid (a ... val rövidnadrág tulajdonság)
- byte (a ... val bájtokat tulajdonság)
- int (a ... val ints tulajdonság)
- hosszú (a ... val vágyakozik tulajdonság)
- úszó (a ... val lebeg tulajdonság)
- kettős (a ... val duplázik tulajdonság)
- char (a ... val karakterek tulajdonság)
- java.lang.String (a ... val húrok tulajdonság)
- java.lang.Osztály (a ... val osztályok tulajdonság)
Is, minden alkalommal csak egy argumentumot adhatunk át a vizsgálati módszerhez.
És mielőtt tovább ment volna, észrevette-e valaki, hogy nem mentünk át nulla érvként? Ez egy másik korlátozás: Nem mehetünk át nulla keresztül a @ValueSource, még arra is Húr és Osztály!
4.2. Null és üres értékek
A JUnit 5.4-től kezdve egyetlenet is átadhatunk nulla értéket egy paraméterezett vizsgálati módszerhez @NullSource:
@ParameterizedTest @NullSource void isBlank_ShouldReturnTrueForNullInputs (String input) {assertTrue (Strings.isBlank (input)); }
Mivel a primitív adattípusok nem fogadhatók el nulla értékeket, nem használhatjuk a @NullSource primitív érvekért.
Hasonló módon adhatunk át üres értékeket a @EmptySource kommentár:
@ParameterizedTest @EmptySource void isBlank_ShouldReturnTrueForEmptyStrings (String input) {assertTrue (Strings.isBlank (input)); }
@EmptySource egyetlen üres argumentumot ad át az annotált metódusnak.
Mert Húr argumentumok esetén az átadott érték olyan egyszerű lenne, mint egy üres Húr. Sőt, ez a paraméterforrás üres értékeket adhat a Gyűjtemény típusok és tömbök.
Annak érdekében, hogy mindkettőnek megfeleljen nulla és üres értékek, használhatjuk a komponáltakat @NullAndEmptySource kommentár:
@ParameterizedTest @NullAndEmptySource void isBlank_ShouldReturnTrueForNullAndEmptyStrings (String input) {assertTrue (Strings.isBlank (input)); }
Mint a @EmptySource, az összeállított kommentár a következőhöz működik: Húrs,Gyűjteménys, és tömbök.
Annak érdekében, hogy még néhány üres karakterlánc variációt átadjunk a paraméterezett tesztnek, kombinálhatjuk @ValueSource, @NullSource és @EmptySource együtt:
@ParameterizedTest @NullAndEmptySource @ValueSource (string = {"", "\ t", "\ n"}) void isBlank_ShouldReturnTrueForAllTypesOfBlankStrings (String input) {assertTrue (Strings.isBlank (input); }
4.3. Enum
Annak érdekében, hogy egy felsorolásban szereplő értékekkel különböző tesztet fussunk, használhatjuk a @EnumSource annotáció.
Azt állíthatjuk például, hogy az összes havi szám 1 és 12 között van:
@ParameterizedTest @EnumSource (Month.class) // mind a 12 hónap átengedése void getValueForAMonth_IsAlwaysBetweenOneAndTwelve (Month month) {int monthNumber = month.getValue (); assertTrue (monthNumber> = 1 && monthNumber <= 12); }
Vagy kiszűrhetünk néhány hónapot a nevek tulajdonság.
Mit szólnál ahhoz, ha azt állítanád, hogy április, szeptember, június és november 30 napos:
@ParameterizedTest @EnumSource (value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"}) void someMonths_Are30DaysLong (Month month) {final boolean isALeapYear = false; assertEquals (30, hónap.hossz (isALeapYear)); }
Alapértelmezés szerint a nevek csak az egyező enum értékeket fogja megtartani. Ezt megfordíthatjuk a mód tulajdonít neki KIZÁRNI:
@ParameterizedTest @EnumSource (érték = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER", "FEBRUARY"}, mode = EnumSource.Mode.EXCLUDE) void paitsiFourMonths_OthersAre31DaysLong végső logikai érték isALeapYear = hamis; assertEquals (31, hónap.hossz (isALeapYear)); }
A szó szerinti húrok mellett szabályos kifejezést adhatunk át a nevek tulajdonság:
@ParameterizedTest @EnumSource (érték = Hónap.osztály, nevek = ". + BER", mód = EnumSource.Mode.MATCH_ANY) érvénytelen négy Hónap_AreEndingWithBer (Hónap hónap) {EnumSet hónap = EnumSet.of (Hónap.SEPTEMBER, Hónap.OCTOBER, .NOVEMBER, hónap.DECEMBER); assertTrue (hónapok.tartalmaz (hónap)); }
Egészen hasonló @ValueSource, @EnumSource csak akkor alkalmazható, ha tesztfuttatásonként csak egy argumentumot adunk át.
4.4. CSV Literals
Tegyük fel, hogy meg fogunk győződni arról, hogy a toUpperCase () módszer től Húr generálja a várható nagybetűs értéket. @ValueSource nem lesz elég.
Paraméteres teszt írásához az ilyen forgatókönyvekhez meg kell tennünk:
- Át egy bemeneti érték és an várható érték a vizsgálati módszerhez
- Számítsa ki a tényleges eredmény azokkal a bemeneti értékekkel
- Állítsd a tényleges érték a várható értékkel
Szükségünk van olyan argumentumforrásokra, amelyek képesek több argumentum átadására. A @CsvSource az egyik ilyen forrás:
@ParameterizedTest @CsvSource ({"teszt, TEST", "tEst, TEST", "Java, JAVA"}) void toUpperCase_ShouldGenerateTheExpectedUppercaseValue (String input, String várható) {String actualValue = input.toUpperCase (); assertEquals (várható, tényleges érték); }
A @CsvSource vesszővel elválasztott értékek tömbjét fogadja el, és minden tömbbejegyzés megfelel egy CSV fájl sorának.
Ez a forrás minden alkalommal egy tömb bejegyzést vesz fel, vesszővel osztja fel és mindegyik tömböt külön paraméterként továbbítja az annotált vizsgálati módszerhez. Alapértelmezés szerint a vessző az oszlopelválasztó, de testre szabhatjuk a határoló tulajdonság:
@ParameterizedTest @CsvSource (value = {"test: test", "tEst: test", "Java: java"}, delimiter = ':') void toLowerCase_ShouldGenerateTheExpectedLowercaseValue (String bevitel, String várható) {String actualValue = input.toLowerCase ( ); assertEquals (várható, tényleges érték); }
Most ez egy kettőspont-külön érték, még mindig CSV!
4.5. CSV-fájlok
Ahelyett, hogy átadnánk a CSV értékeket a kódban, hivatkozhatunk egy tényleges CSV fájlra.
Például használhatunk egy CSV fájlt, például:
bemenet, várható teszt, TEST tEst, TEST Java, JAVA
Betölthetjük a CSV fájlt és hagyja figyelmen kívül a fejléc oszlopot val vel @CsvFileSource:
@ParameterizedTest @CsvFileSource (erőforrások = "/data.csv", numLinesToSkip = 1) void toUpperCase_ShouldGenerateTheExpectedUppercaseValueCSVFile (String input, String várható) {String actualValue = input.toUpperCase (); assertEquals (várható, tényleges érték); }
A erőforrások attribútum az elolvasandó osztályútvonal CSV fájl erőforrásait jelöli. Több fájlt is átadhatunk neki.
A numLinesToSkip attribútum a CSV fájlok olvasásakor kihagyandó sorok számát jelenti. Alapértelmezés szerint, @CsvFileSource nem hagy ki egyetlen sort sem, de ez a szolgáltatás általában hasznos a fejlécsorok kihagyásához, mint itt tettük.
Akárcsak az egyszerű @CsvSource, az elválasztó testreszabható a határoló tulajdonság.
Az oszlopelválasztón kívül:
- A vonalelválasztó testreszabható a lineSeparator attribútum - új sor az alapértelmezett érték
- A fájlkódolás testreszabható a kódolás attribútum - az UTF-8 az alapértelmezett érték
4.6. Módszer
Az eddig tárgyalt érvelési források kissé egyszerűek és egy korlátot mutatnak: Nehéz vagy lehetetlen átadni összetett objektumokat ezek használatával!
Az egyik megközelítés összetettebb érvek megadása egy módszer használata argumentumforrásként.
Teszteljük a isBlank módszer a @MethodSource:
@ParameterizedTest @MethodSource ("nodrošinātStringsForIsBlank") void isBlank_ShouldReturnTrueForNullOrBlankStrings (Karakterlánc-bemenet, logikai elvárt) {assertEquals (várható, Strings.isBlank (input)); }
A név, amelyet ellátunk @MethodSource meg kell egyeznie egy meglévő módszerrel.
Tehát írjuk legközelebb provideStringsForIsBlank, a statikus metódus, amely a Folyam nak,-nek Érvs:
privát statikus adatfolyam biztosítja hamis) ); }
Itt szó szerint viszonzunk egy érvelést, de ez nem szigorú követelmény. Például, bármilyen más gyűjteményszerű felületet visszaadhatunk Lista.
Ha teszt meghívásonként csak egy argumentumot fogunk megadni, akkor nem szükséges a Érvek absztrakció:
@ParameterizedTest @MethodSource // hmm, nincs módszer neve ... void isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument (String input) {assertTrue (Strings.isBlank (input)); } privát statikus adatfolyam isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument () {return Stream.of (null, "", ""); }
Amikor nem adunk nevet a @MethodSource, A JUnit megkeresi a vizsgálati módszerrel megegyező nevű forrásmódszert.
Néha hasznos megosztani az érveket a különböző tesztosztályok között. Ezekben az esetekben az aktuális osztályon kívüli forrásmódszerre hivatkozhatunk teljesen minősített nevével:
class StringsUnitTest {@ParameterizedTest @MethodSource ("com.baeldung.parameterized.StringParams # blankStrings") void isBlank_ShouldReturnTrueForNullOrBlankStringsExternalSource (String input) {assertTrank (Strings.rue) }} public class StringParams {static Stream blankStrings () {return Stream.of (null, "", ""); }}
Használni a FQN # methodName formátumban hivatkozhatunk egy külső statikus módszerre.
4.7. Egyéni argumentumszolgáltató
A teszt argumentumok átadásának másik fejlett megközelítése az úgynevezett felület egyedi megvalósításának használata Szolgáltató:
class BlankStringsArgumentsProvider megvalósítja az ArgumentsProvider {@Orride public Stream provideArguments (ExtensionContext context) {return Stream.of (Arguments.of ((String) null), Arguments.of (""), Arguments.of ("")); }}
Ezután feljegyezhetjük tesztünket a @ArgumentsSource jelölés az egyéni szolgáltató használatához:
@ParameterizedTest @ArgumentsSource (BlankStringsArgumentsProvider.class) void isBlank_ShouldReturnTrueForNullOrBlankStringsArgProvider (String input) {assertTrue (Strings.isBlank (input)); }
Tegyük az egyéni szolgáltatót kellemesebb API-ként történő használatra, egyedi jelölésekkel!
4.8. Egyéni kommentár
Mi lenne, ha a teszt argumentumokat statikus változóból töltené be? Valami hasonló:
statikus adatfolyam argumentumok = Stream.of (Az Arguments.of (null, true), // null karakterláncokat üresnek kell tekinteni. Arguments.of ("", true), Arguments.of ("", true), Arguments.of (" nem üres ", hamis)); @ParameterizedTest @VariableSource ("argumentumok") void isBlank_ShouldReturnTrueForNullOrBlankStringsVariableSource (Stringbevitel, logikai elvárt) {assertEquals (várható, Strings.isBlank (input)); }
Tulajdonképpen, Az 5. JUnit ezt nem biztosítja! A saját megoldást azonban guríthatjuk.
Először is létrehozhatunk egy kommentárt:
@Documented @Target (ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) @ArgumentsSource (VariableArgumentsProvider.class) public @interface VariableSource {/ ** * A statikus változó neve * / String érték (); }
Akkor muszáj valahogy fogyasztja az annotációt részletek és adjon meg tesztérveket. A JUnit 5 két absztrakciót biztosít a két dolog eléréséhez:
- AnnotationFogyasztó hogy felhasználják az annotáció részleteit
- ArgumentProvider tesztérvek megadására
Tehát legközelebb el kell készítenünk a VariableArgumentsProvider osztály a megadott statikus változóból kiolvasva adja vissza az értékét teszt argumentumként:
class VariableArgumentsProvider megvalósítja az ArgumentsProvider, AnnotationConsumer {private String változóNév; @Orride public Stream provideArguments (ExtensionContext context) {return context.getTestClass () .map (this :: getField) .map (this :: getValue) .orElseThrow (() -> new IllegalArgumentException ("Nem sikerült betölteni a teszt argumentumokat") ); } @Orride public void accept (VariableSource variableSource) {változóNév = változóForrás.érték (); } privát mező getField (Class clazz) {try {return clazz.getDeclaredField (változóNév); } catch (e kivétel) {return null; }} @SuppressWarnings ("bejelöletlen") privát adatfolyam getValue (mező mező) {Object value = null; próbáld ki a {value = field.get (null) parancsot; } catch (kivétel figyelmen kívül hagyva) {} return value == null? null: (Stream) érték; }}
És varázslatként működik!
5. Argumentkonverzió
5.1. Implicit konverzió
Írjuk újra az egyiket @EnumTests egy @ -valCsvSource:
@ParameterizedTest @CsvSource ({"APRIL", "JUNE", "SZEPTEMBER", "NOVEMBER"}) // Pssing karakterláncok érvénytelenítenek néhány hónapot_Are30DaysLongCsv (hónap hónap) {final logikai isALeapYear = false; assertEquals (30, hónap.hossz (isALeapYear)); }
Ennek nem kellene működnie, igaz? De valahogy mégis!
Tehát az 5. JUnit átalakítja a Húr argumentumokat a megadott enum típushoz. Az ilyen felhasználási esetek támogatásához a JUnit Jupiter számos beépített implicit típusú konvertert biztosít.
Az átalakítási folyamat az egyes módszerparaméterek deklarált típusától függ. Az implicit konverzióval konvertálható a Húr példányok a következő típusokhoz:
- UUID
- Területi beállítás
- LocalDate, LocalTime, LocalDateTime, Year, Month stb.
- File és Pálya
- URL és URI
- Enum alosztályok
5.2. Kifejezett megtérés
Néha egyedi és explicit átalakítót kell adnunk az argumentumokhoz.
Tegyük fel, hogy a karakterláncokat a éééé / hh / nnformátum LocalDate példányok. Először is meg kell valósítanunk a ArgumentConverter felület:
osztály A SlashyDateConverter megvalósítja az ArgumentConverter {@Orride public Object convert (Object source, ParameterContext context) dobja az ArgumentConversionException {if (! (forrás példánya String)) {dobja új IllegalArgumentException ("Az argumentumnak karakterlánc legyen:" + forrás); } próbáld ki a {String [] parts = ((String) forrás) .split ("/"); int év = Integer.parseInt (részek [0]); int hónap = Integer.parseInt (részek [1]); int nap = Integer.parseInt (részek [2]); return LocalDate.of (év, hónap, nap); } catch (e kivétel) {dobjon új IllegalArgumentException ("Nem sikerült átalakítani", e); }}}
Ezután utalnunk kell a konverterre a @ConvertWith kommentár:
@ParameterizedTest @CsvSource ({"2018/12 / 25,2018", "2019/02 / 11,2019"}) void getYear_ShouldWorkAsExpected (@ConvertWith (SlashyDateConverter.class) LocalDate date, int várható) {assertEquals (várható, dátum. getYear ()); }
6. Argumentum-hozzáférés
Alapértelmezés szerint a paraméterezett teszt minden argumentuma egyetlen módszer paraméternek felel meg. Következésképpen, amikor egy maroknyi argumentumot átadunk egy argumentumforrásnak, a vizsgálati módszer aláírása nagyon nagy és rendetlen lesz.
A probléma megoldásának egyik megközelítése az összes átadott argumentum összefoglalása a ArgumentsAccessor és beolvassa az argumentumokat index és típus szerint.
Például vegyük figyelembe a sajátunkat Személy osztály:
osztály Személy {String keresztnév; String middleName; Karakterlánc vezetéknév; // konstruktor public String fullName () {if (középnév == null || középnév.trim (). isEmpty ()) {return String.format ("% s% s", keresztnév, vezetéknév); } return String.format ("% s% s% s", keresztnév, középnév, vezetéknév); }}
Ezután annak tesztelése érdekében teljes név() módszerrel négy érvet adunk át: keresztnév középső név vezetéknév, és a várható fullName. Használhatjuk a ArgumentsAccessor a teszt argumentumok lekérése ahelyett, hogy metódus paraméterként deklarálná őket:
@ParameterizedTest @CsvSource ({"Isaac ,, Newton, Isaac Newton", "Charles, Robert, Darwin, Charles Robert Darwin"}) void fullName_ShouldGenerateTheExpectedFullName (ArgumentsAccessor argumentsAccessor) {String firstName = argumentsAccessor.getString (0); String middleName = (Karakterlánc) argumentsAccessor.get (1); Karakterlánc vezetéknév = argumentsAccessor.get (2, String.osztály); Karakterlánc vártFullName = argumentumokAccessor.getString (3); Személy személy = új Személy (keresztnév, középnév, vezetéknév); assertEquals (várhatóFullName, person.fullName ()); }
Itt összesített argumentumot összefoglalunk egy ArgumentsAccessor példányt, majd a tesztmódszer törzsében az összes átadott argumentumot beolvassa az indexével. Amellett, hogy csak hozzáférő, a típuskonverziót a rendszer támogatja kap* mód:
- getString (index) lekér egy elemet egy adott indexen, és átalakítja Húr – tugyanez igaz a primitív típusokra is
- get (index) egyszerűen lekér egy elemet egy adott indexen, mint egy Tárgy
- get (index, típus) lekér egy elemet egy adott indexen, és átalakítja az adottra típus
7. Argumentum összesítő
Használni a ArgumentsAccessor az absztrakció a tesztkódot kevésbé olvashatóvá vagy újrafelhasználhatóvá teheti. E problémák megoldása érdekében egyedi és újrafelhasználható összesítőt írhatunk.
Ehhez megvalósítjuk a Argumentumok összesítője felület:
class PersonAggregator implementálja az ArgumentsAggregator {@Orride public Object aggregateArguments (ArgumentsAccessor accessor, ParameterContext context) dobja az ArgumentsAggregationException {return new Person (accessor.getString (1), accessor.getString (2), accessor.getString (3); }}
És akkor hivatkozunk rá a @AggregateWith kommentár:
@ParameterizedTest @CsvSource ({"Isaac Newton, Isaac ,, Newton", "Charles Robert Darwin, Charles, Robert, Darwin"}) void fullName_ShouldGenerateTheExpectedFullName (String vártFullName, @AggregateWith (PersonAggregator.className (PersonFlugEnterName) (personAggregator.ass) person.fullName ()); }
A PersonAggregator az utolsó három érvet veszi fel és példányosítja a Személy osztály belőlük.
8. A megjelenítési nevek testreszabása
Alapértelmezés szerint a paraméterezett teszt megjelenítési neve egy invokációs indexet tartalmaz az a-val együtt Húr az összes elfogadott argumentum ábrázolása, például:
├─ someMonths_Are30DaysLongCsv (hónap) │ │ ├─ [1] ÁPRILIS │ │ ├─ [2] JÚNIUS │ │ ├─ [3] SZEPTEMBER │ │ └─ [4] NOVEMBER
Ezt a kijelzőt azonban a név attribútuma @ParameterizedTest kommentár:
@ParameterizedTest (név = "{index} {0} 30 napos") @EnumSource (érték = Month.class, nevek = {"ÁPRILIS", "JÚNIUS", "SZEPTEMBER", "NOVEMBER"}) void someMonths_Are30DaysLong ( Hónap hónap) {végső logikai isALeapYear = hamis; assertEquals (30, hónap.hossz (isALeapYear)); }
Április 30 napos bizonyára olvashatóbb megjelenítési név:
├─ someHonths_Are30DaysLong (Month) │ │ ├─ APRIL 1 30 napos │ │ ├─ JÚNIUS 2. 30 napos │ │ ├─ SZEPTEMBER 3. 30 nap. NO │ └─ NOVEMBER 4. 30 nap.
A megjelenített név testreszabásakor a következő helyőrzők állnak rendelkezésre:
- {index} lecserélésre kerül az invokációs indexre - egyszerűen fogalmazva, az első végrehajtás invokációs indexe 1, a másodiké 2, és így tovább
- {érvek} a teljes, vesszővel elválasztott argumentumlista helyőrzője
- {0}, {1}, ... az egyes argumentumok helyőrzői
9. Következtetés
Ebben a cikkben a JUnit 5 paraméterezett tesztjeinek anyáit és csavarjait vizsgáltuk.
Megtudtuk, hogy a paraméterezett tesztek két szempontból különböznek a normál tesztektől: azokat a @ParameterizedTest, és forrásra van szükségük a deklarált érveikhez.
Mostanra azt is meg kell tennünk, hogy a JUnit biztosít néhány lehetőséget az argumentumok egyéni céltípusokká alakítására vagy a tesztnevek testreszabására.
Szokás szerint a mintakódok elérhetők a GitHub projektünkön, ezért mindenképpen ellenőrizze!