Skrivespesifikasjoner med Kotlin og Spek

1. Introduksjon

Spesifikasjon Testing rammer er komplementære til Unit Testing rammer for testing av våre applikasjoner.

I denne opplæringen introduserer vi Spek-rammeverket - et spesifikasjonstestingsrammeverk for Java og Kotlin.

2. Hva er spesifikasjonstesting?

Enkelt sagt, i spesifikasjonstesting, begynner vi med spesifikasjonen og beskriver intensjonen med programvaren, i stedet for dens mekanikk.

Dette brukes ofte i Behavior Driven Development siden hensikten er å validere et system mot forhåndsdefinerte spesifikasjoner for applikasjonen vår.

Vanlige kjente spesifikasjonstesterammer inkluderer Spock, Agurk, Jasmin og RSpec.

2.1. Hva er Spek?

Spek er et Kotlin-basert Specification Testing framework for JVM. Den er designet for å fungere som en JUnit 5-testmotor. Dette betyr at vi enkelt kan koble den til ethvert prosjekt som allerede bruker JUnit 5 til å kjøre sammen med andre tester vi måtte ha.

Det er også mulig å kjøre testene ved hjelp av det eldre JUnit 4-rammeverket, ved å bruke JUnit Platform Runner-avhengighet om nødvendig.

2.2. Maven avhengigheter

For å bruke Spek, må vi legge til de nødvendige avhengighetene til Maven-bygningen vår:

 org.jetbrains.spek spek-api 1.1.5 test org.jetbrains.spek spek-junit-platform-engine 1.1.5 test 

De spek-api avhengighet er den faktiske APIen som brukes til testrammeverket. Den definerer alt som testene våre vil jobbe med. De spek-junit-plattform-motor avhengighet er da JUnit 5 Test Engine som er nødvendig for å utføre testene våre.

Merk at alle Spek-avhengighetene må være den samme versjonen som hverandre. Den siste versjonen finner du her.

2.3. Første test

Når Spek er satt opp, er skrivetester et enkelt tilfelle av å skrive riktig klasse i riktig struktur. Dette er litt uvanlig for å gjøre det mer lesbart.

Spek krever at testene våre alle arver fra en passende superklasse - vanligvis Spek - og at vi implementerer testene våre ved å sende en blokk til konstruktøren i denne klassen:

klasse FirstSpec: Spek ({// Implementer testen her})

3. Test stiler

Spesifikasjonstesting legger vekt på å skrive tester på en måte som er så lesbar som mulig. Agurk skriver for eksempel hele testen på et leselig språk og knytter den deretter til trinn slik at koden holdes separat.

Spek fungerer ved å bruke spesielle metoder som fungerer som lesbare strengerhvor hver får en blokk å utføre etter behov. Det er noen variasjoner på hvilke funksjoner vi bruker, avhengig av måten vi vil at testene skal lese.

3.1. gitt//den

En måte vi kan skrive testene våre er i “gitt / på / det” -stilen.

Dette bruker metoder som kalles gitt, og den, nestet i den strukturen, for å skrive testene våre:

  • gitt - setter opp startbetingelsene for testen
  • - utfør testhandlingen
  • den - hevde at testhandlingen ble utført riktig

Vi kan ha så mange av hver blokk som vi trenger, men må hekke dem i denne rekkefølgen:

class CalculatorTest: Spek ({given ("A calculator") {val calculator = Calculator () on ("Adding 3 and 5") {val result = calculator.add (3, 5) it ("Produces 8") {assertEquals (8, resultat)}}}})

Denne testen leser veldig enkelt. Når vi fokuserer på teststrinnene, kan vi lese det som "Gitt en kalkulator, når vi legger til 3 og 5 gir det 8".

3.2. beskrive/den

Den andre måten vi kan skrive testene våre er i "beskriv / det" -stilen. I stedet bruker dette metoden beskrive for alle hekkene, og fortsetter å bruke den for våre påstander.

I dette tilfellet kan vi hekke beskrive metoder så mye som vi trenger for å skrive testene våre:

klasse KalkulatorTest: Spek ({beskriver ("En kalkulator") {val kalkulator = Kalkulator () beskriver ("Tillegg") {val resultat = kalkulator. legger til (3, 5) det ("Produserer riktig svar") {assertEquals ( 8, resultat)}}}})

Det er mindre struktur håndhevet på testene ved hjelp av denne stilen, noe som betyr at vi har mye mer fleksibilitet i hvordan vi skriver testene.

Dessverre er ulempen med at testene ikke leser så naturlig som når vi bruker "gitt / på / det".

3.3. Ekstra stiler

Spek håndhever ikke disse stilene, og det vil tillate at søkeordene byttes så mye som ønsket. De eneste kravene er at alle påstander finnes i et den og at ingen andre blokker finnes på det nivået.

Hele listen over hekkende nøkkelord som er tilgjengelige er:

  • gitt
  • beskrive
  • kontekst

Vi kan bruke disse til å gi testene våre den best mulige strukturen for hvordan vi vil skrive dem.

3.4. Datadrevne tester

Mekanismen som brukes til å definere tester er ikke annet enn enkle funksjonssamtaler. Dette betyr at vi kan gjøre andre ting med dem, som enhver vanlig kode. Spesielt kan vi ringe dem på en datadrevet måte hvis vi ønsker det.

Den enkleste måten å gjøre dette på er å sløyfe over dataene vi vil bruke, og ringe den aktuelle blokken fra innsiden av denne sløyfen:

klasse DataDrivenTest: Spek ({beskriv ("En datadrevet test") {mapOf ("hei" til "HELLO", "verden" til "VERDEN"). for hver {input, forventet -> beskriv ("kapitalisering av $ input") {it ("Returnerer riktig $ forventet") {assertEquals (forventet, input.toUpperCase ())}}}})

Vi kan gjøre alle slags ting som dette hvis vi trenger det, men dette er sannsynligvis det mest nyttige.

4. Påstander

Spek foreskriver ikke noen spesiell måte å bruke påstander på. I stedet, det tillater oss å bruke det påstanden vi er mest komfortable med.

Det åpenbare valget vil være org.junit.jupiter.api.Assertions klasse, siden vi allerede bruker JUnit 5-rammeverket som vår testløper.

Vi kan imidlertid også bruke hvilket som helst annet påstandsbibliotek vi vil ha hvis det gjør testene våre bedre - for eksempel Kluent, Expekt eller HamKrest.

Fordelen med å bruke disse bibliotekene i stedet for standard JUnit 5 Påstander klassen er ned til testens lesbarhet.

For eksempel lyder testen ovenfor omskrevet med Kluent som:

klasse KalkulatorTest: Spek ({beskriver ("En kalkulator") {val kalkulator = Kalkulator () beskriver ("Tillegg") {val resultat = kalkulator. legger til (3, 5) det ("Produserer riktig svar") {resultat skalEkval 8}}}})

5. Før / etter håndtere

Som med de fleste testrammer, Spek kan også utføre logikk før / etter tester.

Dette er, akkurat som navnet tilsier, blokker som utføres før eller etter selve testen.

Alternativene her er:

  • førGruppe
  • ettergruppe
  • beforeEachTest
  • etterEachTest

Disse kan plasseres i hvilket som helst av de nestende nøkkelordene, og vil gjelde for alt i gruppen.

Slik Spek fungerer, blir all kode i et av de nestende nøkkelordene utført umiddelbart ved starten av testen, men kontrollblokkene blir utført i en bestemt rekkefølge sentrert rundt den blokker.

Arbeider utenfra, Spek vil utføre hver beforeEachTest blokker umiddelbart før hver den blokk nestet i samme gruppe, og hver etterEachTest blokker umiddelbart etter hver den blokkere. På samme måte vil Spek utføre hver førGruppe blokker umiddelbart før hver gruppe og hver ettergruppe blokker umiddelbart etter hver gruppe i gjeldende hekking.

Dette er komplisert, og forklares best med et eksempel:

klasse GroupTest5: Spek ({beskriv ("Ytre gruppe") {beforeEachTest {System.out.println ("BeforeEachTest 0")} beforeGroup {System.out.println ("BeforeGroup 0")} etterEachTest {System.out.println ( "AfterEachTest 0")} afterGroup {System.out.println ("AfterGroup 0")} beskriver ("Inner group 1") {beforeEachTest {System.out.println ("BeforeEachTest 1")} beforeGroup {System.out.println ("BeforeGroup 1")} afterEachTest {System.out.println ("AfterEachTest 1")} afterGroup {System.out.println ("AfterGroup 1")} it ("Test 1") {System.out.println (" Test 1 ")}}}})

Resultatet av å kjøre ovennevnte er:

BeforeGroup 0 BeforeGroup 1 BeforeEachTest 0 BeforeEachTest 1 Test 1 AfterEachTest 1 AfterEachTest 0 AfterGroup 1 AfterGroup 0

Straks kan vi se at det ytre beforeGroup / afterGroup blokker er rundt hele settet med tester, mens de indre beforeGroup / afterGroup blokker er bare rundt testene i samme sammenheng.

Vi kan også se at alle førGruppe blokker utføres før noen beforeEachTest blokker og det motsatte for afterGroup / afterEachTest.

Et større eksempel på dette, som viser samspillet mellom flere tester i flere grupper, kan sees på GitHub.

6. Testemner

Mange ganger vil vi skrive en enkelt spesifikasjon for et enkelt testemne. Spek tilbyr en praktisk måte å skrive dette på, slik at det administrerer emnet under test for oss automatisk. Vi bruker SubjectSpek baseklasse i stedet for Spek klasse for dette.

Når vi bruker dette, må vi kunngjøre et kall til Emne blokker på det ytterste nivået. Dette definerer testpersonen. Vi kan da henvise til dette fra hvilken som helst av testkodene våre som Emne.

Vi kan bruke dette til å omskrive vår tidligere kalkulator-test som følger:

klasse KalkulatorTest: SubjectSpek ({emne {Kalkulator ()} beskriver ("En kalkulator") {beskriver ("Tillegg") {val resultat = emne. legger til (3, 5) det ("Produserer riktig svar") {assertEquals ( 8, resultat)}}}})

Det virker ikke så mye, men dette kan bidra til å gjøre testene mye mer lesbare, spesielt når det er et stort antall testsaker å vurdere.

6.1. Maven avhengigheter

For å bruke emneutvidelsen, må vi legge til en avhengighet til Maven-bygningen:

 org.jetbrains.spek spek-subject-extension 1.1.5 test 

7. Oppsummering

Spek er et kraftig rammeverk som tillater noen veldig lesbare tester, som igjen betyr at alle deler av organisasjonen kan lese dem.

Dette er viktig for å la alle kolleger bidra til å teste hele applikasjonen.

Endelig kan kodebiter, som alltid, bli funnet på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found