JUnit Parametrirani test s primjerom pomoću @Parameters

⚡ Pametni sažetak

Parametrizirani testovi u JUnit Ponavljajte istu metodu testiranja s različitim ulaznim vrijednostima, tako da jedna metoda pokriva mnoge scenarije. Anotacije @RunWith i @Parameters daju skup podataka za svaku iteraciju.

  • 🔘 Izvor podataka: Statička metoda @Parameters vraća kolekciju nizova, a svaki niz postaje jedna testna iteracija.
  • ☑️ Trkač: @RunWith(Parameterized.class) zamjenjuje zadani blokJUnit4ClassRunner i ponovno gradi klasu jednom po retku podataka.
  • Graditelj: Jedan javni konstruktor pohranjuje jedan red podataka u poljima instance na koja se testna metoda poziva.
  • 🧪 Obrađeni primjer: Pet ulaznih redaka pokreće test sum(), a JUnit prikaz izvješća Radi 5/5 bez ikakvih kvarova.
  • 🛠️ JUnit 5: @ParameterizedTest s @ValueSource, @CsvSource ili @MethodSource uklanja i runner i konstruktor.
  • 📌 Zamke: Nestatička metoda @Parameters, dva javna konstruktora ili nedostajuća ovisnost junit-jupiter-params zaustavljaju izvođenje.

JUnit parametrizirani test korištenjem anotacija @RunWith i @Parameters

Što je parametrizirani test u JUnit?

A parametrizirani test je test koji izvršava istu metodu testiranja iznova i iznova koristeći različite vrijednosti. Pomaže programerima da uštede vrijeme pri pisanju testova koji se razlikuju samo po ulaznim podacima i očekivanim rezultatima.

Korištenjem parametriziranog testa može se postaviti metoda testiranja koja dohvaća podatke iz nekog izvora podataka. To ga čini najjednostavnijim oblikom testiranje temeljeno na podacima dostupno unutra JUnit sam po sebi, bez potrebe za vanjskom bibliotekom.

Razmotrimo jednostavan test koji zbraja različite brojeve. Kod može izgledati ovako:

JUnit testna metoda koja ponavlja tri poziva assertEquals za metodu sum

Gornji pristup dovodi do velike redundancije. Svaki novi par brojeva zahtijeva još jednu tvrdnju unutar iste metode, a neuspjeh prve tvrdnje skriva svaku tvrdnju koja slijedi nakon nje.

Potreban je jednostavniji pristup. Korištenjem parametriziranog testa možete dodati jednu metodu koja daje deset ulaznih podataka, a vaš će se test automatski pokrenuti deset puta.

Koraci za stvaranje parametriziranog JUnit test

Sljedeći kod prikazuje primjer parametriziranog testa. Testira metodu sum() klase Airthematic, što je pravopis koji se koristi u cijelom primjeru projekta.

Korak 1) Kreirajte klasu. U ovom primjeru, unesemo dva broja koristeći metodu sum(int, int), koja će vratiti zbroj zadanih brojeva.

Klasa Airthematic koja deklarira javnu metodu zbrajanja koja zbraja dva inteligentna argumenta

Korak 2) Napravite parametriziranu testnu klasu.

Zaglavlje testne klase označeno s @RunWith(Parameterized.class) i četiri privatna polja

Code Objašnjenje

  • Code Redak 11: Označite svoju testnu klasu koristeći @RunWith(Parameterized.class).
  • Code Redak 13: Proglašavanje varijable 'firstNumber' privatnom i tipa int.
  • Code Redak 14: Deklarisanje varijable 'secondNumber' kao privatne i tip int.
  • Code Redak 15: Deklariranje varijable 'expectedResult' kao privatne i tipa int.
  • Code Redak 16: Deklarisanje varijable 'airthematic' kao privatne i tip kao Airthematic.

@RunWith(naziv_klase.klasa): the @RunWith Anotacija se koristi za određivanje naziva klase izvršavanja. Ako ne navedemo nijedan tip kao parametar, runtime će odabrati BlokiratiJUnit4ClassRunner prema zadanim postavkama.

Ova klasa je odgovorna za pokretanje testova s ​​novom testnom instancom. Odgovorna je za pozivanje JUnit metode životnog ciklusa kao što su postavljanje (povezivanje resursa) i rastavljanje (objavljivanje resursa), koje su opisane u JUnit ispitni uređaj udžbenik.

Za parametrizaciju, potrebno je označiti klasu pomoću @RunWith i proslijediti potrebnu .class za testiranje.

Korak 3) Napravite konstruktor koji pohranjuje testne podatke. Pohranjuje 3 varijable.

Parametrizirani konstruktor testa koji dodjeljuje tri inteligentna argumenta poljima instance

Korak 4) Stvorite statičku metodu koja generira i vraća testne podatke.

Statička metoda unosa označena s @Parameterized.Parameters koja vraća dvodimenzionalni niz objekata

Code Redak 32,33: Izrada dvodimenzionalnog niza (davanje ulaznih parametara za zbrajanje). Korištenjem metode asList pretvaramo podatke u tip List, budući da je povratni tip ulazne metode Kolekcija.

Code Redak 30: Korištenje @Parametri napomenu za stvaranje skupa ulaznih podataka za izvođenje našeg testa.

Statička metoda identificirana anotacijom @Parameters vraća kolekciju gdje će svaki unos u kolekciji biti ulazni podatak za jednu iteraciju testa. Razmotrimo element {1,2,3}. Ovdje:

  • prviBroj = 1
  • drugiBroj = 2
  • očekivaniRezultat = 3

Ovdje će se svaki element niza proslijediti konstruktoru, jedan po jedan, jer se klasa instancira više puta. Pet nizova deklariranih u primjeru stoga proizvode sljedećih pet izvršavanja:

ponavljanje prviBroj drugiBroj očekivani rezultat Konzolna linija
[0] 1 2 3 Zbroj Numbers = : 3
[1] 11 22 33 Zbroj Numbers = : 33
[2] 111 222 333 Zbroj Numbers = : 333
[3] 10 9 19 Zbroj Numbers = : 19
[4] 100 9 109 Zbroj Numbers = : 109

Korak 5) Potpuni kod.

Potpuni popis AirthematicTest-a s uvozima, konstruktorom, metodom @Parameters i metodom @Test

Code Objašnjenje:

  • Code Redak 25: Korištenje anotacije @Before za postavljanje resursa (ovdje Airthematic.class). Anotacija @Before se ovdje koristi za pokretanje prije svakog testnog slučaja. Sadrži preduvjet testa.
  • Code Redak 36: Korištenje anotacije @Test za izradu našeg testa.
  • Code Redak 39: Stvaranje tvrdnja kako bismo provjerili je li naš zbroj jednak onome što smo očekivali.

Korak 6) Napravite klasu za pokretanje parametriziranog testa:

Klasa TestRunner prosljeđuje AirthematicTest.class na JUnitCore.runClasses i greške ispisa

Code Objašnjenje:

  • Code Redak 8: Deklarisanje glavne metode klase Test koja će pokrenuti naš JUnit Test.
  • Code Redak 9: Izvršavanje testnih slučajeva pomoću JUnitCore.runClasses, koji kao parametar uzima naziv testne klase (u našem primjeru koristimo AirthematicTest.class).
  • Code Redak 11: Obrada rezultata pomoću for petlje i ispis neuspješnog rezultata.
  • Code Redak 13: Ispis uspješnog rezultata.

Izlaz:

Evo rezultata koji pokazuje uspješan test bez greške trace, kao što je navedeno u nastavku. Imajte na umu da JUnit prikaz navodi jedan unos po retku podataka umjesto jednog testa:

Eclipse JUnit prikaz izvješća Izvodi se 5/5 s 0 pogrešaka i 0 neuspjeha za parametriziranu klasu

Pogledajte rezultat na konzoli, koji prikazuje zbrajanje dvaju brojeva:

Eclipse konzolni ispis jedan Zbroj Numbers redak za svaki od pet redaka parametara

Parametrizirani testovi u JUnit 5 s @ParameterizedTest

Gornji primjer je napisan za JUnit 4. JUnit 5 (Jupiter) potpuno izostavlja model trkača, tako da @RunWith(Parameterized.class), konstruktor podataka i polja instance nestaju. JUnit 4 prikazani kod nije zastario: još uvijek se izvršava nepromijenjen na JUnit Platforma putem vintage engine-a. Novi testovi se, međutim, obično pišu s @ParameterizedTest.

Potrebne su dvije ovisnosti: junit-jupiter-api za testne anotacije i junit-jupiter-params za parametriziranu podršku. Bez drugog artefakta, izvorne anotacije se uopće neće riješiti.

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));
    }
}

Jupiter nudi nekoliko izvora argumenata, a pravi ovisi o obliku podataka:

Izvorna napomena Zalihe Koristite ga kada
@ValueSource Jedan stupac literala Test uzima točno jedan argument
@CsvSource Ugrađeni retci odvojeni zarezima Male tablice brojeva i nizova znakova jasno se čitaju u datoteci
@CsvFileSource Redci pročitani iz CSV-a na testnoj klasnoj putanji Skup podataka je velik ili se održava izvan koda
@MethodSource Statička tvornica koja vraća tok argumenata Potrebni su stvarni objekti, izračunate vrijednosti ili randomizirani podaci
@EnumSource Konstante nabrajanja Svaka vrijednost nabrajanja mora se izvršiti

Dva pravila hvataju većinu početnika. Anotacija izvora postavljena na običnu @Test metodu se tiho ignorira, pa metoda mora nositi @ParameterizedTest. Prazna vrijednost bez navodnika u @CsvSource se čita kao null, dok se prazna vrijednost pod navodnicima čita kao prazan niz.

The JUnit 4 anotacije korištene u ovom članku preslikavaju se na Jupiter na sljedeći način: @RunWith(Parameterized.class) postaje @ParameterizedTest plus anotacija izvora, @Parameters postaje @MethodSource ili @CsvSource, a @Before postaje @BeforeEach. Potpuni popis nalazi se u JUnit bilješke udžbenik.

Prednosti i ograničenja parametriziranih testova

Parametrizacija nije besplatna. Uklanja dupliciranje, ali i ograničava način pisanja testa, stoga je vrijedno znati obje strane prije pretvaranja postojećeg paketa.

Prednosti

  • Less dupliciranje: Jedna metoda zamjenjuje blok gotovo identičnih assert naredbi, kao što prikazuje prva snimka zaslona u ovom članku.
  • Jeftinije pokriće: Dodavanje rubnog slučaja košta još jedan redak podataka umjesto cijelog novog testni slučaj metoda.
  • Precizno izvještavanje: Svaka iteracija se izvještava zasebno, tako da JUnit prikaz točno identificira koji je redak bio neuspješan, a ne jedan agregirani neuspjeh.
  • Centralizirani podaci: Ulazi se nalaze u jednoj metodi i kasnije se mogu premjestiti u CSV datoteku ili tvornicu bez dodirivanja tvrdnji.

Ograničenja

  • Jedan oblik tvrdnje: Svaki redak izvršava iste tvrdnje, tako da scenarij koji zahtijeva različite provjere i dalje zahtijeva vlastitu metodu testiranja.
  • Opseg na razini klase u JUnit 4: Izvršitelj parametrizira cijelu klasu, tako da se nepovezane @Test metode u toj klasi također izvršavaju jednom po retku.
  • Nečitljiva izvješća: Bez predloška imena, kvarovi se prikazuju kao testAirthematicTest[3], što ne govori ništa o podacima koji su se pokvarili.
  • Obimni inline podaci: Veliki nizovi istiskuju logiku testiranja; umjesto toga, premjestite ih u @CsvFileSource ili tvornicu @MethodSource.

Uobičajene pogreške u JUnit Parametrizirani testovi

Većina parametriziranih kvarova su inicijalizacijske pogreške koje se javljaju prije izvršavanja jedne tvrdnje. Tablica u nastavku navodi poruke koje se najčešće pojavljuju i što ih pokreće.

Poruka Izazvati Popraviti
Testna klasa treba imati točno jedan javni konstruktor Klasa ne deklarira niti jedan javni konstruktor, ili čak dva. Zadržite jedan javni konstruktor čiji parametri odgovaraju stupcima podataka
Nema javne metode statičkih parametara na klasi Metoda @Parameters nije javna statička ili vraća pogrešan tip. Deklarirajte je kao javnu statičku kolekciju i vratite Arrays.asList(…)
IllegalArgumentException: pogrešan broj argumenata Red je širi ili uži od popisa parametara konstruktora Neka svaki niz u kolekciji bude iste širine kao i konstruktor
Pogreška konfiguracije: nema pružatelja argumenata Jupiter test nosi @ParameterizedTest bez napomene o izvoru Dodajte @ValueSource, @CsvSource, @CsvFileSource, @MethodSource ili @EnumSource
Čini se da izvorna napomena ne radi ništa Metoda je označena s @Test umjesto @ParameterizedTest Zamijenite @Test s @ParameterizedTest i uvozite junit-jupiter-params

Još jedna zamka je dijeljeno stanje. Jer JUnit gradi novu instancu po retku, sve što se nalazi u statičkom polju preživi svaku iteraciju, a vrijednost koju zapisuje redak [0] može tiho promijeniti ishod retka [4]. Zadržite stanje po retku u poljima instance i resetirajte dijeljene resurse u metodi @Before ili @BeforeEach. Opće smjernice o izoliranju testova obuhvaćene su u ispitivanje jedinice udžbenik.

Pitanja i odgovori

TestNG dostavlja retke putem metode @DataProvider na koju se referencira svaka testna metoda, tako da nepovezani testovi u klasi ostaju nepromijenjeni. JUnit 4 parametrizira cijelu klasu putem svog trkača. JUnit 5 zatvara tu prazninu s @ParameterizedTest po metodi.

Da. JUnit 4 prihvaća @Parameters(name = “{index}: sum({0},{1})={2}”) i Jupiter prihvaća @ParameterizedTest(name = “…”). Rezervirana mjesta se zamjenjuju tijekom izvođenja, pa izvješće o neuspjehu imenuje problematični redak umjesto prikazivanja golog indeksa.

Da. JUnit 4 podržava @Parameter(0) i @Parameter(1) na javnim nestatičkim poljima, a klasa se tada oslanja na zadani konstruktor. Kombiniranje ubrizgavanja polja s konstruktorom podataka pokreće grešku exactly-one-public-constructor.

JUnit 4 treba samo artefakt junit jer se Parameterized runner isporučuje unutar njega. JUnit 5 treba junit-jupiter-params uz junit-jupiter-api; bez tog artefakta @ParameterizedTest i svaka anotacija izvora ne uspijevaju riješiti problem.

Jupiter pruža @CsvFileSource(resources = “/data.csv”, numLinesToSkip = 1) koji čita retke iz testne putanje klase. JUnit 4 nema ugrađeni ekvivalent, pa metoda @Parameters mora otvoriti i analizirati samu datoteku prije vraćanja kolekcije.

In JUnit 4 može, ali izvršavatelj parametrizira cijelu klasu, tako da se svaka metoda izvršava jednom po retku podataka. Jupiter parametrizira pojedinačne metode, tako da se obične @Test metode u istoj klasi i dalje izvršavaju točno jednom.

AI asistenti čitaju potpis metode i predlažu granične retke kao što su nula, negativan, maksimalni i prekoračeni unosi koje rukom pisana tablica često propušta. Revpregledajte svaki generirani očekivani rezultat, jer model može proizvesti vjerojatan redak s pogrešnim odgovorom.

GitHub kopilot brzo proizvodi skelu, ali se često miješa JUnit 4 i Jupiter uvoze, a ponekad ostavljaju i napomenu izvora na običnoj @Test metodi. Provjerite uvoze prije pokretanja paketa.

Sažmite ovu objavu uz: