JUnit Test parametrizat cu exemplu folosind @Parameters
⚡ Rezumat inteligent
Teste parametrizate în JUnit rulează aceeași metodă de testare în mod repetat cu valori de intrare diferite, astfel încât o metodă acoperă mai multe scenarii. Adnotările @RunWith și @Parameters furnizează setul de date pentru fiecare iterație.
Ce este un test parametrizat în JUnit?
A test parametrizat este un test care execută aceeași metodă de testare iar și iar, folosind valori diferite. Ajută dezvoltatorii să economisească timp atunci când scriu teste care diferă doar prin datele de intrare și rezultatele așteptate.
Folosind un test parametrizat, se poate configura o metodă de testare care preia date dintr-o anumită sursă de date. Aceasta îl face cea mai simplă formă de testare bazată pe date disponibil în interior JUnit în sine, fără a fi necesară o bibliotecă externă.
Luați în considerare un test simplu care însumează numere diferite. Codul ar putea arăta astfel:
Abordarea de mai sus duce la multă redundanță. Fiecare nouă pereche de numere necesită o altă instrucțiune de afirmare în cadrul aceleiași metode, iar o eroare la prima afirmație ascunde toate afirmațiile care o urmează.
Este nevoie de o abordare mai simplă. Folosind un test parametrizat, puteți adăuga o singură metodă care furnizează zece intrări de date, iar testul dvs. va rula automat de zece ori.
Pași pentru a crea un parametrizat JUnit Testare
Următorul cod prezintă un exemplu de test parametrizat. Acesta testează metoda sum() a clasei Airthematic, care este ortografia utilizată în întregul proiect exemplu.
Pas 1) Creați o clasă. În acest exemplu, vom introduce două numere folosind metoda sum(int, int), care va returna suma numerelor date.
Pas 2) Creați o clasă de test parametrizată.
Code Explicație
- Code Linia 11: Adnotați clasa de test folosind @RunWith(Parameterized.class).
- Code Linia 13: Declararea variabilei „firstNumber” ca private și tipul ca int.
- Code Linia 14: Declararea variabilei „secondNumber” ca fiind privată și de tip int.
- Code Linia 15: Declararea variabilei „expectedResult” ca fiind privată și de tip int.
- Code Linia 16: Se declară variabila „airthematic” ca fiind privată și de tip Airthematic.
@Alearga cu(nume_clasă.clasă): the @Alearga cu adnotarea este utilizată pentru a specifica numele clasei de alergători. Dacă nu specificăm niciun tip ca parametru, timpul de execuție va alege BlocaJUnit4ClassRunner în mod implicit.
Această clasă este responsabilă pentru rularea testelor cu o nouă instanță de test. Este responsabilă pentru invocarea JUnit metodele ciclului de viață, cum ar fi configurarea (resursele asociate) și demontarea (lansarea resurselor), care sunt descrise în JUnit dispozitiv de testare tutorial.
Pentru a parametriza, trebuie să adnotați clasa folosind @RunWith și să transmiteți fișierul .class necesar pentru testare.
Pas 3) Creați un constructor care stochează datele de test. Acesta stochează 3 variabile.
Pas 4) Creați o metodă statică care generează și returnează date de testare.
Code Linia 32,33: Crearea unui tablou bidimensional (furnizarea parametrilor de intrare pentru adunare). Folosind metoda asList convertim datele într-un tip List, deoarece tipul returnat de metoda de intrare este o Colecție.
Code Linia 30: Utilizarea @Parametrii adnotare pentru a crea un set de date de intrare pentru a rula testul nostru.
Metoda statică identificată de adnotarea @Parameters returnează o Colecție unde fiecare intrare din Colecție va fi data de intrare pentru o iterație a testului. Luați în considerare elementul {1,2,3}. Iată:
- primulNumăr = 1
- al doileaNumăr = 2
- RezultatAșteptat = 3
Aici, fiecare element al tabloului va fi transmis constructorului, pe rând, deoarece clasa este instanțiată de mai multe ori. Prin urmare, cele cinci tablouri declarate în exemplu produc următoarele cinci execuții:
| Repetare | primulNumăr | secondNumber | Rezultat așteptat | Linia de consolă |
|---|---|---|---|---|
| [0] | 1 | 2 | 3 | Suma de Numbers = : 3 |
| [1] | 11 | 22 | 33 | Suma de Numbers = : 33 |
| [2] | 111 | 222 | 333 | Suma de Numbers = : 333 |
| [3] | 10 | 9 | 19 | Suma de Numbers = : 19 |
| [4] | 100 | 9 | 109 | Suma de Numbers = : 109 |
Pas 5) Codul complet.
Code Explicaţie:
- Code Linia 25: Se utilizează adnotarea @Before pentru configurarea resurselor (Airthematic.class aici). Adnotarea @Before este utilizată aici pentru a rula înaintea fiecărui caz de testare. Aceasta conține precondiția testului.
- Code Linia 36: Folosind adnotarea @Test pentru a crea testul nostru.
- Code Linia 39: Crearea unui declarație afirmativă pentru a verifica dacă suma noastră este echivalentă cu ceea ce ne așteptam.
Pas 6) Creați o clasă de testare pentru a rula testul parametrizat:
Code Explicaţie:
- Code Linia 8: Declararea metodei principale a clasei Test care va rula metoda noastră JUnit Test.
- Code Linia 9: Executarea cazurilor de testare folosind JUnitCore.runClasses, care primește numele clasei de test ca parametru (în exemplul nostru folosim AirthematicTest.class).
- Code Linia 11: Procesarea rezultatului folosind o buclă for și afișarea rezultatului eșuat.
- Code Linia 13: Imprimarea rezultatului de succes.
ieșire:
Iată rezultatul, care arată un test reușit fără eșecuri trace, așa cum este indicat mai jos. Rețineți că JUnit vizualizarea listează o intrare per rând de date în loc de un singur test:
Vedeți rezultatul în consolă, care arată adunarea celor două numere:
Teste parametrizate în JUnit 5 cu @ParameterizedTest
Exemplul de mai sus este scris pentru JUnit 4. JUnit 5 (Jupiter) elimină complet modelul de alergător, astfel încât @RunWith(Parameterized.class), constructorul de date și câmpurile de instanță dispar toate. JUnit Codul 4 prezentat mai sus nu este învechit: acesta rulează în continuare neschimbat pe JUnit Platformă prin intermediul motorului vintage. Testele noi, însă, sunt de obicei scrise cu @ParameterizedTest.
Sunt necesare două dependențe: junit-jupiter-api pentru adnotările de test și junit-jupiter-parametri pentru suportul parametrizat. Fără al doilea artefact, adnotările sursă nu se vor rezolva deloc.
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 oferă mai multe surse de argumente, iar cea corectă depinde de forma datelor:
| Adnotare sursă | Furnituri | Folosește-l când |
|---|---|---|
| @ValueSource | O singură coloană de literali | Testul acceptă doar un argument |
| @CsvSource | Rânduri separate prin virgulă în linie | Tabele mici de numere și șiruri de caractere se citesc curat în fișier |
| @CsvFileSource | Rânduri citite dintr-un fișier CSV pe calea de clasă de testare | Setul de date este mare sau este menținut în afara codului |
| @MethodSource | O fabrică statică care returnează un flux de argumente | Sunt necesare obiecte reale, valori calculate sau date aleatorii |
| @EnumSource | Constantele unei enumări | Fiecare valoare enum trebuie exercitată |
Două reguli sunt potrivite pentru majoritatea începătorilor. O adnotare sursă plasată pe o metodă @Test simplă este ignorată silențios, deci metoda trebuie să conțină @ParameterizedTest. Iar o valoare goală neîncadrată între ghilimele din @CsvSource este citită ca nulă, în timp ce o valoare goală între ghilimele este citită ca un șir gol.
JUnit 4 adnotări utilizate în acest articol se mapează pe Jupiter după cum urmează: @RunWith(Parameterized.class) devine @ParameterizedTest plus o adnotare sursă, @Parameters devine @MethodSource sau @CsvSource, iar @Before devine @BeforeEach. Lista completă este prezentată în JUnit adnotări tutorial.
Avantajele și limitele testelor parametrizate
Parametrizarea nu este gratuită. Elimină duplicarea, dar limitează și modul în care poate fi scris un test, așa că merită să cunoașteți ambele părți înainte de a converti o suită existentă.
Avantaje
- Less duplicare: O metodă înlocuiește un bloc de instrucțiuni de afirmare aproape identice, așa cum arată prima captură de ecran din acest articol.
- Acoperire mai ieftină: Adăugarea unui caz limită costă încă un rând de date în loc de un rând complet nou. caz de testare metodă.
- Raportare precisă: Fiecare iterație este raportată separat, astfel încât JUnit Vizualizarea identifică exact ce rând a eșuat, mai degrabă decât o singură eroare agregată.
- Date centralizate: Intrările se află într-o singură metodă și pot fi mutate ulterior într-un fișier CSV sau într-o fabrică fără a atinge aserțiunile.
Limitări
- O formă de afirmație: Fiecare rând rulează aceleași aserțiuni, deci un scenariu care necesită verificări diferite are nevoie în continuare de propria metodă de testare.
- Domeniu de aplicare la nivel de clasă în JUnit 4: Runner-ul parametrizează întreaga clasă, astfel încât metodele @Test fără legătură din acea clasă rulează și ele o dată pe rând.
- Rapoarte ilizibile: Fără un șablon de nume, erorile apar ca testAirthematicTest[3], care nu spune nimic despre datele care au generat erori.
- Date inline voluminoase: Matricele mari aglomerează logica de testare; mutați-le în @CsvFileSource sau într-o fabrică @MethodSource în schimb.
Erori frecvente în JUnit Teste parametrizate
Majoritatea erorilor parametrizate sunt erori de inițializare generate înainte de executarea unei singure aserțiuni. Tabelul de mai jos listează mesajele care apar cel mai des și ce le declanșează.
| Mesaj | Provoca | Repara |
|---|---|---|
| Clasa de test ar trebui să aibă exact un constructor public | Clasa nu declară niciun constructor public sau doi dintre ei | Păstrați un constructor public ai cărui parametri se potrivesc cu coloanele de date |
| Nicio metodă publică cu parametri statici în clasă | Metoda @Parameters nu este public static sau returnează tipul greșit | Declară-o ca o colecție public static și returnează Arrays.asList(…) |
| ExcepțieArgumentIllegal: număr greșit de argumente | Un rând este mai lat sau mai îngust decât lista de parametri a constructorului | Faceți ca fiecare matrice din Colecție să aibă aceeași lățime ca și constructorul |
| Eroare de configurare: fără furnizor de argumente | Un test Jupiter poartă @ParameterizedTest fără adnotare sursă | Adăugați @ValueSource, @CsvSource, @CsvFileSource, @MethodSource sau @EnumSource |
| Adnotarea sursă pare să nu facă nimic | Metoda este adnotată @Test în loc de @ParameterizedTest | Înlocuiți @Test cu @ParameterizedTest și importați junit-jupiter-params |
O altă capcană este starea partajată. Deoarece JUnit construiește o nouă instanță pe rând, orice conținut dintr-un câmp static supraviețuiește fiecărei iterații, iar o valoare scrisă de rândul [0] poate schimba discret rezultatul rândului [4]. Păstrează starea pe rând în câmpurile instanței și resetează resursele partajate în metoda @Before sau @BeforeEach. Îndrumări generale privind izolarea testelor sunt prezentate în testarea unitara tutorial.









