Testiranje REST API-ja s JBehaveom
1. Uvod
U ovom ćemo članku na brzinu pogledati JBehave, a zatim se usredotočiti na testiranje REST API-ja iz perspektive BDD-a.
2. JBehave i BDD
JBehave je razvojni okvir vođen ponašanjem. Namjerava pružiti intuitivan i dostupan način za automatizirano testiranje prihvaćanja.
Ako niste upoznati s BDD-om, bilo bi dobro započeti s ovim člankom koji govori o drugom okviru za testiranje BDD-a - Krastavcu, u kojem uvodimo opću strukturu i značajke BDD-a.
Slično ostalim BDD okvirima, JBehave usvaja sljedeće koncepte:
- Priča - predstavlja automatski izvršni priraštaj poslovne funkcionalnosti, sadrži jedan ili više scenarija
- Scenariji - predstavljaju konkretne primjere ponašanja sustava
- Koraci - predstavite stvarno ponašanje pomoću klasičnih BDD ključnih riječi: S obzirom, Kada i Zatim
Tipičan scenarij bio bi:
Daje se preduvjet Kada se dogodi događaj, onda treba uhvatiti ishod
Svaki korak u scenariju odgovara napomeni u JBehaveu:
- @ Daj: pokretanje konteksta
- @Kada: radite akciju
- @Zatim: testirajte očekivani ishod
3. Ovisnost Mavena
Da bismo iskoristili JBehave u našem projektu maven, ovisnost o jbehave-core trebala bi biti uključena u pom:
org.jbehave jbehave-core 4.1 test
4. Brzi primjer
Da bismo koristili JBehave, moramo slijediti sljedeće korake:
- Napišite korisničku priču
- Mapirajte korake od korisničke priče na Java kôd
- Konfigurirajte korisničke priče
- Pokrenite JBehave testove
- Pregledajte rezultate
4.1. Priča
Počnimo sa sljedećom jednostavnom pričom: „kao korisnik želim povećati brojač kako bih mogao povećati vrijednost brojača za 1“.
Priču možemo definirati u a .priča datoteka:
Scenarij: kada korisnik poveća brojač, njegova vrijednost se povećava za 1 Daje se brojač I brojač ima bilo kakvu integralnu vrijednost Kada korisnik povećava brojač Tada vrijednost brojača mora biti 1 veća od prethodne vrijednosti
4.2. Koraci mapiranja
S obzirom na korake, primijenimo ovo na Javi:
javna klasa Povećaj korake {private int counter; private int previousValue; @Given ("brojač") javna praznina aCounter () {} @Given ("brojač ima bilo kakvu integralnu vrijednost") public void counterHasAnyIntegralValue () {counter = new Random (). NextInt (); previousValue = brojač; } @When ("korisnik povećava brojač") javna praznina povećavaTheCounter () {counter ++; } @Then ("vrijednost brojača mora biti 1 veća od prethodne vrijednosti") public void theValueOfTheCounterMustBe1Greater () {assertTrue (1 == counter - previousValue); }}
Zapamti to vrijednost u bilješkama mora se točno podudarati s opisom.
4.3. Konfiguriranje naše priče
Da bismo izveli korake, moramo postaviti pozornicu za našu priču:
javna klasa PovećajStoriLiveTest proširuje JUnitStories {@Override javnu konfiguraciju konfiguracije () {vrati novu MostUsefulConfiguration () .useStoryLoader (nova LoadFromClasspath (this.getClass ())) .useStoryReporterBuilder (nova StoryReporterBuildero (C). ) .withFormats (CONSOLE)); } @Override public InjectableStepsFactory stepsFactory () {return new InstanceStepsFactory (configuration (), new Povećaj korake ()); } @Override zaštićeni Popis storyPaths () {return Arrays.asList ("povećati.priču"); }}
U storyPaths (), pružamo svoje .priča put datoteke koji će JBehave raščlaniti. Provedba stvarnih koraka osigurana je u stepsFactory (). Zatim u konfiguracija(), učitavač priča i izvještaj o priči pravilno su konfigurirani.
Sad kad smo sve spremni, svoju priču možemo započeti jednostavnim trčanjem: mvn čisti test.
4.4. Pregled rezultata testa
Rezultat testa možemo vidjeti u konzoli. Kako su naši testovi uspješno prošli, rezultat bi bio isti s našom pričom:
Scenarij: kada korisnik poveća brojač, njegova vrijednost se povećava za 1 Daje se brojač I brojač ima bilo kakvu integralnu vrijednost Kada korisnik povećava brojač Tada vrijednost brojača mora biti 1 veća od prethodne vrijednosti
Ako zaboravimo provesti bilo koji korak scenarija, izvješće će nas obavijestiti. Recimo da nismo implementirali @Kada korak:
Scenarij: kada korisnik poveća brojač, njegova vrijednost se povećava za 1 Daje se brojač I brojač ima bilo kakvu integralnu vrijednost Kada korisnik povećava brojač (NA PROCEDBI) Tada vrijednost brojača mora biti 1 veća od prethodne vrijednosti (NIJE IZVEDENO )
@When ("korisnik povećava brojač") @Pending public void whenTheUserIncreasesTheCounter () {// NA PROCEDBI}
Izvještaj bi rekao @Kada korak je na čekanju i zbog toga @Zatim korak se ne bi izvodio.
Što ako naš @Then korak zakaže? Pogrešku možemo uočiti odmah iz izvješća:
Scenarij: kada korisnik poveća brojač, njegova vrijednost se povećava za 1 Daje se brojač I brojač ima bilo kakvu integralnu vrijednost Kada korisnik povećava brojač Tada vrijednost brojača mora biti 1 veća od prethodne vrijednosti (FAILED) (java. lang.AssertionError)
5. Testiranje REST API-ja
Sada smo shvatili osnove JBhave; vidjet ćemo kako s njim testirati REST API. Naši testovi temeljit će se na našem prethodnom članku koji govori o tome kako testirati REST API s Javom.
U tom smo članku testirali GitHub REST API i uglavnom se usredotočili na HTTP odgovor, zaglavlja i korisni teret. Radi jednostavnosti možemo ih zapisati u tri zasebne priče.
5.1. Testiranje statusnog koda
Priča:
Scenarij: kada korisnik provjeri nepostojećeg korisnika na githubu, github će odgovoriti 'not found' S obzirom na github korisnički profil api I nasumično nepostojeće korisničko ime Kada tražim slučajnog korisnika putem api-a Tada github odgovara: 404 not found Kada tražim eugenp1 putem api-a Tada github odgovara: 404 nije pronađen Kada tražim eugenp2 preko api-a Tada github odgovara: 404 nije pronađen
Koraci:
javna klasa GithubUserNotFoundSteps {private String api; private String nonExistentUser; privatni int githubResponseCode; @Given ("github korisnički profil api") javna praznina givenGithubUserProfileApi () {api = "//api.github.com/users/%s"; } @Given ("slučajno nepostojeće korisničko ime") javna praznina givenANonexistentUsername () {nonExistentUser = randomAlphabetic (8); } @When ("Tražim slučajnog korisnika putem api-a") javna praznina kadaILookForTheUserViaTheApi () baca IOException {githubResponseCode = getGithubUserProfile (api, nonExistentUser) .getStatusLine () .getStatusCode (); } @When ("Tražim $ korisnika putem api-a") javna void kadaILookForSomeNonExistentUserViaTheApi (Korisnik niza) baci IOException {githubResponseCode = getGithubUserProfile (api, korisnik) .getStatusLine () .getStatusCode (); } @Then ("github response: 404 not found") javna praznina thenGithubRespond404NotFound () {assertTrue (SC_NOT_FOUND == githubResponseCode); } // ...}
Primijetite kako, u provedbi koraka, koristili smo značajku ubrizgavanja parametara. Argumenti izvučeni iz koračnog kandidata upravo se podudaraju slijedeći prirodni redoslijed parametara u anotiranom Java načinu.
Također su podržani anotirani imenovani parametri:
@ Kada ("Tražim $ korisničko ime putem api-a") javna void kadaILookForSomeNonExistentUserViaTheApi (@Named ("username") String user) baca IOException
5.2. Testiranje vrste medija
Evo jednostavne priče o testiranju MIME tipa:
Scenarij: kada korisnik provjeri valjani korisnički profil na githubu, github će odgovoriti na json podatke S obzirom na github korisnički profil api I važeće korisničko ime Kada potražim korisnika putem api-a Tada github odgovara podacima tipa json
I evo koraka:
javna klasa GithubUserResponseMediaTypeSteps {privatni niz api; privatni niz validUser; private String mediaType; @Given ("github korisnički profil api") javna praznina givenGithubUserProfileApi () {api = "//api.github.com/users/%s"; } @Given ("važeće korisničko ime") javna praznina danaAValidUsername () {validUser = "eugenp"; } @When ("Tražim korisnika putem api-a") javna praznina kadaILookForTheUserViaTheApi () baca IOException {mediaType = ContentType .getOrDefault (getGithubUserProfile (api, validUser) .getEntity ()) .getMimeType (); } @Then ("github odgovaraju podaci tipa json") javna void thenGithubRespondDataOfTypeJson () {assertEquals ("application / json", mediaType); }}
5.3. Testiranje korisnog tereta JSON-a
Zatim zadnja priča:
Scenarij: kada korisnik provjeri valjani korisnički profil na github-u, github-ov odgovor json trebao bi sadržavati korisničku težinu za prijavu s istim korisničkim imenom. Dati github-ov korisnički profil api Kada tražim eugenp preko api-a. Tada github-ov odgovor sadrži korisni teret za prijavu isti kao eugenp
I jednostavna ravna izvedba:
javna klasa GithubUserResponsePayloadSteps {privatni niz api; privatni resurs GitHubUser; @Given ("github korisnički profil api") javna praznina givenGithubUserProfileApi () {api = "//api.github.com/users/%s"; } @When ("Tražim $ korisnika putem api-a") javna praznina kadaILookForEugenpViaTheApi (korisnik niza) baci IOException {HttpResponse httpResponse = getGithubUserProfile (api, korisnik); resource = RetrieveUtil.retrieveResourceFromResponse (httpResponse, GitHubUser.class); } @Then ("github-ov odgovor sadrži 'login' korisni teret isti kao i $ username") public void thenGithubsResponseContainsAloginPayloadSameAsEugenp (String username) {assertThat (username, Matchers.is (resource.getLogin ())); }}
6. Sažetak
U ovom smo članku ukratko predstavili JBehave i implementirali REST API testove u BDD stilu.
U usporedbi s našim običnim Java test kodom, kod implementiran s JBehaveom izgleda mnogo jasniji i intuitivniji, a izvještaj o rezultatu testa izgleda mnogo elegantnije.
Kao i uvijek, primjer koda može se naći u projektu Github.