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.









