Programmering

Hamcrest Containing Matchers

Hamcrest 1.3 Javadoc-dokumentasjonen for Matchers-klassen legger til mer dokumentasjon for flere av klassens metoder enn det som var tilgjengelig i Hamcrest 1.2. For eksempel har de fire overbelastede metodene mer beskrivende Javadoc-dokumentasjon som vist i de to sammenligningsskjermbildene som vises neste.

Selv om man kan finne ut hvordan "inneholder" matchere fungerer bare ved å prøve dem, gjør Javadoc i Hamcrest 1.3 det lettere å lese hvordan de fungerer. De fleste Java-utviklere tenker sannsynligvis på oppførsel som String.contains (CharSequence) eller Collection.contains (Object) når de tenker på en inneholder () metode. Med andre ord, de fleste Java-utviklere tenker sannsynligvis på "inneholder" som en beskrivelse av om String / Collection inneholder de oppgitte tegnene / objektene blant andre mulige tegn / objekter. For Hamcrest-matchere har "inneholder" imidlertid en mye mer spesifikk betydning. Som Hamcrest 1.3-dokumentasjonen gjør mye tydeligere, er "inneholder" matchere mye mer følsomme for antall varer og rekkefølgen på varene som sendes til disse metodene.

Eksemplene mine som vises her bruker JUnit og Hamcrest. Det er viktig å understreke her at Hamcrests JAR-fil må vises på enhetstestens klassevei før JUnits JAR-fil, ellers må jeg bruke den "spesielle" JUnit JAR-filen som er bygget for bruk med den frittstående Hamcrest JAR. Ved å bruke en av disse tilnærmingene unngås NoSuchMethodError og andre feil (som org.hamcrest.Matcher.describeMismatch feil) som skyldes feil samsvarende versjoner av klasser. Jeg har skrevet om denne JUnit / Hamcrest-nyansen i blogginnlegget Moving Beyond Core Hamcrest i JUnit.

De neste to skjermbildene viser resultatene (som vist i NetBeans 7.3) av enhetstestkodebitene som jeg viser senere i bloggen for å demonstrere Hamcrest-holdige matchere. Testene skal ha noen feil (7 bestått tester og 4 tester som ikke lykkes) for å gjøre det åpenbart hvor Hamcrest-matchere kanskje ikke fungerer som man forventer uten å lese Javadoc. Det første bildet viser bare 5 bestått tester, 2 tester mislykkes og 4 tester som forårsaker feil. Dette er fordi jeg har ført JUnit opp før Hamcrest på NetBeans-prosjektets "Test Libraries" klassesti. Det andre bildet viser de forventede resultatene fordi Hamcrest JAR oppstår før JUnit JAR i prosjektets "Test Libaries" -klassen.

I forbindelse med denne demonstrasjonen har jeg en enkel konstruert klasse som skal testes. Kildekoden for det Hoved klasse vises neste.

Hoved.java

pakke dustin. eksempler; importere java.util.Collections; importere java.util.HashSet; importere java.util.Set; / ** * Hovedklasse som skal enhetstestes. * * @author Dustin * / public class Main {/ ** Bruker Java 7s diamantoperatør. * / private Set strings = new HashSet (); public Main () {} public boolean addString (final String newString) {return this.strings.add (newString); } public Set getStrings () {return Collections.unmodifiableSet (this.strings); }} 

Med klassen som skal testes vist, er det nå på tide å se på å bygge noen JUnit-baserte tester med Hamcrest-matchere. Spesielt skal testene sikre at strenger legges til via klassen addString (streng) metoden er i dens underliggende Sett og tilgjengelig via getStrings () metode. Enhetstestmetodene som vises nedenfor viser hvordan du bruker Hamcrest-matchere på riktig måte for å avgjøre om ekstra strenger er inkludert i klassens underliggende Sett

Bruk av Hamcrest inneholder () Matcher med enkelt streng i settverk

 / ** * Denne testen vil bestå fordi det bare er en enkelt streng, og den vil derfor * inneholde at den enkelte streng og rekkefølge vil være riktig underforstått. * / @Test public void testAddStringAndGetStringsWithContainsForSingleStringSoWorks () {final Main subject = new Main (); endelig boolsk resultatJava = subject.addString ("Java"); siste Sett strenger = subject.getStrings (); assertThat (strenger, inneholder ("Java")); } 

Enhetstesten vist ovenfor består fordi Sett har bare en streng i seg, og rekkefølgen og antall strenger testet med inneholder matcher kamper.

Bruk av Hamcrest Inneholder med samme antall elementer som fungerer hvis ordre samsvarer

 / ** * Matcheren "inneholder" forventer nøyaktig rekkefølge, noe som virkelig betyr at den ikke * skal brukes sammen med {@code Set} s. Enten vil denne metoden * fungere, og metoden med samme navn og "2" vil ikke fungere eller * omvendt. * / @Test public void testAddStringAndGetStringsWithContainsForMultipleStringsNotWorks1 () {final Hovedemne = nytt Main (); endelig boolsk resultatJava = subject.addString ("Java"); endelig boolsk resultatGroovy = subject.addString ("Groovy"); siste Sett strenger = subject.getStrings (); assertThat (strenger, inneholder ("Java", "Groovy")); } / ** * Matcheren "inneholder" forventer nøyaktig rekkefølge, noe som virkelig betyr at den ikke * skal brukes sammen med {@code Set}. Enten vil denne metoden * fungere, og metoden med samme navn og "1" vil ikke fungere eller * omvendt. * / @Test public void testAddStringAndGetStringsWithContainsForMultipleStringsNotWorks2 () {final Hovedemne = nytt Main (); endelig boolsk resultatJava = subject.addString ("Java"); endelig boolsk resultatGroovy = subject.addString ("Groovy"); final Sett strenger = subject.getStrings (); assertThat (strenger, inneholder ("Groovy", "Java")); } 

De to eksemplet på enhetstester vist ovenfor og deres resulterende resultat av å kjøre testene som vist i forrige skjermbilde, viser at så lenge antallet argumenter til inneholder () matcher er det samme som antall strenger i samlingen som testes, kampen kan arbeid hvis elementene som er testet er i nøyaktig samme rekkefølge som elementene i samlingen. Med en uordnet Sett, denne ordren kan ikke stole på, så inneholder () sannsynligvis ikke vil være en god matcher å bruke med en enhetstest på en Sett av mer enn ett element.

Bruk av Hamcrest Inneholder med forskjellige antall elementer som aldri fungerer

 / ** * Demonstrasjon som inneholder vil IKKE bestå når det er et annet antall * elementer som er spurt om inneholder enn i samlingen. * / @Test public void testAddStringAndGetStringsWithContainsNotWorksDifferentNumberElements1 () {final Main subject = new Main (); endelig boolsk resultatJava = subject.addString ("Java"); endelig boolsk resultatGroovy = subject.addString ("Groovy"); final Sett strenger = subject.getStrings (); assertThat (strenger, inneholder ("Java")); } / ** * Demonstrasjon som inneholder, vil IKKE passere når det er et annet antall * elementer som er spurt om inneholder enn i samlingen, selv når de er i * annen rekkefølge. * / @Test public void testAddStringAndGetStringsWithContainsNotWorksDifferentNumberElements2 () {final Main subject = new Main (); endelig boolsk resultatJava = subject.addString ("Java"); endelig boolsk resultatGroovy = subject.addString ("Groovy"); final Sett strenger = subject.getStrings (); assertThat (strenger, inneholder ("Groovy")); } 

Som JUnit-testresultatene indikerer, består disse to enhetstestene aldri fordi antall elementer som testes for i Sett er færre enn antall elementer i Sett. Med andre ord, dette beviser at inneholder () matcher tester ikke bare for at et gitt element er i en samling: den tester for at alle spesifiserte elementer er til stede og i den angitte rekkefølgen. Dette kan være for begrensende i noen tilfeller, så nå går jeg videre til noen andre kamper Hamcrest gir for å avgjøre om et element er inneholdt i en bestemt samling.

Ved å bruke Hamcrest's inneholderInAnyOrder () Matcher

De inneholderInAnyOrder matcher er ikke så streng som inneholder () matcher: det lar testede elementer være i hvilken som helst rekkefølge i den inneholder samlingen for å passere.

 / ** * Test av addString og getStrings metoder i klasse Main ved bruk av Hamcrest * matcher inneholderInAnyOrder. * / @Test public void testAddStringAndGetStringsWithContainsInAnyOrder () {final Main subject = new Main (); endelig boolsk resultatJava = subject.addString ("Java"); endelig boolsk resultatCSharp = subject.addString ("C #"); endelig boolsk resultatGroovy = subject.addString ("Groovy"); endelig boolsk resultatScala = subject.addString ("Scala"); endelig boolsk resultatClojure = subject.addString ("Clojure"); final Sett strenger = subject.getStrings (); assertThat (strenger, inneholderInAnyOrder ("Java", "C #", "Groovy", "Scala", "Clojure")); } / ** * Bruk containInAnyOrder og vis at ordren ikke betyr noe så lenge * alle oppgitte oppføringer er i samlingen i en eller annen rekkefølge. * / @Test public void testAddStringAndGetStringsWithContainsInAnyOrderAgain () {final Main subject = new Main (); endelig boolsk resultatJava = subject.addString ("Java"); endelig boolsk resultatGroovy = subject.addString ("Groovy"); final Sett strenger = subject.getStrings (); assertThat (strenger, inneholderInAnyOrder ("Java", "Groovy")); assertThat (strenger, inneholderInAnyOrder ("Groovy", "Java")); } 

De to enhetstestene som er vist rett over begge passerer til tross for at strengene som testes blir gitt til inneholderInAnyOrder () matcher i en annen rekkefølge enn hva de kunne eksistere i for begge samlingene. Imidlertid jo mindre strenge inneholderInAnyOrder () matcher krever fortsatt at alle elementene i den inneholder samlingen skal spesifiseres for å passere. Følgende enhetstest består ikke fordi denne betingelsen ikke er oppfylt.

 / ** * Dette mislykkes fordi inneholderInAnyOrder krever at alle elementene samsvares * selv om de er i annen rekkefølge. Med bare ett element som er prøvd og to * elementer i samlingen, vil det fortsatt mislykkes. Med andre ord betyr ikke rekkefølge * noe med inneholderInAnyOrder, men alle elementene i samlingen * må fremdeles sendes til matchesInAnyOrder-matcher, bare ikke i * nøyaktig samme rekkefølge. * / @Test public void testAddStringAndGetStringsWithContainsInAnyOrderDiffNumberElements () {final Main subject = new Main (); endelig boolsk resultatJava = subject.addString ("Java"); endelig boolsk resultatGroovy = subject.addString ("Groovy"); siste Sett strenger = subject.getStrings (); assertThat (strenger, inneholderInAnyOrder ("Java")); } 

Hamcrest hasItem () og hasItems () Matchers Work As Sounds

Som vist i de neste to enhetstestmetodene (som begge består), Hamcrest hasItem () (for enkeltvare) og hasItems (for flere artikler) tester vellykket om en samling har henholdsvis ett eller flere enn en spesifisert vare uten hensyn til bestilling eller antall spesifiserte varer. Dette fungerer virkelig mer som de fleste Java-utviklere er vant til å "inneholder" når de jobber med strenger og samlinger.

 / ** * Demonstrer hasItem () vil også fungere for å bestemme at en samling inneholder * et bestemt element. * / @Test public void testAddStringAndGetStringsWithHasItem () {final Main subject = new Main (); endelig boolsk resultatJava = subject.addString ("Java"); endelig boolsk resultatGroovy = subject.addString ("Groovy"); siste Sett strenger = subject.getStrings (); assertThat (strenger, hasItem ("Groovy")); assertThat (strenger, hasItem ("Java")); } / ** * Demonstrer at hasItems fungerer for å bestemme at en samling har en * eller flere elementer, og at antall varer og rekkefølgen på varene * ikke er viktig for å bestemme pass / fiasko. * / @Test public void testAddStringAndGetStringsWithHasItems () {final Main subject = new Main (); endelig boolsk resultatJava = subject.addString ("Java"); endelig boolsk resultatGroovy = subject.addString ("Groovy"); final Sett strenger = subject.getStrings (); assertThat (strenger, hasItems ("Groovy", "Java")); assertThat (strenger, hasItems ("Java", "Groovy")); assertThat (strenger, hasItems ("Groovy")); assertThat (strenger, hasItems ("Java")); } 

Hamcrest isIn () Matcher tester inneslutning fra annen retning

Den nettopp diskuterte hasItem () og hasItems () matchere er mindre strenge enn inneholder () og enda mindre streng enn inneholderInAnyOrder () og er ofte det man vil når man bare vil sikre at en eller flere gjenstander er et sted i en samling uten bekymring for varens rekkefølge i den samlingen, eller at andre mulige gjenstander er i den samlingen. En annen måte å bruke Hamcrest til å bestemme det samme forholdet, men fra det motsatte perspektivet, er å bruke er i matcher. De er i matcher avgjør om et element er et sted med samlingen levert til matcheren uten hensyn til varens bestilling i samlingen eller om det er andre varer i den som inneholder samlingen.

 / ** * Bruk isIn matcher til å teste individuelt element er i den oppgitte samlingen. * / @Test public void testAddStringAndGetStringsWithIsIn () {final Main subject = new Main (); endelig boolsk resultatJava = subject.addString ("Java"); endelig boolsk resultatGroovy = subject.addString ("Groovy"); siste Sett strenger = subject.getStrings (); assertThat ("Groovy", isIn (strenger)); assertThat ("Java", isIn (strenger)); } 
$config[zx-auto] not found$config[zx-overlay] not found