Agurkdatatabeller

1. Introduksjon

Agurk er et Behavioral Driven Development (BDD) rammeverk som lar utviklere lage tekstbaserte testscenarier ved hjelp av Gherkin-språket. I mange tilfeller krever disse scenariene mock-data for å utøve en funksjon, som kan være tungvint å injisere - spesielt med komplekse eller flere oppføringer.

I denne opplæringen vil vi se på hvordan du bruker agurkdatatabeller for å inkludere mock-data på en lesbar måte.

2. Syntaks for scenario

Når vi definerer agurkscenarier, injiserer vi ofte testdata som brukes av resten av scenariet:

Scenario: Korrekt antall bøker som ikke er null funnet av forfatteren Gitt jeg har en bok i butikken som heter The Devil in the White City av Erik Larson Når jeg søker etter bøker av forfatter Erik Larson Så finner jeg 1 bok

2.1. Datatabeller

Mens integrerte data er tilstrekkelig for en enkelt bok, kan scenariet vårt bli rotete når vi legger til flere bøker. For å håndtere dette oppretter vi en datatabell i vårt scenario:

Scenario: Riktig antall bøker som ikke er null funnet av forfatteren. Jeg har følgende bøker i butikken Djevelen i den hvite byen | Erik Larson | | Løven, heksen og garderoben | C.S. Lewis | | I dyrenes hage | Erik Larson | Når jeg søker etter bøker av forfatter Erik Larson, finner jeg to bøker

Vi definerer datatabellen vår som en del av vår Gitt klausul av innrykk tabellen under teksten til Gitt klausul. Ved hjelp av denne datatabellen kan vi legge til et vilkårlig antall bøker - inkludert bare en enkelt bok - i butikken vår ved å legge til eller fjerne rader.

I tillegg datatabeller kan brukes med hvilken som helst klausul - ikke bare Gitt klausuler.

2.2. Inkludert overskrifter

Det er tydelig at den første kolonnen representerer tittelen på boken, og den andre kolonnen representerer forfatteren av boken. Men betydningen av hver kolonne er ikke alltid så åpenbar.

Når det er behov for avklaring, vi kan inkludere en overskrift ved å legge til en ny første rad:

Scenario: Korrekt antall bøker som ikke er null funnet av forfatteren. Jeg har følgende bøker i butikken tittel | forfatter | | Djevelen i den hvite byen | Erik Larson | | Løven, heksen og garderoben | C.S. Lewis | | I dyrenes hage | Erik Larson | Når jeg søker etter bøker av forfatter Erik Larson, finner jeg to bøker

Mens overskriften ser ut til å være bare en rad i tabellen, denne første raden har en spesiell betydning når vi analyserer bordet vårt i en liste over kart i neste avsnitt.

3. Trinndefinisjoner

Etter å ha opprettet vårt scenario implementerer vi Gitt trinndefinisjon. I tilfelle et trinn som inneholder en datatabell, vi implementerer metodene våre med en Data bord argument:

@Given ("some phrase") public void somePhrase (DataTable table) {// ...}

De Data bord objektet inneholder tabelldataene fra datatabellen vi definerte i vårt scenario, så vel som metoder for å transformere disse dataene til brukbar informasjon. Generelt er det tre måter å transformere en datatabell i Agurk: (1) en liste over lister, (2) en liste over kart og (3) en tabelltransformator.

For å demonstrere hver teknikk, bruker vi en enkel Bok domeneklasse:

public class Book {private String title; privat strengforfatter; // standard konstruktører, getters & setters ...}

I tillegg oppretter vi en Bokhandel klasse som klarer Bok gjenstander:

public class BookStore {private List books = new ArrayList (); public void addBook (Book book) {books.add (book); } public void addAllBooks (Collection books) {this.books.addAll (books); } public List booksByAuthor (String author) {return books.stream () .filter (book -> Objects.equals (author, book.getAuthor ())) .collect (Collectors.toList ()); }}

For hvert av de følgende scenariene starter vi med en grunnleggende trinndefinisjon:

offentlig klasse BookStoreRunSteps {privat BookStore-butikk; private Liste funnetBøker; @Før offentlig ugyldig setUp () {store = ny BookStore (); foundBooks = ny ArrayList (); } // Når og deretter definisjoner ...}

3.1. Liste over lister

Den mest grunnleggende metoden for håndtering av tabelldata er konvertering av Data bord argument inn i en liste over lister. Vi kan lage en tabell uten topptekst for å demonstrere:

Scenario: Korrekt antall bøker som ikke er null funnet av forfatter etter liste Gitt jeg har følgende bøker i butikken etter liste | Djevelen i den hvite byen | Erik Larson | | Løven, heksen og garderoben | C.S. Lewis | | I dyrenes hage | Erik Larson | Når jeg søker etter bøker av forfatter Erik Larson, finner jeg to bøker

Agurk konverterer tabellen ovenfor til en liste over lister ved å behandle hver rad som en liste over kolonneverdiene. Dermed analyserer agurk hver rad i en liste som inneholder boktittelen som det første elementet og forfatteren som den andre:

[["Djevelen i den hvite byen", "Erik Larson"], ["Løven, heksen og garderoben", "C.S. Lewis"], ["I dyrenes hage", "Erik Larson"]]

Vi bruker asLister metode - levere en Strengklasse argument - å konvertere Data bord argument til a Liste. Dette Klasse argument informerer asLister metode hvilken datatype vi forventer at hvert element skal være. I vårt tilfelle vil vi at tittelen og forfatteren skal være det String verdier. Dermed leverer vi Strengklasse:

@Given ("^ Jeg har følgende bøker i butikken etter liste $") public void haveBooksInTheStoreByList (DataTable table) {List rader = table.asLists (String.class); for (Listekolonner: rader) {butikk.addBook (ny bok (kolonner.get (0), kolonner.get (1))); }}

Vi gjentar oss deretter over hvert element i underlisten og lager et tilsvarende Bok gjenstand. Til slutt legger vi til hver opprettet Bok innvende mot vårt Bokhandel gjenstand.

Hvis vi analyserte data som inneholder en overskrift, vi hopper over første rad siden Agurk ikke skiller mellom overskrifter og raddata for en liste over lister.

3.2. Liste over kart

Mens en liste over lister gir en grunnleggende mekanisme for å trekke ut elementer fra en datatabell, kan trinnimplementeringen være kryptisk. Agurk gir en liste over kartmekanismer som et mer lesbart alternativ.

I dette tilfellet, vi må gi en overskrift til bordet vårt:

Scenario: Korrekt antall bøker som ikke er null funnet av forfatteren etter kart Gitt jeg har følgende bøker i butikken etter kart | tittel | forfatter | | Djevelen i den hvite byen | Erik Larson | | Løven, heksen og garderoben | C.S. Lewis | | I dyrenes hage | Erik Larson | Når jeg søker etter bøker av forfatter Erik Larson, finner jeg to bøker

I likhet med listen over listermekanismer oppretter Agurk en liste som inneholder hver rad, men i stedet tilordner kolonneoverskriften til hver kolonneverdi. Agurk gjentar denne prosessen for hver påfølgende rad:

[{"title": "Djevelen i den hvite byen", "author": "Erik Larson"}, {"title": "The Lion, the Witch and the Wardrobe", "author": "CS Lewis"} , {"title": "In the Beasts Garden", "author": "Erik Larson"}]

Vi bruker asMaps metode - levere to Strengklasse argumenter - for å konvertere Data bord argument til a Liste. Det første argumentet angir datatypen til nøkkelen (overskrift), og det andre angir datatypen for hver kolonneverdi. Dermed leverer vi to Strengklasse argumenter fordi våre overskrifter (nøkkel) og tittel og forfatter (verdier) alle er Strings.

Så gjentar vi over hver Kart objekt og trekk ut hver kolonneverdi ved å bruke kolonneoverskriften som nøkkel:

@Given ("^ Jeg har følgende bøker i butikken etter kart $") public void haveBooksInTheStoreByMap (DataTable table) {List rader = table.asMaps (String.class, String.class); for (Kartkolonner: rader) {store.addBook (ny bok (kolonner.get ("tittel"), kolonner.get ("forfatter"))); }}

3.3. Bordtransformator

Den siste (og mest rike) mekanismen for å konvertere datatabeller til brukbare objekter er å lage en TableTransformer. EN TableTransformer er et objekt som instruerer agurk hvordan man konverterer en Data bord objekt mot ønsket domeneobjekt:

La oss se et eksempel på scenario:

Scenario: Korrekt antall bøker som ikke er null funnet av forfatter med transformator Gitt jeg har følgende bøker i butikken med transformator | tittel | forfatter | | Djevelen i den hvite byen | Erik Larson | | Løven, heksen og garderoben | C.S. Lewis | | I dyrenes hage | Erik Larson | Når jeg søker etter bøker av forfatter Erik Larson, finner jeg to bøker

Mens en liste over kart med nøkkelordede kolonnedata er mer presis enn en liste med lister, ruller vi fremdeles vår trinndefinisjon med konverteringslogikk. I stedet, vi bør definere trinnet vårt med ønsket domeneobjekt (i dette tilfellet a BookCatalog) som argument:

@Given ("^ Jeg har følgende bøker i butikken med transformator $") public void haveBooksInTheStoreByTransformer (BookCatalog catalog) {store.addAllBooks (catalog.getBooks ()); }

Å gjøre dette, vi må lage en tilpasset implementering av TypeRegistryConfigurer grensesnitt.

Denne implementeringen må utføre to ting:

  1. Lage en ny TableTransformer gjennomføring.
  2. Registrer denne nye implementeringen ved hjelp av configureTypeRegistry metode.

Å fange Data bord til et brukbart domeneobjekt, oppretter vi et BookCatalog klasse:

public class BookCatalog {private List books = new ArrayList (); public void addBook (Book book) {books.add (book); } // standard getter ...}

For å utføre transformasjonen, la oss implementere TypeRegistryConfigurer grensesnitt:

public class BookStoreRegistryConfigurer implementerer TypeRegistryConfigurer {@Override public Locale locale () {return Locale.ENGLISH; } @Override public void configureTypeRegistry (TypeRegistry typeRegistry) {typeRegistry.defineDataTableType (new DataTableType (BookCatalog.class, new BookTableTransformer ())); } // ...

og implementer deretter TableTransformer grensesnitt for vårt BookCatalog klasse:

 privat statisk klasse BookTableTransformer implementerer TableTransformer {@Override public BookCatalog transform (DataTable table) throw Throwable {BookCatalog catalog = new BookCatalog (); table.cells () .stream () .skip (1) // Hopp over topprad .map (felt -> ny bok (fields.get (0), fields.get (1))) .forEach (katalog :: addBook ); retur katalog; }}}

Merk at vi transformerer engelske data fra tabellen, og derfor returnerer vi den engelske lokaliteten fra vår sted () metode. Når vi analyserer data på et annet sted, må vi endre returtype for sted () metoden til riktig sted.

Siden vi inkluderte en datatabelloverskrift i vårt scenario, vi må hoppe over den første raden når det går over tabellcellene (derav hopp over (1) anrop). Vi fjerner hopp over (1) ring hvis bordet vårt ikke hadde en overskrift.

Som standard er limkode assosiert med en test antas å være i samme pakke som løperklassen. Derfor er ingen ekstra konfigurasjon nødvendig hvis vi inkluderer vår BookStoreRegistryConfigurer i samme pakke som løperklassen vår. Hvis vi legger til konfiguratoren i en annen pakke, vi må eksplisitt inkludere pakken i @CucumberOptionslim felt for løperklassen.

4. Konklusjon

I denne artikkelen så vi på hvordan vi kunne definere et agurkascenario med tabelldata ved hjelp av en datatabell. I tillegg har vi utforsket tre måter å implementere en trinndefinisjon som bruker en agurkdatatabell.

Mens en liste med lister og en liste over kart er tilstrekkelig for grunnleggende tabeller, gir en tabelltransformator en mye rikere mekanisme som er i stand til å håndtere mer komplekse data.

Den komplette kildekoden til denne artikkelen finner du på GitHub.


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