Pisanje specifikacija s Kotlinom i Spekom

1. Uvod

Specifikacije Okviri za testiranje komplementarni su okvirima za jedinstveno testiranje za testiranje naših aplikacija.

U ovom uputstvu predstavit ćemo okvir Spek - okvir za testiranje specifikacija za Javu i Kotlin.

2. Što je ispitivanje specifikacija?

Jednostavno rečeno, u Ispitivanju specifikacija počinjemo sa specifikacijom i opisujemo namjeru softvera, umjesto njegove mehanike.

To se često koristi u razvoju usmjerenom na ponašanje jer je namjera provjeriti valjanost sustava prema unaprijed definiranim specifikacijama naše aplikacije.

Uobičajeni okviri za ispitivanje specifikacija uključuju Spock, Krastavac, Jasmin i RSpec.

2.1. Što je Spek?

Spek je okvir za ispitivanje specifikacija zasnovan na Kotlinu za JVM. Dizajniran je za rad kao JUnit 5 Test Engine. To znači da ga možemo lako uključiti u bilo koji projekt koji već koristi JUnit 5 za pokretanje zajedno s bilo kojim drugim testovima koje bismo mogli imati.

Također je moguće pokrenuti testove pomoću starijeg okvira JUnit 4, koristeći ovisnost JUnit Platform Runner, ako je potrebno.

2.2. Ovisnosti Mavena

Da bismo koristili Spek, trebamo dodati potrebne ovisnosti u našu Maven izgradnju:

 test org.jetbrains.spek spek-api 1.1.5 test org.jetbrains.spek spek-junit-platforma-motor 1.1.5 test 

The spek-api ovisnost je stvarni API koji se koristi za okvir testiranja. Definira sve s čime će naši testovi raditi. The spek-junit-platforma-motor ovisnost je tada JUnit 5 Test Engine potreban za izvršavanje naših testova.

Imajte na umu da sve ovisnosti o Speku moraju biti iste verzije kao jedna druge. Najnoviju verziju možete pronaći ovdje.

2.3. Prvo ispitivanje

Jednom kada je Spek postavljen, pisanje testova jednostavan je slučaj pisanja ispravne klase u ispravnu strukturu. Ovo je pomalo neobično kako bi bilo čitljivije.

Spek zahtijeva da svi naši testovi naslijede iz odgovarajuće superklase - obično Spek - i da implementiramo svoje testove prosljeđivanjem bloka konstruktoru ove klase:

klasa FirstSpec: Spek ({// implementiraj test ovdje})

3. Testirajte stilove

Ispitivanje specifikacija naglašava pisanje testova na što čitljiviji način. Krastavac, na primjer, čitav test piše razumljivim jezikom, a zatim ga veže uz korake kako bi se kod držao odvojeno.

Spek djeluje pomoću posebnih metoda koje djeluju kao čitljivi nizovi, od kojih je svaki dobio blok za izvršenje prema potrebi. Postoje neke varijacije funkcija koje koristimo, ovisno o načinu na koji želimo da testovi čitaju.

3.1. dato/na/to

Jedan od načina na koji možemo pisati svoje testove je u stilu "dao / uključio / la".

Tu se koriste metode tzv dato, na i to, ugniježđeni u toj strukturi, da napišemo naše testove:

  • dato - postavlja početne uvjete za test
  • na - izvršiti test radnju
  • to - ustvrditi da je ispitna radnja izvedena ispravno

Od svakog bloka možemo imati onoliko koliko nam treba, ali moramo ih ugnijezditi ovim redoslijedom:

class CalculatorTest: Spek ({dao ("Kalkulator") {val kalkulator = Kalkulator () uključen ("Dodavanje 3 i 5") {val rezultat = kalkulator.add (3, 5) it ("Proizvodi 8") {assertEquals (8, rezultat)}}}})

Ovaj se test vrlo lako čita. Fokusirajući se na korake ispitivanja, možemo ga pročitati kao "Dati kalkulator, pri dodavanju 3 i 5 daje 8".

3.2. opisati/to

Drugi način na koji možemo pisati svoje testove je u stilu "opiši / to". Umjesto toga, ovo koristi metodu opisati za cijelo gniježđenje i nastavlja koristiti to za naše tvrdnje.

U ovom slučaju možemo ugnijezditi opisati metode onoliko koliko nam je potrebno za pisanje testova:

klasa Test Kalkulator: Spek ({opis ("Kalkulator") {val kalkulator = Kalkulator () opis ("Dodatak") {val rezultat = kalkulator.add (3, 5) it ("Daje točan odgovor") {assertEquals ( 8, rezultat)}}}})

Na testovima se koristi manje strukture koja koristi ovaj stil, što znači da imamo puno veću fleksibilnost u načinu pisanja testova.

Nažalost, loša strana ovoga je što testovi ne čitaju tako prirodno kao kada koristimo "given / on / it".

3.3. Dodatni stilovi

Spek ne provodi ove stilove i omogućit će izmjenu ključnih riječi koliko god želite. Jedini zahtjevi su da sve tvrdnje postoje unutar to i da se na toj razini ne mogu pronaći drugi blokovi.

Cjelovit popis ugniježđenih ključnih riječi koji su dostupni je:

  • dato
  • na
  • opisati
  • kontekst

Pomoću njih možemo našim testovima dati najbolju moguću strukturu za način na koji ih želimo napisati.

3.4. Podaci vođeni testovima

Mehanizam koji se koristi za definiranje testova nije ništa drugo nego jednostavni pozivi funkcija. To znači da s njima možemo raditi i druge stvari, poput bilo kojeg uobičajenog koda. Konkretno, ako ih želimo, možemo ih nazvati na temelju podataka.

Najlakši način da to učinite je prelazak preko podataka koje želimo koristiti i pozivanje odgovarajućeg bloka unutar ove petlje:

klasa DataDrivenTest: Spek ({opisati ("Test vođen podacima") {mapOf ("zdravo" u "POZDRAV", "svijet" u "SVIJET"). za svaki {ulaz, očekuje se -> opisati ("Kapitalizacija $ unosa") {it ("Ispravno vraća $ očekivano") {assertEquals (očekuje se, input.toUpperCase ())}}}})

Možemo raditi svakakve stvari ako je potrebno, ali ovo je vjerojatno najkorisnije.

4. Tvrdnje

Spek ne propisuje nikakav poseban način korištenja tvrdnji. Umjesto toga, omogućuje nam upotrebu bilo kojeg okvira za tvrdnje s kojim nam je najviše ugodno.

Očiti izbor bit će org.junit.jupiter.api.Tvrdnje klase, jer već koristimo JUnit 5 framework kao naš testni pokretač.

Međutim, možemo koristiti i bilo koju drugu knjižnicu tvrdnji koju želimo ako poboljšava naše testove - npr. Kluent, Expekt ili HamKrest.

Prednost korištenja ovih knjižnica umjesto standardnog JUnit 5 Tvrdnje razred svodi se na čitljivost testova.

Na primjer, gornji test prepisan koristeći Kluent glasi kao:

klasa Test Kalkulator: Spek ({opisati ("Kalkulator") {val kalkulator = Kalkulator () opisati ("Dodatak") {val rezultat = kalkulator.add (3, 5) it ("Daje točan odgovor") {rezultat trebaEqual 8}}}})

5. Prije i poslije rukovatelja

Kao i kod većine testnih okvira, Spek također može izvršavati logiku prije / nakon testova.

To su, točno kao što im ime govori, blokovi koji se izvršavaju prije ili nakon samog testa.

Ovdje su opcije:

  • prijeGrupa
  • afterGroup
  • beforeEachTest
  • afterEachTest

Oni se mogu smjestiti u bilo koju od ključnih riječi za ugniježđenje i primjenjivat će se na sve unutar te grupe.

Način na koji Spek radi, sav kôd unutar bilo koje ključne riječi za gniježđenje izvršava se odmah na početku testa, ali se kontrolni blokovi izvršavaju određenim redoslijedom usredotočenim oko to blokovi.

Radeći izvana, Spek će izvršiti svaku beforeEachTest blok neposredno prije svake to blok ugniježđen unutar iste grupe i svaki afterEachTest blok odmah nakon svake to blok. Jednako tako, Spek će izvršiti svaku prijeGrupa blokirati neposredno prije svake grupe i svake afterGroup blokirati odmah nakon svake grupe u trenutnom gniježđenju.

To je komplicirano i najbolje je objasniti na primjeru:

klasa GroupTest5: Spek ({opis ("Vanjska grupa") {beforeEachTest {System.out.println ("BeforeEachTest 0")} beforeGroup {System.out.println ("BeforeGroup 0")} afterEachTest {System.out.println ( "AfterEachTest 0")} afterGroup {System.out.println ("AfterGroup 0")} opisati ("Unutarnja grupa 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 ")}}}})

Rezultat pokretanja gore navedenog je:

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

Odmah možemo vidjeti da je vanjski beforeGroup / afterGroup blokovi su oko cijelog niza testova, dok su unutarnji beforeGroup / afterGroup blokovi su samo oko testova u istom kontekstu.

Također možemo vidjeti da su svi prijeGrupa blokovi se izvršavaju prije bilo kojeg beforeEachTest blokovi i suprotno za afterGroup / afterEachTest.

Veći primjer toga, koji prikazuje interakciju između više testova u više skupina, može se vidjeti na GitHubu.

6. Ispitanici

Mnogo puta ćemo napisati jednu specifikaciju za pojedinu ispitnu temu. Spek nudi prikladan način da ovo napišete tako da nam automatski upravlja predmetom koji se testira. Koristimo SubjectSpek osnovna klasa umjesto Spek razred za ovo.

Kada ovo koristimo, trebamo objaviti poziv predmet blok na najudaljenijoj razini. Ovo definira ispitanika. Tada se na to možemo pozivati ​​iz bilo kojeg testnog koda kao predmet.

Ovo možemo koristiti za ponovno pisanje prethodnog testa kalkulatora na sljedeći način:

klasa CalculatorTest: SubjectSpek ({subject {Calculator ()} descri ("Kalkulator") {descri ("Addition") {val result = subject.add (3, 5) it ("Daje točan odgovor") {assertEquals ( 8, rezultat)}}}})

Možda se ne čini puno, ali ovo može pomoći da testovi postanu puno čitljiviji, pogotovo kada postoji velik broj testnih slučajeva koje treba razmotriti.

6.1. Ovisnosti Mavena

Da bismo koristili ekstenziju Predmet, trebamo dodati ovisnost u našu Maven izgradnju:

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

7. Sažetak

Spek je moćan okvir koji omogućuje nekoliko vrlo čitljivih testova, što zauzvrat znači da ih mogu pročitati svi dijelovi organizacije.

To je važno kako bi se omogućilo svim kolegama da doprinesu testiranju cijele aplikacije.

Napokon, isječci koda, kao i uvijek, mogu se naći na GitHubu.


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