JUnit 5 je novi de facto standard za razvijanje enotnih testov v Javi. Ta najnovejša različica je za seboj pustila omejitve Java 5 in integrirala številne funkcije Java 8, predvsem podporo za lambda izraze.
V tej prvi polovici dvodelnega uvoda v JUnit 5 boste začeli s testiranjem z JUnit 5. Pokazal vam bom, kako konfigurirati projekt Maven za uporabo JUnit 5, kako pisati teste z uporabo @Test
in @ParameterizedTest
in kako delati z novimi pripisi v življenjskem ciklu v JUnit 5. Videli boste tudi kratek primer uporabe oznak filtra in pokazal vam bom, kako JUnit 5 integrirati s knjižnico trditev drugih proizvajalcev - v tem primeru , Hamcrest. Na koncu boste dobili hiter uvod v integracijo JUnit 5 z Mockito, tako da boste lahko napisali bolj robustne enote za kompleksne resnične sisteme.
Testno voden razvoj
Če že kdaj razvijate kodo Java, ste verjetno dobro seznanjeni s testnim razvojem, zato bom ta odsek na kratko. Pomembno je razumeti zakaj pišemo enotne teste, pa tudi strategije, ki jih razvijalci uporabljajo pri oblikovanju enotnih testov.
Test-driven development (TDD) je postopek razvoja programske opreme, ki prepleta kodiranje, testiranje in oblikovanje. To je preizkusni pristop, katerega cilj je izboljšati kakovost vaših aplikacij. Testno usmerjen razvoj je opredeljen z naslednjim življenjskim ciklom:
- Dodajte test.
- Zaženite vse teste in opazujte, da novi test ne uspe.
- Uporabite kodo.
- Zaženite vse teste in opazujte, kako novi test uspe.
- Refaktor kode.
Slika 1 prikazuje ta življenjski cikel TDD.
Steven HainesPisanje testov pred pisanjem kode ima dvojni namen. Najprej vas prisili k razmišljanju o poslovnem problemu, ki ga želite rešiti. Na primer, kako naj se obnašajo uspešni scenariji? Kateri pogoji bi morali propasti? Kako naj propadejo? Drugič, najprej vam testiranje daje več zaupanja v svoje teste. Kadar pišem teste po pisanju kode, jih moram vedno razbiti, da se prepričam, da dejansko lovijo napake. Pisanje testov se najprej izogne dodatnemu koraku.
Pisanje testov za srečno pot je običajno enostavno: ob dobrem vnosu bi moral razred vrniti deterministični odziv. Toda pisanje negativnih (ali neuspešnih) testnih primerov, zlasti za kompleksne komponente, je lahko bolj zapleteno.
Kot primer razmislite o pisanju testov za repozitorij baze podatkov. Na srečni poti v bazo vstavimo zapis in prejmemo nazaj ustvarjeni predmet, vključno z morebitnimi ustvarjenimi ključi. V resnici moramo upoštevati tudi možnost konflikta, na primer vstaviti zapis z edinstveno vrednostjo stolpca, ki ga že ima drug zapis. Poleg tega, kaj se zgodi, ko se skladišče ne more povezati z bazo podatkov, morda zato, ker se je spremenilo uporabniško ime ali geslo? Kaj se zgodi, če pri prevozu pride do omrežne napake? Kaj se zgodi, če se zahteva ne izpolni v določeni časovni omejitvi?
Če želite zgraditi robustno komponento, morate upoštevati vse verjetne in verjetne scenarije, zanje razviti teste in napisati kodo, ki bo zadovoljila te teste. Kasneje v članku bomo preučili strategije za ustvarjanje različnih scenarijev okvar, skupaj z nekaterimi novimi funkcijami v JUnit 5, ki vam lahko pomagajo pri preizkusu teh scenarijev.
Sprejetje JUnit 5
Če že nekaj časa uporabljate JUnit, bodo nekatere spremembe v JUnit 5 prilagoditev. Tu je povzetek na visoki ravni, kaj se razlikuje med obema različicama:
- JUnit 5 je zdaj zapakiran v
org.junit.jupiter
group, kar spremeni način, kako ga boste vključili v svoje projekte Maven in Gradle. - JUnit 4 je zahteval najmanj JDK 5 JDK; JUnit 5 zahteva najmanj 8 JDK.
- JUNIT 4
@ Pred tem
,@BeforeClass
,@Po
, in@Po pouku
pripisi so bili nadomeščeni z@BeforeEach
,@BeforeAll
,@AfterEach
, in@Konec koncev
oziroma. - JUNIT 4
@ Prezri
pripis je bil nadomeščen z@Onemogočeno
pripis. - The
@Kategorija
pripis je bil nadomeščen z@Oznaka
pripis. - JUnit 5 doda nov nabor metod uveljavljanja.
- Tekači so bili zamenjani z razširitvami, z novim API-jem za izvedbe razširitev.
- JUnit 5 uvaja predpostavke, ki ustavijo izvajanje testa.
- JUnit 5 podpira vgnezdene in dinamične preizkusne razrede.
Večino teh novih funkcij bomo raziskali v tem članku.
Enotno testiranje z JUnit 5
Začnimo preprosto, s primerom konfiguriranja projekta za uporabo JUnit 5 za preskus enote. Seznam 1 prikazuje a MathTools
razred, katerega metoda pretvori števec in imenovalec v dvojno
.
Seznam 1. Primer projekta JUnit 5 (MathTools.java)
paket com.javaworld.geekcap.math; javni razred MathTools {javni statični dvojni convertToDecimal (int števec, int imenovalec) {if (imenovalec == 0) {vrzi novo IllegalArgumentException ("Imenovalec ne sme biti 0"); } vrniti (dvojni) števec / (dvojni) imenovalec; }}
Za preskušanje imamo dva glavna scenarija MathTools
razred in njegova metoda:
- A veljaven test, v katerem za števec in imenovalec posredujemo cela števila, ki niso nič.
- A scenarij okvare, v katerem za imenovalec prenesemo ničto vrednost.
Seznam 2 prikazuje preskusni razred JUnit 5 za preizkušanje teh dveh scenarijev.
Seznam 2. Preskusni razred JUnit 5 (MathToolsTest.java)
paket com.javaworld.geekcap.math; import java.lang.IllegalArgumentException; uvoz org.junit.jupiter.api.Trditve; uvoz org.junit.jupiter.api.Test; razred MathToolsTest {@Test void testConvertToDecimalSuccess () {dvojni rezultat = MathTools.convertToDecimal (3, 4); Assertions.assertEquals (0,75, rezultat); } @Test void testConvertToDecimalInvalidDenominator () {Assertions.assertThrows (IllegalArgumentException.class, () -> MathTools.convertToDecimal (3, 0)); }}
V seznamu 2 je testConvertToDecimalInvalidDenominator
metoda izvrši MathTools :: convertToDecimal
metoda znotraj assertThrows
pokličite. Prvi argument je pričakovana vrsta izjeme. Drugi argument je funkcija, ki bo vrgla to izjemo. The assertThrows
metoda izvrši funkcijo in preveri, ali je vržena pričakovana vrsta izjeme.
Razred Assertions in njegove metode
Theorg.junit.jupiter.api.Test
oznaka označuje preskusno metodo. Upoštevajte, da @Test
opomba zdaj prihaja iz paketa JUnit 5 Jupiter API namesto JUnit 4 org.junit
paket. The testConvertToDecimalSuccess
metoda najprej izvede MathTools :: convertToDecimal
metoda s števcem 3 in imenovalcem 4, nato trdi, da je rezultat enak 0,75. The org.junit.jupiter.api.Trditve
razred ponuja nabor statično
metode za primerjavo dejanskih in pričakovanih rezultatov. The Trditve
class ima naslednje metode, ki pokrivajo večino primitivnih podatkovnih vrst:
assertArrayEquals
primerja vsebino dejanskega polja s pričakovanim nizom.assertEquals
primerja dejansko vrednost s pričakovano vrednostjo.assertNotEquals
primerja dve vrednosti, da potrdi, da nista enaki.assertTrue
preveri, ali je navedena vrednost resnična.assertFalse
potrdi, da je navedena vrednost napačna.assertLinesMatch
primerja dva seznamaVrvica
s.assertNull
potrdi, da je navedena vrednost nična.assertNotNull
potrdi, da navedena vrednost ni nič.assertSame
preveri, da se dve vrednosti nanašata na isti objekt.assertNotSame
preveri, da se dve vrednosti ne nanašata na isti objekt.assertThrows
potrjuje, da izvajanje metode vrže pričakovano izjemo (to lahko vidite vtestConvertToDecimalInvalidDenominator
primer zgoraj).assertTimeout
preveri, ali se dobavljena funkcija dokonča v določenem času.assertTimeoutPreempitive
preveri, ali se dobavljena funkcija zaključi v določenem časovnem poteku, a ko je dosežen, prekine izvajanje funkcije.
Če katera od teh trditev ne uspe, je preskus enote označen kot neuspešen. To obvestilo o napaki bo zapisano na zaslon, ko zaženete preizkus, nato pa shranjeno v datoteki poročila.
Uporaba delte z assertEquals
Pri uporabi plovec
in dvojno
vrednosti v assertEquals
, lahko določite tudi delta
ki predstavlja prag razlike med obema. V našem primeru bi lahko dodali delto 0,001, če bi bilo 0,75 dejansko vrnjeno kot 0,750001.
Analiziranje rezultatov testa
Poleg preverjanja vrednosti ali vedenja, trditi
metode lahko sprejmejo tudi besedilni opis napake, ki vam lahko pomaga pri diagnosticiranju napak. Na primer:
Assertions.assertEquals (0,75, rezultat, "Vrednost MathTools :: convertToDecimal ni vrnila pravilne vrednosti 0,75 za 3/4"); Assertions.assertEquals (0,75, rezultat, () -> "Vrednost MathTools :: convertToDecimal ni vrnila pravilne vrednosti 0,75 za 3/4");
Rezultat bo prikazal pričakovano vrednost 0,75 in dejansko vrednost. Prikazalo se bo tudi določeno sporočilo, ki vam lahko pomaga razumeti kontekst napake. Razlika med obema različicama je v tem, da prva vedno ustvari sporočilo, tudi če ni prikazano, druga pa sporočilo ustvari le, če trditev ne uspe. V tem primeru je konstrukcija sporočila nepomembna, zato v resnici ni pomembno. Kljub temu ni treba ustvariti sporočila o napaki za preizkus, ki je uspešno opravljen, zato je običajno najboljša praksa, da uporabimo drugi slog.
Nazadnje, če za izvajanje testov uporabljate IDE, kot je IntelliJ, bo vsaka testna metoda prikazana z imenom metode. To je v redu, če so imena metod berljiva, lahko pa dodate tudi @DisplayName
pripis k testnim metodam, da jih bolje prepoznate:
@Test @DisplayName ("Testiraj uspešno decimalno pretvorbo") void testConvertToDecimalSuccess () {dvojni rezultat = MathTools.convertToDecimal (3, 4); Assertions.assertEquals (0,751, rezultat); }
Izvajanje testa enote
Če želite zagnati teste JUnit 5 iz projekta Maven, morate vključiti maven-surefire-plugin
v Mavenu pom.xml
datoteko in dodajte novo odvisnost. Seznam 3 prikazuje pom.xml
datoteka za ta projekt.
Seznam 3. Maven pom.xml za primer projekta JUnit 5
4.0.0 com.javaworld.geekcap junit5 jar 1.0-SNAPSHOT org.apache.maven.plugins maven-compiler-plugin 3.8.1 8 8 org.apache.maven.plugins maven-surefire-plugin 3.0.0-M4 junit5 // maven.apache.org org.junit.jupiter junit-jupiter 5.6.0 test
JUNIT 5 odvisnosti
JUnit 5 pakira svoje komponente v org.junit.jupiter
skupini in moramo dodati junit-jupiter
artefakt, ki je zbirni artefakt, ki uvaža naslednje odvisnosti:
junit-jupiter-api
definira API za pisanje testov in razširitev.junit-jupiter-motor
je izvedba preizkusnega motorja, ki izvaja preskuse enot.junit-jupiter-params
zagotavlja podporo za parametrizirane teste.
Nato moramo dodati maven-surefire-plugin
zgraditi vtičnik za izvajanje preskusov.
Na koncu vključite tudi maven-compiler-plugin
z različico Java 8 ali novejšo, tako da boste lahko uporabljali funkcije Java 8, kot so lambda.
Zaženi!
Z naslednjim ukazom zaženite preskusni razred iz IDE ali Mavena:
mvn čisti test
Če ste uspešni, bi morali videti rezultate, podobne naslednjim:
[INFO] ------------------------------------------------ -------- [INFO] PRESKUSI [INFO] ----------------------------------- -------------------- [INFO] Izvajanje com.javaworld.geekcap.math.MathToolsTest [INFO] Izvedeni testi: 2, napake: 0, napake: 0, preskočeno : 0, potekel čas: 0,04 s - v com.javaworld.geekcap.math.MathToolsTest [INFO] [INFO] Rezultati: [INFO] [INFO] Izvedeni testi: 2, neuspehi: 0, napake: 0, preskočeni: 0 [ INFO] [INFO] --------------------------------------------- --------------------------- [INFO] ZGRADI USPEH [INFO] --------------- -------------------------------------------------- ------- [INFO] Skupni čas: 3.832 s [INFO] Končano ob: 2020-02-16T08: 21: 15-05: 00 [INFO] ------------- -------------------------------------------------- ---------