Skrivespecifikationer med Kotlin og Spek

1. Introduktion

Specifikation Testrammer er komplementære til Enhedstestrammer til test af vores applikationer.

I denne vejledning introducerer vi Spek-rammen - en Specification Testing-ramme til Java og Kotlin.

2. Hvad er specifikationstestning?

Kort sagt, i Specification Testing starter vi med specifikationen og beskriver intentionen med softwaren i stedet for dens mekanik.

Dette bruges ofte i Behavior Driven Development, da hensigten er at validere et system mod foruddefinerede specifikationer for vores applikation.

Almindeligt kendte Specifikationstestrammer inkluderer Spock, Agurk, Jasmin og RSpec.

2.1. Hvad er Spek?

Spek er en Kotlin-baseret Specification Testing framework til JVM. Det er designet til at fungere som en JUnit 5-testmotor. Dette betyder, at vi let kan tilslutte det til ethvert projekt, der allerede bruger JUnit 5 til at køre sammen med andre test, vi måtte have.

Det er også muligt at køre testene ved hjælp af den ældre JUnit 4-ramme ved hjælp af JUnit Platform Runner-afhængighed, hvis det er nødvendigt.

2.2. Maven afhængigheder

For at bruge Spek skal vi tilføje de krævede afhængigheder til vores Maven-build:

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

Det spek-api afhængighed er den faktiske API, der bruges til testrammen. Det definerer alt, hvad vores tests vil arbejde med. Det spek-junit-platform-motor afhængighed er derefter JUnit 5 Test Engine, der er nødvendig for at udføre vores tests.

Bemærk, at alle Spek-afhængigheder skal være den samme version som hinanden. Den seneste version kan findes her.

2.3. Første test

Når Spek er oprettet, er skrivetest et simpelt tilfælde af at skrive den rigtige klasse i den korrekte struktur. Dette er lidt usædvanligt for at gøre det mere læsbart.

Spek kræver, at vores tests alle arver fra en passende superklasse - typisk Spek - og at vi implementerer vores tests ved at sende en blok til konstruktøren i denne klasse:

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

3. Test stilarter

Specifikationstest lægger vægt på at skrive test på en så læsbar måde som muligt. Agurk skriver for eksempel hele testen på et menneskeligt læsbart sprog og binder den derefter til trin, så koden holdes adskilt.

Spek fungerer ved hjælp af specielle metoder, der fungerer som læsbare strengehvor hver får en blok til at udføre efter behov. Der er nogle variationer på, hvilke funktioner vi bruger, afhængigt af den måde, vi ønsker, at testene skal læses.

3.1. givet//det

En måde, hvorpå vi kan skrive vores tests, er i "given / on / it" -stil.

Dette bruger metoder kaldet givet, og det, indlejret i den struktur, for at skrive vores tests:

  • givet - opsætter de indledende betingelser for testen
  • - udfør testhandlingen
  • det - hævde, at testhandlingen blev udført korrekt

Vi kan have så mange af hver blok, som vi har brug for, men vi skal rede dem i denne rækkefølge:

klasse 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 test læser meget let. Når vi fokuserer på testtrinnene, kan vi læse det som "Givet en lommeregner, ved at tilføje 3 og 5 giver det 8".

3.2. beskrive/det

Den anden måde, hvorpå vi kan skrive vores tests, er i "beskriv / det" -stil. I stedet bruger dette metoden beskrive til alle de indlejrede, og fortsætter med at bruge det for vores påstande.

I dette tilfælde kan vi rede beskrive metoder så meget som vi har brug for til at skrive vores tests:

klasse CalculatorTest: Spek ({beskriv ("A calculator") {val calculator = Calculator () beskriv ("Addition") {val result = calculator.add (3, 5) it ("Producerer det rigtige svar") {assertEquals ( 8, resultat)}}}})

Der er mindre struktur håndhævet på testene ved hjælp af denne stil, hvilket betyder, at vi har meget mere fleksibilitet i, hvordan vi skriver testene.

Desværre er ulempen ved dette, at testene ikke læser så naturligt som når vi bruger "given / on / it".

3.3. Yderligere stilarter

Spek håndhæver ikke disse stilarter, og det giver mulighed for, at nøgleordene udveksles så meget som ønsket. De eneste krav er, at alle påstande findes inde i en det og at der ikke findes andre blokke på det niveau.

Den fulde liste over tilgængelige nøgleord er:

  • givet
  • beskrive
  • sammenhæng

Vi kan bruge disse til at give vores tests den bedst mulige struktur for, hvordan vi vil skrive dem.

3.4. Datadrevne tests

Mekanismen, der bruges til at definere tests, er alt andet end enkle funktionsopkald. Dette betyder, at vi kan gøre andre ting med dem, som enhver normal kode. Især kan vi kalde dem på en datadrevet måde, hvis vi ønsker det.

Den nemmeste måde at gøre dette på er at sløjfe over de data, vi vil bruge, og kalde den relevante blok inde fra denne sløjfe:

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

Vi kan gøre alle mulige ting som dette, hvis vi har brug for det, men det er sandsynligvis det mest nyttige.

4. Påstande

Spek foreskriver ikke nogen særlig måde at bruge påstande på. I stedet, det giver os mulighed for at bruge de påstande, vi er mest fortrolige med.

Det oplagte valg vil være org.junit.jupiter.api.Assertions klasse, da vi allerede bruger JUnit 5-rammen som vores testløber.

Vi kan dog også bruge ethvert andet påstandsbibliotek, som vi ønsker, hvis det gør vores tests bedre - f.eks. Kluent, Expekt eller HamKrest.

Fordelen ved at bruge disse biblioteker i stedet for standard JUnit 5 Påstande klasse er ned til testens læsbarhed.

For eksempel læser ovenstående test, der er skrevet om igen ved hjælp af Kluent, som:

klasse CalculatorTest: Spek ({beskriv ("A calculator") {val calculator = Calculator () beskriv ("Addition") {val result = calculator.add (3, 5) it ("Producerer det rigtige svar") {result shouldEqual 8}}}})

5. Før / efter håndtering

Som med de fleste testrammer, Spek kan også udføre logik før / efter test.

Disse er, præcis som deres navn antyder, blokke, der udføres før eller efter selve testen.

Mulighederne her er:

  • før Gruppe
  • eftergruppe
  • beforeEachTest
  • efterEachTest

Disse kan placeres i et hvilket som helst af de indlejrede nøgleord og gælder for alt inden for denne gruppe.

Den måde, Spek fungerer på, udføres al kode i et af de indlejrede nøgleord straks ved testens start, men kontrolblokkene udføres i en bestemt rækkefølge centreret omkring det blokke.

Arbejder udefra og ud, Spek udfører hver beforeEachTest blokere umiddelbart før hver det blok indlejret i den samme gruppe og hver efterEachTest blokere straks efter hver det blok. Ligeledes udfører Spek hver før Gruppe blokere umiddelbart før hver gruppe og hver eftergruppe blokere straks efter hver gruppe i den nuværende indlejring.

Dette er kompliceret og forklares bedst med et eksempel:

klasse GroupTest5: Spek ({beskriv ("Ydre gruppe") {beforeEachTest {System.out.println ("BeforeEachTest 0")} beforeGroup {System.out.println ("BeforeGroup 0")} efterEachTest {System.out.println ( "AfterEachTest 0")} afterGroup {System.out.println ("AfterGroup 0")} beskriver ("Indre gruppe 1") {beforeEachTest {System.out.println ("BeforeEachTest 1")} før Group {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 af at køre ovenstående 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 ydre beforeGroup / afterGroup blokke er omkring hele testen, mens den indvendige beforeGroup / afterGroup blokke er kun omkring testene i samme sammenhæng.

Vi kan også se, at alle de før Gruppe blokke udføres før nogen beforeEachTest blokke og det modsatte for afterGroup / afterEachTest.

Et større eksempel på dette, der viser interaktionen mellem flere tests i flere grupper, kan ses på GitHub.

6. Test emner

Mange gange vil vi skrive en enkelt Spec for et enkelt testemne. Spek tilbyder en bekvem måde at skrive dette på, således at det automatisk administrerer emnet under test for os. Vi bruger SubjectSpek base klasse i stedet for Spek klasse for dette.

Når vi bruger dette, er vi nødt til at erklære et opkald til emne blokere på det yderste niveau. Dette definerer testpersonen. Vi kan derefter henvise til dette fra enhver af vores testkoder som emne.

Vi kan bruge dette til at omskrive vores tidligere regnemaskine test som følger:

klasse CalculatorTest: SubjectSpek ({subject {Calculator ()} beskriv ("A calculator") {beskriv ("Addition") {val result = subject.add (3, 5) it ("Producerer det rigtige svar") {assertEquals ( 8, resultat)}}}})

Det ser måske ikke ud til meget, men det kan hjælpe med at gøre testene meget mere læsbare, især når der er et stort antal testsager at overveje.

6.1. Maven afhængigheder

For at bruge emneudvidelsen skal vi tilføje en afhængighed af vores Maven-build:

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

7. Resume

Spek er en stærk ramme, der giver mulighed for nogle meget læsbare tests, hvilket igen betyder, at alle dele af organisationen kan læse dem.

Dette er vigtigt for at give alle kolleger mulighed for at bidrage til at teste hele applikationen.

Endelig kan kodestykker, som altid, findes på GitHub.


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