Programiranje

Hamcrest, ki vsebuje tekme

Dokumentacija Hamcrest 1.3 Javadoc za razred Matchers dodaja več dokumentacije za nekatere metode tega razreda, kot je bila na voljo v Hamcrest 1.2. Na primer, štiri preobremenjene metode vsebujejo bolj opisno dokumentacijo Javadoc, kot je prikazano na naslednjih dveh prikaznih primerjalnih zaslonih.

Čeprav lahko človek ugotovi, kako "vsebuje" ujemanja, že tako, da jih preizkusi, vendar Javadoc v Hamcrest 1.3 lažje bere, kako delujejo. Večina razvijalcev Java verjetno pomisli na vedenje, kot je String.contains (CharSequence) ali Collection.contains (Object), ko pomisli na vsebuje () metoda. Z drugimi besedami, večina razvijalcev Java verjetno misli, da "vsebuje" opisuje, ali String / Collection vsebuje predvidene znake / predmete med drugimi možnimi znaki / predmeti. Za tekme Hamcrest pa ima "vsebuje" veliko bolj specifičen pomen. Ker je dokumentacija Hamcrest 1.3 veliko jasnejša, so ujemanja "vsebuje" veliko bolj občutljiva na število elementov in vrstni red elementov, ki se prenašajo na te metode.

Moji primeri, prikazani tukaj, uporabljajo JUnit in Hamcrest. Tu je pomembno poudariti, da se mora Hamcrestova datoteka JAR pojaviti na poti razreda predavanja enote pred datoteko JUnit JAR, sicer pa moram uporabiti "posebno" datoteko JUnit JAR, izdelano za uporabo s samostojno Hamcrest JAR. Z uporabo katerega koli od teh pristopov se izognemo NoSuchMethodError in drugim napakam (npr. Napaka org.hamcrest.Matcher.describeMismatch), ki so posledica neusklajenih različic razredov. O tem odtenku JUnit / Hamcrest sem pisal v objavi v blogu Moving Beyond Core Hamcrest v JUnit.

Naslednja dva posnetka zaslona prikazujeta rezultate (kot je prikazano v NetBeans 7.3) delčkov kode preskusne enote, ki jih bom kasneje prikazal v blogu, da prikažem ujemanja, ki vsebujejo Hamcrest. Preizkusi naj bi imeli nekaj napak (7 preizkusov je uspelo in 4 preizkusi niso uspeli), da bi bilo jasno, kje Hamcrestovi tekmovalci morda ne bodo delovali, kot bi pričakovali brez branja Javadoca. Prva slika prikazuje le 5 opravljenih preizkusov, 2 preskusa neuspešna in 4 preskusa, ki povzročajo napake. To je zato, ker imam JUnit pred Hamcrestom na seznamu učiteljev "Test Libraries" projekta NetBeans. Druga slika prikazuje pričakovane rezultate, ker se Hamcrest JAR pojavi pred JUnit JAR v učni poti projekta "Test Libaries".

Za namene te predstavitve imam na preprost izmišljen tečaj, ki ga je treba preizkusiti. Izvorna koda za to Glavna razred je prikazan naslednji.

Main.java

paket prah v.primeri; uvoz java.util.Collections; uvoz java.util.HashSet; import java.util.Set; / ** * Glavni razred, ki ga je treba preizkusiti. * * @author Dustin * / javni razred Main {/ ** Uporablja diamantnega operaterja Java 7. * / zasebni niz nizov = nov HashSet (); public Main () {} javni logični addString (končni niz newString) {return this.strings.add (newString); } public Set getStrings () {return Collections.unmodifiableSet (this.strings); }} 

Ko je prikazan razred, ki ga je treba preizkusiti, je zdaj čas, da si ogledamo nekaj testov, ki temeljijo na JUnit, s Hamcrestovimi tekmovalci. Natančneje, testi morajo zagotoviti, da se nizi dodajo prek predavanj addString (String) v osnovi Nastavite in dostopna prek getStrings () metoda. Metode preskusov enot, prikazane v nadaljevanju, prikazujejo, kako pravilno uporabljati Hamcrest-ove ujemanja, da ugotovite, ali so dodani nizi v osnovnem razredu Nastavite

Uporaba Hamcrest vsebuje () Matcher z enim nizom v Set Works

 / ** * Ta preizkus bo opravljen, ker obstaja samo en niz, zato bo * vseboval ta niz in vrstni red bo implicitno pravilen. * / @Test public void testAddStringAndGetStringsWithContainsForSingleStringSoWorks () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končno Set nizov = subject.getStrings (); assertThat (nizi, vsebuje ("Java")); } 

Zgornji test enote je uspešno opravljen, ker Nastavite vsebuje samo en niz, zato je vrstni red in število nizov preizkušeno z vsebuje tekme tekem.

Uporaba Hamcrest Contains z enakim številom elementov deluje, če se vrstni red ujema

 / ** * Ujemanje "vsebuje" pričakuje natančno razvrščanje, kar v resnici pomeni, da se * ne sme uporabljati skupaj s {@code Set}. Običajno ta metoda * deluje in metoda z istim imenom in "2" na koncu ne bo delovala ali * obratno. * / @Test public void testAddStringAndGetStringsWithContainsForMultipleStringsNotWorks1 () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končni logični rezultatGroovy = subject.addString ("Groovy"); končno Set nizov = subject.getStrings (); assertThat (nizi, vsebuje ("Java", "Groovy")); } / ** * Ujemanje "contains" pričakuje natančno razvrščanje, kar v resnici pomeni, da se * ne sme uporabljati skupaj s {@code Set}. Običajno ta metoda * deluje in metoda z istim imenom in "1" na koncu ne bo delovala ali * obratno. * / @Test public void testAddStringAndGetStringsWithContainsForMultipleStringsNotWorks2 () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končni logični rezultatGroovy = subject.addString ("Groovy"); končno Nastavi nize = subject.getStrings (); assertThat (nizi, vsebuje ("Groovy", "Java")); } 

Dva zgoraj prikazana primera preskusov enote in njuna posledična izhodna izvedba, kot je prikazano na prejšnjem posnetku zaslona, ​​kažeta, da dokler je število argumentov vsebuje () ujemanja so enaka številu nizov v zbirki, ki se testira, ujemanje maja delo če preizkušeni elementi so v popolnoma enakem vrstnem redu kot elementi v zbirki. Z neurejenim Nastavite, na ta ukaz se torej ni mogoče zanesti, zato vsebuje () ni verjetno, da bi bil primeren za ujemanje s testom enote na Nastavite več kot enega elementa.

Uporaba Hamcrest vsebuje z različnim številom elementov nikoli ne deluje

 / ** * Demonstracija, ki vsebuje, NE bo uspela, če bo število elementov, ki jih vprašate o vsebini, drugačno kot v zbirki. * / @Test public void testAddStringAndGetStringsWithContainsNotWorksDifferentNumberElements1 () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končni logični rezultatGroovy = subject.addString ("Groovy"); končno Nastavi nize = subject.getStrings (); assertThat (nizi, vsebuje ("Java")); } / ** * Demonstracija, ki vsebuje, NE bo podana, če je različno število * elementov, o katerih se sprašuje, vsebuje, kot v zbirki, tudi v * drugačnem vrstnem redu. * / @Test public void testAddStringAndGetStringsWithContainsNotWorksDifferentNumberElements2 () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končni logični rezultatGroovy = subject.addString ("Groovy"); končno Nastavi nize = subject.getStrings (); assertThat (nizi, vsebuje ("Groovy")); } 

Kot kažejo rezultati preskusa JUnit, ti dve enotni preizkusi nikoli ne opravita, ker je število elementov, ki se preskušajo v Nastavite je manj kot število elementov v Nastavite. Z drugimi besedami, to dokazuje, da vsebuje () matcher ne preizkusi zgolj za dani element, ki je v zbirki: preskusi vse prisotne določene elemente in v določenem vrstnem redu. To je v nekaterih primerih morda preveč omejujoče, zato se bom zdaj lotil nekaterih drugih tekem, ki jih Hamcrest določa, ali je element v določeni zbirki.

Uporaba Hamcrest-ove vsebujeInAnyOrder () Matcher

The vsebujeInAnyOrder tekmo ni tako strogo kot vsebuje () ujemanje: omogoča preskušanje preizkušenih elementov v poljubnem vrstnem redu znotraj zbirke, ki vsebuje.

 / ** * Preizkus metod addString in getStrings razreda Main z uporabo Hamcrest * matcher containsInAnyOrder. * / @Test public void testAddStringAndGetStringsWithContainsInAnyOrder () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končni logični rezultatCSharp = subject.addString ("C #"); končni logični rezultatGroovy = subject.addString ("Groovy"); končni logični rezultatScala = subject.addString ("Scala"); končni logični rezultatClojure = subject.addString ("Clojure"); končno Nastavi nize = subject.getStrings (); assertThat (nizi, vsebujeInAnyOrder ("Java", "C #", "Groovy", "Scala", "Clojure")); } / ** * Uporaba vsebujeInAnyOrder in pokažite, da vrstni red ni pomemben, če so * vsi predvideni vnosi v zbirki v nekem vrstnem redu. * / @Test public void testAddStringAndGetStringsWithContainsInAnyOrderAgain () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končni logični rezultatGroovy = subject.addString ("Groovy"); končno Set nizov = subject.getStrings (); assertThat (nizi, vsebujeInAnyOrder ("Java", "Groovy")); assertThat (nizi, vsebujeInAnyOrder ("Groovy", "Java")); } 

Dva preskusa enote, ki sta prikazana tik nad obema, opravita kljub temu, da sta testirana niza zagotovljena vsebujeInAnyOrder () ujemanja v drugačnem vrstnem redu, kot bi lahko obstajali v obeh zbirkah. Vendar manj stroga vsebujeInAnyOrder () matcher še vedno zahteva, da se posredujejo vsi elementi zbirke, ki vsebuje. Naslednji preskus enote ne opravi, ker ta pogoj ni izpolnjen.

 / ** * To ne bo uspelo, ker vsebujeInAnyOrder zahteva, da se vsi elementi ujemajo *, četudi v drugačnem vrstnem redu. Ko bo preizkušen samo en element in dva * elementa v zbirki, še vedno ne bo uspel. Z drugimi besedami, vrstni red * ni pomemben pri vsebujeInInnyOrder, vendar je treba vse elemente v zbirki * še vedno posredovati v ujemajoči se vsebujeInAnyOrder, samo ne v * enakem vrstnem redu. * / @Test public void testAddStringAndGetStringsWithContainsInAnyOrderDiffNumberElements () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končni logični rezultatGroovy = subject.addString ("Groovy"); končno Set nizov = subject.getStrings (); assertThat (nizi, vsebujeInAnyOrder ("Java")); } 

Hamcrest hasItem () in hasItems () Matchers delujejo kot zvoki

Kot je prikazano v naslednjih dveh enotnih preskusnih metodah (obe uspešni), Hamcrest hasItem () (za en izdelek) in hasItems (za več predmetov) uspešno preizkusi, ali ima zbirka enega ali več določenih predmetov, ne glede na vrstni red ali število določenih predmetov. To v resnici deluje bolj tako, kot je večina razvijalcev Java vajena, da "vsebuje" delo pri delu z nizi in zbirkami.

 / ** * Demonstrate hasItem () bo deloval tudi za določanje, da zbirka vsebuje * določen predmet. * / @Test public void testAddStringAndGetStringsWithHasItem () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končni logični rezultatGroovy = subject.addString ("Groovy"); končno Nastavi nize = subject.getStrings (); assertThat (nizi, hasItem ("Groovy")); assertThat (nizi, hasItem ("Java")); } / ** * Dokažite, da hasItems deluje tako, da ugotovi, da ima zbirka enega * ali več elementov in da število elementov in vrstni red elementov * pri določanju prehoda / neuspeha ni pomemben. * / @Test public void testAddStringAndGetStringsWithHasItems () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končni logični rezultatGroovy = subject.addString ("Groovy"); končno Nastavi nize = subject.getStrings (); assertThat (nizi, hasItems ("Groovy", "Java")); assertThat (nizi, hasItems ("Java", "Groovy")); assertThat (nizi, hasItems ("Groovy")); assertThat (nizi, hasItems ("Java")); } 

Hamcrest isIn () Matcher testira omejitve iz druge smeri

Pravkar razpravljali hasItem () in hasItems () tekme so manj stroge kot vsebuje () in še manj stroga kot vsebujeInAnyOrder () in so pogosto tisto, kar si človek želi, ko želi preprosto zagotoviti, da je eden ali več predmetov nekje v zbirki, ne da bi skrbelo za vrstni red predmeta v tej zbirki ali da so drugi možni predmeti v tej zbirki. Drug način za uporabo Hamcrest-a za določitev istega odnosa, vendar iz nasprotne perspektive, je uporaba isIn tekmo. The isIn Matcher določa, ali je predmet nekje z zbirko, ki jo prejme ujemalec, ne glede na vrstni red tega predmeta v zbirki ali pa so v tej zbirki drugi predmeti ali ne.

 / ** * Uporaba isIn matcher za preizkušanje posameznega elementa je v predvideni zbirki. * / @Test public void testAddStringAndGetStringsWithIsIn () {final Main subject = new Main (); končni logični rezultatJava = subject.addString ("Java"); končni logični rezultatGroovy = subject.addString ("Groovy"); končno Nastavi nize = subject.getStrings (); assertThat ("Groovy", isIn (nizi)); assertThat ("Java", isIn (nizi)); } 
$config[zx-auto] not found$config[zx-overlay] not found