Ruby for Newbies Testing Web Apps med Capybara og Agurk

Ruby er et av de mest populære språkene som brukes på nettet. Vi driver en sesjon her på Nettuts + som vil introdusere deg til Ruby, i tillegg til de store rammeverkene og verktøyene som følger med Ruby-utviklingen. I denne episoden lærer du om å teste Sinatra-appene med Agurk, Capybara og Rspec.

I den forrige opplæringen i denne serien så vi på Rspec, og hvordan du kan gjøre testdrevet utvikling med den. Jeg nevnte at i neste episode ville vi se på å bruke Rspec for å teste webapper. Et par kommentatorer nevnte imidlertid at de ville være interessert i å se testing med agurk, så det er det vi skal bruke til å teste en veldig enkel web-app i stedet. Faktisk bruker vi en del av Rspec for å få samme søkeordsyntaks som du så sist, men den faktiske testoppsettet er i agurk.


Foretrekker en Screencast?


Trinn 1: Bygg applikasjonen

Vi skal lage en utrolig enkel Sinatra app for å teste. Til å begynne med, la oss lage en prosjektmappe og kaste dette i en Gemfile:

Hva? Du vet ikke Gemfiles? Gå ut fra under den steinen og ta opp episode 8

 kilde: rubygems perle "sinatra" perle "hagle" perle "agurk" perle "capybara" perle "rspec"

Kjør nå bunt installasjon i den katalogen. Med perlene installert, er vi klare til å gå! (Eventuelt - hvis du bruker RVM-du kan installere disse edelstenene for dette prosjektet bare ved å kjøre rvm --rvmrc - oppgi 1.9.2@cucumber_example; Kjør dette før bunt installasjon)

Så, åpne en fil som heter myapp.rb; her er vår super enkle app; det simulerer bare et nettsted som kan gi deg mulighet til å registrere deg for et nyhetsbrev.

 krever "sinatra / base" klasse MyApp < Sinatra::Base get "/" do erb :index end post "/thankyou" do @name = params["name"] @email = params["email"] erb :thankyou end get "/form" do erb :form end end

Hvis du ikke er kjent med Sinatra, sjekk ut Dan Harpers gode økter Sang med Sinatra; som får deg til å komme i gang med det grunnleggende innen kort tid.

Hvis du er kjent med Sinatra, ser du at vi lager tre stier her; på hjemmesiden ('/'), gjengir vi bare index.erb mal (mer på malene på et minutt). Hvis vi mottar en postforespørsel til banen /Takk skal du ha, vi tar verdiene til Navn og e-post parametere og tilordne dem til forekomstvariabler. Instansvariabler vil være tilgjengelige i hvilken som helst mal vi gjør, som skjer thankyou.erb. Endelig, på / skjema, vi gjengir form.erb mal.

La oss nå bygge disse malene. Sinatra vil se inne i en "visninger" -mappe for maler, så la oss sette dem der. Som du så i myapp.rb, Vi bruker ERB til å lage malene, så de vil selvsagt være ERB-maler. Hvis vi har en layout.erb mal, vil den pakke inn alle våre andre maler. Så, la oss gjøre dette:

layout.erb

     APP   

APP

<%= yield %>

Det ringer til utbytte vil være der de andre malene er satt inn. Og de andre malene er ganske enkle:

index.erb

 

Dette er hjemmesiden

Meld deg på vårt nyhetsbrev!

form.erb

 

Fyll ut dette skjemaet for å motta vårt nyhetsbrev.

thankyou.erb

 

Hei der, <%= @name %>. Du mottar nå vår e-post på <%= @email %>

Så, det er vår app. For å teste det manuelt, kan du sette dette inn i a config.ru fil:

 krever "./myapp" kjøre MyApp

Og kjør deretter hagle i terminalen. Dette vil starte en websever, sannsynligvis på port 9393. Du kan nå poke rundt og teste vår webapp. Men vi vil automatisere denne testingen, ikke sant? La oss gjøre det!


Trinn 2: Innstilling av vårt testmiljø

Agurk regner seg selv som? Oppførsel drevet utvikling med eleganse og glede.? Mens glede virker litt hektisk for meg, tror jeg at vi begge vil være enige om at eleganse, vel, Gurka har det.

Fordi atferdsdrevet utvikling handler om å forstå hva kunden ønsker før du begynner å kode, har agurk som mål å gjøre testene lesbare av klienter (AKA, ikke-programmører). Så vil du se her at alle tester er skrevet i det som ser ut til å være ren tekst (det er faktisk Gherkin).

Husk hvordan, med Rspec, har vi separate spesifikke filer for å beskrive ulike funksjoner? I agurk-tale er det funksjoner, og de tilhører alle i en? Funksjoner? mappe. Inne i den mappen lagres to mapper som heter? Støtte? og? trinn_definisjoner.?

Inne i? Støtte? mappe, åpne en env.rb. Denne koden vil sette opp testmiljøet vårt. Her er det vi trenger:

 require_relative "? /? / myapp" krever "Capybara" krever "Capybara / agurk" krever "rspec" World gjør Capybara.app = MyApp inkludere Capybara :: DSL inkluderer RSpec :: Matchers end

Dette krever de forskjellige bibliotekene vi trenger, og bruker inkludere å laste deres metoder inn i vårt miljø. Hva er denne Capybara som vi bruker? I utgangspunktet er det funksjonaliteten som gjør at vi kan bruke vår webapp, slik at vi kan teste den. Det er viktig å sette Capybara.app til vår app. Jeg bør nevne at, hvis vi gjør dette med en Rails-app, vil det meste av dette oppsettet bli gjort automatisk for oss.

(Merk: I skjermbildet, jeg inkludere RSpec :: Forventninger unneccessarily; la det være.)

Ok, så la oss skrive noen tester!


Trinn 3 Skriver testene

La oss starte med vår hjemmeside. Åpne filen home_pages.feature (i mappen? funksjoner?) og starte med dette:

 Feature: Viewer besøker hjemmesiden For å lese siden Som seer, vil jeg se hjemmesiden til appen min

Dette er en vanlig måte å starte en funksjonsfil starter på; Ser egentlig ikke ut som kode, gjør det? Vel, det er Gherkin, et domenespesifikt språk (DSL) som? Lar deg beskrive programvareens oppførsel uten å spesifisere hvordan denne oppførselen er implementert.? Det vi har skrevet så langt, går ikke på noen måte, men det forklarer formålet med funksjonen. Her er den generelle strukturen:

 For å [mål] Som en [rolle] vil jeg ha [funksjon]

Du trenger ikke å følge den mal: du kan sette hva du vil; Formålet er å beskrive funksjonen. Dette synes imidlertid å være et vanlig mønster.

Neste kommer en liste over scenarier som beskriver funksjonen. Her er den første:

 Scenario: Se hjemmesiden Gitt jeg er på hjemmesiden Da skal jeg se "Dette er hjemmesiden."

Hvert scenario kan ha opptil tre deler: gitts, Nårs, og Deretters:

  • gitt - gitt linjer beskriver hva forutsetningen bør eksistere.
  • Når - Når linjer beskriver handlingene du tar.
  • Deretter - Deretter linjer beskriver resultatet.

Det er også Og linjer, som gjør hva linjen over dem gjør. For eksempel:

 Gitt jeg er på hjemmesiden Og jeg er logget inn Da skal jeg se "Velkommen tilbake!" Og jeg bør se "Innstillinger"

I dette tilfellet er den første Og linje fungerer som en gitt linje, og den andre fungerer som en Deretter linje.

Vi får se noen Når linjer kort tid. Men nå, la oss kjøre den testen. For å gjøre det, kjør agurk i terminalen. Du ser sannsynligvis noe slikt ut:

Gurkespesifikkfilene er skrevet for å være lesbare for ikke-programmører, så vi må? Implementere trinndefinisjoner for udefinerte trinn.? Heldigvis gir agurk oss noen utdrag for å begynne med.

Ser på disse utdragene, kan du se hvordan dette vil fungere. Hvert trinn er matchet med et vanlig uttrykk. Eventuelle citerte verdier vil bli fanget og bestått som en blokkparameter. Inne i blokken gjør vi hva vi forventer å skje som følge av dette trinnet. Dette kan være oppsettkoden i gitt trinn, noen beregninger eller handlinger i Når trinn og en sammenligning i Deretter trinn.

Gurka vil laste alle filer i mappen? Funksjoner / step_definitions? for trinn, så la oss lage? sinatra_steps.rb? fil og legg til disse to trinnene:

 Gitt / ^ Jeg er på hjemmesiden $ / gjør besøk "/" avslutte Da / ^ jeg burde se "([^"] *) "$ / do | text | page.should have endret tekst end

I denne lille brikken her bruker vi Agurk, Rspec og Capybara. For det første har vi agurk gitt og Deretter metoden samtaler. For det andre bruker vi Capybara-metodene besøk (for å besøke en URL) og has_content?. Men du ser ikke anropet til has_content? fordi vi har lastet RSpec-spillerne, så vi kan få våre tester lest som de ville med Rspec. Hvis vi ønsket å forlate RSpec ut, ville vi bare skrive page.has_content? tekst.

Nå, hvis du kjører agurk igjen, vil du se at våre tester passerer:

La oss legge til to flere scenarier for vår hjemmeside:

Scenario: Finn kurs på hjemmesiden Gitt jeg er på hjemmesiden Da skal jeg se "MY APP" i selgeren "h1" Scenario: Finn lenken til skjemaet Gitt Jeg er på hjemmesiden Da skal jeg se "Registrer deg for vårt nyhetsbrev. " i en lenke

Disse krever to flere Deretter trinnene, som du finner hvis du prøver å kjøre dette. Legg til disse til sinatra_steps.rb:

 Da / ^ skal jeg se "([^"] *) "i selectoren" ([^ "] *)" $ / do | text, selector | page.should have_selector selector, content: tekst end Da / ^ Jeg burde se "([^"] *) "i en link $ / do | text | page.should have_link tekst slutten

Du bør kunne fortelle hva dette gjør: den første ser etter tekst innenfor et bestemt element på siden. Den andre ser etter en lenke med den oppgitte teksten (ja, du kunne ha gjort det Da bør jeg se "Registrer deg?" I velgeren "a", men jeg ville gjerne ha en annen Capybara / Rspec-metode)

Igjen, løp agurk; Du vil se alle våre tester passerer:

La oss nå åpne? Funksjoner / form_page.feature ?; kaste dette inn der:

 Feature: Viewer melde seg på nyhetsbrevet For å motta nyhetsbrevet Som bruker av nettsiden vil jeg kunne registrere meg for nyhetsbrevet. Scenario: Se skjema siden Gitt jeg er på "/ form" Da skal jeg se "Fyll ut ut dette skjemaet for å motta vårt nyhetsbrev. " Scenario: Fyll ut skjema Gitt jeg er på "/ form" Når jeg fyller inn "navn" med "John Doe" Og jeg fyller ut "email" med "[email protected]" Og jeg klikker "Registrer deg!" Da skal jeg se "Hei der, John Doe. Du får ny mottatt vårt nyhetsbrev på [email protected]"

Det første scenariet her er ganske enkelt, selv om vi trenger å skrive gitt trinn for er. Du kan sikkert finne ut hvordan du gjør det nå:

 Gitt / ^ Jeg er på "([^"] *) "$ / do | sti | besøk sti slutt

Den andre er litt mer i dybden. For første gang bruker vi Når trinn (husk, Og trinn som følger Når trinn er også Når trinn). Det er ganske klart hva de Når skritt bør gjøre, men hvordan gjør vi det i Ruby-koden? Heldigvis har Capybara noen nyttige metoder for å hjelpe deg:

 Når / ^ jeg fyller inn "([^"] *) "med" ([^ "] *)" $ / do | element, tekst | fill_in element, with: text end Når / ^ jeg klikker "([^"] *) "$ / do | element | click_on element end

Vi bruker Fyll inn metode, som tar navnet eller id-attributtet til et element på siden. Vi bruker også click_on, som vil klikke på elementet med gitt tekst, id eller verdi. Det er også mer spesifikt click_link og click_button. For å se mer, sjekk ut Capybara Readme. Bla gjennom "DSL"? avsnitt for å se flere av metodene som Capybara tilbyr.

Når du kjører agurk nå bør du få alle våre tester, passerer:


Konklusjon

Innse at det vi prøver her er det nettopp brukergrensesnittet, ikke den underliggende koden. Hvis koden virkelig signerte deg for nyhetsbrevet, må vi også teste koden som legger til navn og e-postadresse i databasen, etc. Bare fordi vi ser hva vi skal se, betyr det ikke at vi Jeg mottar faktisk nyhetsbrevet, ikke sant? Det bør testes separat.

Og det tester webapps med agurk-, Capybara- og Rspec-kampanjer. Som nevnt, sjekk ut Capybara-dokumentene for mer!