Testiranje s Hamcrestom

1. Pregled

Hamcrest je dobro poznati okvir koji se koristi za jedinstveno testiranje u Java ekosustavu. Sadržan je u JUnit-u i, jednostavno rečeno, koristi postojeće predikate - nazvane klase podudaranja - za donošenje tvrdnji.

U ovom uputstvu hoćemo istražiti Hamcrest API i naučite kako to iskoristiti za pisanje urednijih i intuitivnijih jediničnih testova za naš softver.

2. Hamcrest postavljanje

Možemo koristiti Hamcrest s maven dodavanjem sljedeće ovisnosti našem pom.xml datoteka:

 org.hamcrest hamcrest-svi 1.3 

Najnoviju verziju ove knjižnice uvijek možete pronaći ovdje.

3. Primjer testa

Hamcrest se obično koristi sa junit i drugi ispitni okviri za iznošenje tvrdnji. Točnije, umjesto korištenja junit‘Je mnogobrojna tvrditi metode, koristimo samo API-jev single ustvrdiTo izjava s odgovarajućim podudaranjima.

Pogledajmo primjer koji testira dva Nizs za jednakost bez obzira na slučaj. To bi nam trebalo dati jasnu predodžbu o tome kako Hamcrest uklapa se u metodu ispitivanja:

javna klasa StringMatcherTest {@Test javna praznina given2Strings_whenEqual_thenCorrect () {String a = "foo"; Niz b = "FOO"; assertThat (a, jednakToIgnoringCase (b)); }}

U sljedećim odjeljcima ćemo pogledati nekoliko drugih uobičajenih podudaranja Hamcrest ponude.

4. The Objekt Podudaranje

Hamcrest pruža podudaranje za iznošenje tvrdnji o proizvoljnim Java objektima.

Tvrditi da je toString metoda an Objekt vraća navedeni Niz:

@Test javna praznina givenBean_whenToStringReturnsRequiredString_thenCorrect () {Osoba osoba = nova osoba ("Baraka", "Washington"); Niz str = person.toString (); assertThat (osoba, hasToString (str)); }

Također možemo provjeriti je li jedan razred podklase drugog:

@Test javna praznina given2Classes_whenOneInheritsFromOther_thenCorrect () {assertThat (Cat.class, typeCompatibleWith (Animal.class)); }}

5. Podudaranje graha

Možemo koristiti Hamcrest'S Bean Matcher za pregled svojstava Java graha.

Pretpostavimo sljedeće Osoba grah:

javni razred Osoba {Ime niza; Adresa niza; javna osoba (niz personName, string personAddress) {name = personName; adresa = personAddress; }}

Možemo provjeriti ima li grah svojstvo, Ime ovako:

@Test javna praznina givenBean_whenHasValue_thenCorrect () {Osoba osoba = nova osoba ("Baeldung", 25); assertThat (person, hasProperty ("name")); }

Također možemo provjeriti je li Osoba ima adresa svojstvo, inicijalizirano u New Yorku:

@Test javna praznina givenBean_whenHasCorrectValue_thenCorrect () {Osoba osoba = nova osoba ("Baeldung", "New York"); assertThat (person, hasProperty ("address", jednakTo ("New York"))); }

Možemo provjeriti i dvije Osoba objekti se grade s istim vrijednostima:

@Test javna praznina given2Beans_whenHavingSameValues_thenCorrect () {Person person1 = new Person ("Baeldung", "New York"); Osoba person2 = nova osoba ("Baeldung", "New York"); assertThat (person1, samePropertyValuesAs (person2)); } 

6. The Kolekcija Podudaranje

Hamcrest osigurava podudarnosti za inspekciju Kolekcijas.

Jednostavna provjera da biste saznali je li Kolekcija prazno je:

@Test javna praznina givenCollection_whenEmpty_thenCorrect () {List emptyList = new ArrayList (); assertThat (emptyList, empty ()); }

Da biste provjerili veličinu a Kolekcija:

@Test javna praznina danaAList_whenChecksSize_thenCorrect () {Popis hamcrestMatchers = Arrays.asList ("zbirke", "grah", "tekst", "broj"); assertThat (hamcrestMatchers, hasSize (4)); }

Također ga možemo koristiti za utvrđivanje da niz ima potrebnu veličinu:

@Test javna praznina givenArray_whenChecksSize_thenCorrect () {String [] hamcrestMatchers = {"zbirke", "grah", "tekst", "broj"}; assertThat (hamcrestMatchers, arrayWithSize (4)); }

Da biste provjerili je li Kolekcija sadrži dane članove, bez obzira na redoslijed:

@Test javna praznina danaAListAndValues_whenChecksListForGivenValues_thenCorrect () {Popis hamcrestMatchers = Arrays.asList ("zbirke", "grah", "tekst", "broj"); assertThat (hamcrestMatchers, containsInAnyOrder ("grah", "tekst", "zbirke", "broj")); }

Da bi se dalje ustvrdilo da je Kolekcija članovi su poredani prema redoslijedu:

@Test javna praznina danaAListAndValues_whenChecksListForGivenValuesWithOrder_thenCorrect () {Popis hamcrestMatchers = Arrays.asList ("zbirke", "grah", "tekst", "broj"); assertThat (hamcrestMatchers, sadrži ("zbirke", "grah", "tekst", "broj")); }

Da biste provjerili ima li niz jedan zadani element:

@Test javna praznina givenArrayAndValue_whenValueFoundInArray_thenCorrect () {String [] hamcrestMatchers = {"zbirke", "grah", "tekst", "broj"}; assertThat (hamcrestMatchers, hasItemInArray ("tekst")); }

Za isti test možemo koristiti i alternativno podudaranje:

@Test javna praznina givenValueAndArray_whenValueIsOneOfArrayElements_thenCorrect () {String [] hamcrestMatchers = {"zbirke", "grah", "tekst", "broj"}; assertThat ("tekst", isOneOf (hamcrestMatchers)); }

Ili još uvijek možemo učiniti isto s drugim podudaranjem, poput ovako:

@Test javna praznina givenValueAndArray_whenValueFoundInArray_thenCorrect () {String [] niz = novi String [] {"zbirke", "grah", "tekst", "broj"}; assertThat ("grah", isIn (niz)); }

Također možemo provjeriti sadrži li niz zadane elemente bez obzira na redoslijed:

@Test javna praznina givenArrayAndValues_whenValuesFoundInArray_thenCorrect () {String [] hamcrestMatchers = {"zbirke", "grah", "tekst", "broj"}; assertThat (hamcrestMatchers, arrayContainingInAnyOrder ("grah", "zbirke", "broj", "tekst")); }

Da biste provjerili sadrži li niz zadane elemente, ali u danom redoslijedu:

@Test javna praznina givenArrayAndValues_whenValuesFoundInArrayInOrder_thenCorrect () {String [] hamcrestMatchers = {"zbirke", "grah", "tekst", "broj"}; assertThat (hamcrestMatchers, arrayContaining ("zbirke", "grah", "tekst", "broj")); }

Kad naš Kolekcija je Karta, možemo koristiti sljedeće podudarnosti u ovim odgovarajućim funkcijama:

Da biste provjerili sadrži li zadani ključ:

@Test javna praznina givenMapAndKey_whenKeyFoundInMap_thenCorrect () {Map map = new HashMap (); map.put ("ime bloga", "baeldung"); assertThat (map, hasKey ("blogname")); }

i zadana vrijednost:

@Test javna praznina givenMapAndValue_whenValueFoundInMap_thenCorrect () {Map map = new HashMap (); map.put ("ime bloga", "baeldung"); assertThat (map, hasValue ("baeldung")); }

i na kraju zadani unos (ključ, vrijednost):

@Test javna praznina givenMapAndEntry_whenEntryFoundInMap_thenCorrect () {Map map = new HashMap (); map.put ("ime bloga", "baeldung"); assertThat (map, hasEntry ("blogname", "baeldung")); }

7. The Broj Podudaranje

The Broj podudaranja se koriste za izvođenje tvrdnji o varijablama Broj razred.

Provjeriti većeNego stanje:

@Test javna praznina givenAnInteger_whenGreaterThan0_thenCorrect () {assertThat (1, većeThan (0)); }

Provjeriti većeNego ili jednak stanje:

@Test javna praznina givenAnInteger_whenGreaterThanOrEqTo5_thenCorrect () {assertThat (5, većaThanOrEqualTo (5)); }

Provjeriti manje od stanje:

@Test javna praznina givenAnInteger_whenLessThan0_thenCorrect () {assertThat (-1, lessThan (0)); }

Provjeriti manje od ili jednak stanje:

@Test javna praznina givenAnInteger_whenLessThanOrEqTo5_thenCorrect () {assertThat (-1, lessThanOrEqualTo (5)); }

Provjeriti blizu stanje:

@Test javna praznina danaADouble_whenCloseTo_thenCorrect () {assertThat (1.2, closeTo (1, 0.5)); }

Pazimo dobro na posljednju utakmicu, blizu. Prvi argument, operand, je onaj s kojim se uspoređuje cilj, a drugi argument je dopušteno odstupanje od operanda . To znači da ako je cilj operand + odstupanje ili odstupanje operanda, tada će test proći.

8. Podudaranje teksta

Tvrdnja o Nizs je olakšan, uredniji i intuitivniji Hamcrest‘S podudaranja teksta. Pogledat ćemo ih u ovom odjeljku.

Da biste provjerili je li Niz prazno je:

@Test javna praznina givenString_whenEmpty_thenCorrect () {String str = ""; assertThat (str, isEmptyString ()); }

Da biste provjerili je li Niz je prazna ili null:

@Test javna praznina givenString_whenEmptyOrNull_thenCorrect () {String str = null; assertThat (str, isEmptyOrNullString ()); }

Provjeriti jednakost dvoje Nizs zanemarujući bijeli prostor:

@Test javna praznina given2Strings_whenEqualRegardlessWhiteSpace_thenCorrect () {String str1 = "text"; Niz str2 = "tekst"; assertThat (str1, jednakToIgnoringWhiteSpace (str2)); }

Također možemo provjeriti prisutnost jedne ili više podniza u danoj Niz u danom redoslijedu:

@Test javna praznina givenString_whenContainsGivenSubstring_thenCorrect () {String str = "kaligrafija"; assertThat (str, stringContainsInOrder (Arrays.asList ("call", "graph"))); }

Napokon, možemo provjeriti jednakost dvoje Nizs bez obzira na slučaj:

@Test javna praznina given2Strings_whenEqual_thenCorrect () {String a = "foo"; Niz b = "FOO"; assertThat (a, jednakToIgnoringCase (b)); }

9. Core API

The Hamcrest temeljni API trebaju koristiti nezavisni dobavljači okvira. Međutim, nudi nam neke izvrsne konstrukcije kako bi naši jedinični testovi bili čitljiviji, a također i neke osnovne podudarnosti koje se mogu koristiti jednako lako.

Čitljivost s je konstruirati na podudarniku:

@Test javna praznina given2Strings_whenIsEqualRegardlessWhiteSpace_thenCorrect () {String str1 = "text"; Niz str2 = "tekst"; assertThat (str1, je (jednakToIgnoringWhiteSpace (str2))); }

The je konstruirati na jednostavnom tipu podataka:

@Test javna praznina given2Strings_whenIsEqual_thenCorrect () {String str1 = "text"; Niz str2 = "tekst"; assertThat (str1, je (str2)); }

Negacija s ne konstruirati na podudarniku:

@Test javna praznina given2Strings_whenIsNotEqualRegardlessWhiteSpace_thenCorrect () {String str1 = "text"; Niz str2 = "tekstovi"; assertThat (str1, ne (jednakToIgnoringWhiteSpace (str2))); }

The ne konstruirati na jednostavnom tipu podataka:

@Test javna praznina given2Strings_whenNotEqual_thenCorrect () {String str1 = "text"; Niz str2 = "tekstovi"; assertThat (str1, ne (str2)); }

Provjerite je li Niz sadrži zadani podniz:

@Test javna praznina danaAStrings_whenContainsAnotherGivenString_thenCorrect () {String str1 = "kaligrafija"; Niz str2 = "poziv"; assertThat (str1, containsString (str2)); }

Provjerite je li Niz započinje zadanim podnizom:

@Test javna praznina danaAString_whenStartsWithA AnotherGivenString_thenCorrect () {String str1 = "kaligrafija"; Niz str2 = "poziv"; assertThat (str1, startWith (str2)); }

Provjerite je li Niz završava zadanim podnizom:

@Test javna praznina givenAString_whenEndsWithAnotherGivenString_thenCorrect () {String str1 = "kaligrafija"; Niz str2 = "phy"; assertThat (str1, završavaWith (str2)); }

Provjerite jesu li dvije Objektsu iste instance:

@Test javna praznina given2Objects_whenSameInstance_thenCorrect () {Cat cat = new Cat (); assertThat (cat, sameInstance (cat)); }

Provjerite je li Objekt je instanca zadane klase:

@Test javna praznina givenAnObject_whenInstanceOfGivenClass_thenCorrect () {Mačka mačke = nova Mačka (); assertThat (cat, instanceOf (Cat.class)); }

Provjerite jesu li svi članovi a Kolekcija ispuniti uvjet:

@Test javna praznina givenList_whenEachElementGreaterThan0_thenCorrect () {Popis popisa = Arrays.asList (1, 2, 3); int baseCase = 0; assertThat (list, everyItem (većeTan (baseCase))); }

Provjerite je li Niz nije null:

@Test javna praznina givenString_whenNotNull_thenCorrect () {String str = "notnull"; assertThat (str, notNullValue ()); }

Lančani uvjeti zajedno, test prolazi kada cilj ispunjava bilo koji od uvjeta, sličnih logičnom ILI:

@Test javna praznina givenString_whenMeetsAnyOfGivenConditions_thenCorrect () {String str = "kaligrafija"; String start = "call"; Kraj niza = "foo"; assertThat (str, anyOf (startWith (start), containsString (end))); }

Lančani uvjeti zajedno, test prolazi samo kada cilj ispunjava sve uvjete, slično logičnom I:

@Test javna praznina givenString_whenMeetsAllOfGivenConditions_thenCorrect () {String str = "kaligrafija"; String start = "call"; Kraj niza = "phy"; assertThat (str, allOf (startWith (početak), završavaWith (kraj))); }

10. Prilagođeno podudaranje

Proširenjem možemo definirati vlastiti podudarnik TypeSafeMatcher. U ovom ćemo odjeljku stvoriti prilagođeno podudaranje koje omogućava prolazak testa samo kada je cilj pozitivan cijeli broj.

javna klasa IsPositiveInteger proširuje TypeSafeMatcher {javna void descriTo (Opis opisa) {description.appendText ("pozitivan cijeli broj"); } @Factory public static Matcher isAPositiveInteger () {return new IsPositiveInteger (); } @Override zaštićeni logički matchSafely (Integer integer) {return integer> 0; }}

Trebamo samo implementirati matchSafely metoda koja provjerava je li cilj zaista pozitivan cijeli broj i opišiTo metoda koja daje poruku o neuspjehu u slučaju da test ne prođe.

Evo testa koji koristi naše novo prilagođeno podudaranje:

@Test javna praznina givenInteger_whenAPositiveValue_thenCorrect () {int num = 1; assertThat (num, isAPositiveInteger ()); }

i evo poruke o neuspjehu koju dobivamo jer smo proslijedili u pozitivni cijeli broj:

java.lang.AssertionError: Očekivano: pozitivan cijeli broj, ali: was 

11. Zaključak

U ovom uputstvu imamo istraživao Hamcrest API i naučio kako s njim možemo pisati bolje i održivije cjeline.

Potpuna implementacija svih ovih primjera i isječaka koda mogu se naći u mom Hamcrest github projektu.