Ruby for Newbies Testa Web Apps med Capybara och Gurka

Ruby är ett av de mest populära språk som används på webben. Vi kör en session här på Nettuts + som kommer att introducera dig till Ruby, liksom de stora ramar och verktyg som följer med Ruby utveckling. I det här avsnittet lär du dig att testa dina Sinatra-appar med gurka, Capybara och Rspec.

I den tidigare handledningen i denna serie tittade vi på Rspec och hur du kan göra testdriven utveckling med den. Jag nämnde att vi i nästa avsnitt skulle titta på att använda Rspec för att testa webapps. Ett par kommenterare nämnde dock att de skulle vara intresserade av att testa med gurka, så det är vad vi ska använda för att testa en mycket enkel webapp i stället. Faktum är att vi använder en del av Rspec för att få samma matchningssyntax som du såg förra gången, men den faktiska testinställningen är i Gurka.


Föredrar en skärmdump?


Steg 1: Bygga App

Vi ska skapa en otroligt enkel Sinatra app för att testa. Till att börja med, låt oss skapa en projektmapp och kasta den i en Gemfile:

Vad? Du vet inte Gemfiles? Gå ut ur den där klippan och hämta episod 8

 källa: rubygems pärla "sinatra" pärla "hagelgevär" pärla "gurka" pärla "capybara" pärla "rspec"

Nu kör buntinstallation i den katalogen. Med juvelerna installerade är vi redo att gå! (Eventuellt - om du använder RVM-du kan bara installera dessa pärlor för projektet genom att köra rvm - rvmrc - skapa 1.9.2@cucumber_example; kör detta innan buntinstallation)

Så öppna en fil som heter myapp.rb; här är vår super enkla app; det simulerar bara en webbplats som kan låta dig registrera dig för ett nyhetsbrev.

 kräver "sinatra / bas" klass 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

Om du inte känner till Sinatra, kolla Dan Harpers utmärkta sessioner. Sjunga med Sinatra; som får dig att komma igång med grunderna på nolltid.

Om du är bekant med Sinatra ser du att vi skapar tre vägar här; på hemsidan ('/'), gör vi bara index.erb mall (mer på mallarna på en minut). Om vi ​​får en postförfrågan till sökvägen /tack, vi tar värdena på namn och e-post parametrar och tilldela dem till exempel variabler. Instansvariabler kommer att finnas tillgängliga inuti vilken mall vi gör, vilket råkar vara thankyou.erb. Slutligen, på /form, vi gör det form.erb mall.

Låt oss nu bygga dessa mallar. Sinatra kommer att se in i en "vyer" -mapp för mallarna, så låt oss sätta dem där. Som du såg in myapp.rb, vi använder ERB för att göra mallarna, så de kommer givetvis att vara ERB-mallar. Om vi ​​har en layout.erb mall, kommer det att paketera alla våra andra mallar. Så, låt oss göra det här:

layout.erb

     APPEN   

APPEN

<%= yield %>

Det kallar till avkastning kommer att vara där de övriga mallarna sätts in. Och de andra mallarna är ganska enkla:

index.erb

 

Detta är hemsidan

Anmäl dig till vårt nyhetsbrev!

form.erb

 

Fyll i formuläret för att få vårt nyhetsbrev.

thankyou.erb

 

Hallå där, <%= @name %>. Du får nu vårt mail på <%= @email %>

Så, det finns vår app. För att testa det manuellt kan du lägga det här i en config.ru fil:

 kräver "./myapp" kör MyApp

Och kör sedan hagelgevär i terminalen. Detta kommer att starta en webbsändare, förmodligen på port 9393. Du kan nu kasta runt och testa vår webbapp. Men vi vill automatisera denna testning, eller hur? Vi gör det!


Steg 2: Att ställa in vår testmiljö

Gurka räknar sig själv som? Beteendedriven utveckling med elegans och glädje.? Medan glädje verkar lite fördjupad för mig, tror jag att vi båda kommer överens om att elegans, ja, det har gurka.

Eftersom beteendedriven utveckling delvis handlar om att förstå vad kunden vill innan du börjar kodning, syftar gurka till att göra sina tester läsbara av kunder (AKA, icke-programmerare). Så ser du här att alla dina test är skrivna i vad som verkar vara vanlig text (det är faktiskt Gurkja).

Kom ihåg hur, med Rspec, har vi separata specfiler för att beskriva olika funktioner? I gurka-tal är det funktioner, och alla hör till en? Funktioner? mapp. Inne i den mappen skapas ytterligare två mappar som heter? Support? och? steg_definitioner.?

Inuti? Stöd? mapp, öppna en env.rb. Denna kod kommer att ställa in vår testmiljö. Här är vad vi behöver:

 require_relative "? /? / myapp" kräver "Capybara" kräver "Capybara / gurka" kräver "rspec" World do Capybara.app = MyApp inkluderar Capybara :: DSL inkluderar RSpec :: Matchers slut

Detta kräver de olika bibliotek som vi behöver och använder inkludera att ladda sina metoder i vår miljö. Vad är den här Capybara som vi använder? I grund och botten är det funktionaliteten som tillåter oss att använda vår webbapp, så att vi kan testa den. Det är viktigt att ställa in Capybara.app till vår app. Jag borde nämna att, om vi gör det med en Rails-app, skulle det mesta av denna inställning göras automatiskt för oss.

(Obs: I skärmbilden, jag inkluderar RSpec :: Förväntningar unneccessarily; lämna det ute.)

Okej, låt oss skriva några tester!


Steg 3 Skriva testerna

Låt oss börja med vår hemsida. Öppna filen home_pages.feature (i mappen? funktioner?) och börja med det här:

 Funktion: Viewer besöker hemsidan För att läsa sidan Som tittare vill jag se min apps startsida

Detta är ett vanligt sätt att starta en funktionsfil startar; Verkar inte riktigt som kod, gör det? Jo, det är Gherkin, ett domänspecifikt språk (DSL) som låter dig beskriva programvarans beteende utan att ange hur det beteendet implementeras.? Det vi skrivit hittills går inte på något sätt, men det förklarar syftet med funktionen. Här är den allmänna strukturen:

 För att [mål] Som en [roll] vill jag ha [funktion]

Du behöver inte följa den mallen: du kan lägga vad du vill, Syftet är att beskriva funktionen. Men detta verkar vara ett vanligt mönster.

Därefter kommer en lista över scenarier som beskriver funktionen. Här är den första:

 Scenario: Visa hemsida Eftersom jag är på hemsidan Då ska jag se "Detta är hemsidan."

Varje scenario kan ha upp till tre delar: Givens, Närs, och Sedans:

  • Given - Given linjer beskriver vad förhandstillståndet borde finnas.
  • När - När linjer beskriver de åtgärder du tar.
  • Sedan - Sedan linjer beskriver resultatet.

Det finns också Och linjer, som gör vad linjen ovanför dem gör. Till exempel:

 Med tanke på att jag är på hemsidan Och jag är inloggad Då ska jag se "Välkommen tillbaka!" Och jag borde se "Inställningar"

I det här fallet är den första Och linje fungerar som en Given linje, och den andra fungerar som en Sedan linje.

Vi får se några När rader snart. Men just nu, låt oss springa det testet. För att göra det, springa gurka i terminalen. Du kommer förmodligen se något så här:

Gurkafunktionsfiler är skrivna så att de kan läsas till icke-programmörer, så vi måste? Implementera stegdefinitioner för odefinierade steg.? Tack och lov, gurka ger oss några utdrag att börja med.

Om du tittar på dessa utdrag kan du se hur detta kommer att fungera. Varje steg matchas med ett vanligt uttryck. Eventuella citerade värden kommer att fångas och skickas som en blockparameter. Inuti kvarteret gör vi vad vi förväntar oss att hända som ett resultat av det steget. Detta kan vara inställningskod i Given steg, några beräkningar eller åtgärder i När steg och en jämförelse i Sedan steg.

Gurka kommer ladda alla filer i mappen? Features / step_definitions? för steg, så låt oss skapa? sinatra_steps.rb? fil och lägg till dessa två steg:

 Givet / ^ Jag är på hemsidan $ / do visit "/" avsluta Då / ^ ska jag se "([^"] *) "$ / do | text | page.should have text

I det här lilla fragmentet använder vi Gurka, Rspec och Capybara. För det första har vi gurkan Given och Sedan metodsamtal. För det andra använder vi Capybara-metoderna besök (för att besöka en URL) och has_content?. Men du ser inte samtalet till has_content? eftersom vi har laddat RSpec-matcharna, så vi kan läsa våra test som de skulle med Rspec. Om vi ​​ville lämna RSpec ut, skulle vi bara skriva page.has_content? text.

Nu, om du kör gurka igen ser du att våra tester passerar:

Låt oss lägga till ytterligare två scenarier för vår hemsida:

Scenario: Hitta rubrik på hemsidan Eftersom jag är på hemsidan Då ska jag se "MY APP" i väljaren "h1" Scenario: Hitta länken till formuläret Eftersom jag är på hemsidan Då ska jag se "Registrera dig för vårt nyhetsbrev. " i en länk

Dessa kräver ytterligare två Sedan steg, som du hittar om du försöker köra detta. Lägg till dessa till sinatra_steps.rb:

 Då / ^ ska jag se "([^"] *) "i väljaren" ([^ "] *)" $ / do | text, väljare | page.should have_selector selector, content: text end Then / ^ Jag borde se "([^"] *) "i en länk $ / do | text | page.should have_link textänden

Du borde kunna berätta vad de gör: den första letar efter text inom ett visst element på sidan. Den andra letar efter en länk med den givna texten (ja, du kunde ha gjort det Då ska jag se "Registrera?" I väljaren "a", men jag ville ha dig en annan Capybara / Rspec-metod)

Återigen, springa gurka; Du ser alla våra test passerar:

Låt oss nu öppna? Features / form_page.feature ?; kasta detta in där:

 Funktion: Viewer registrerar sig för nyhetsbrevet För att få nyhetsbrevet Som användare av webbplatsen vill jag kunna anmäla mig till nyhetsbrevet. Scenario: Se formulärsida Eftersom jag är på "/ form" Då ska jag se "Fyll ut denna blankett för att få vårt nyhetsbrev. " Scenario: Fyll i formulär Med tanke på att jag är på "/ form" När jag fyller i "namn" med "John Doe" Och jag fyller i "email" med "[email protected]" Och jag klickar på "Registrera!" Då ska jag se "Hej där, John Doe. Du kommer att få nya vårt nyhetsbrev på [email protected]"

Det första scenariot här är ganska enkelt, även om vi behöver skriva Given steg för är. Du kan förmodligen räkna ut hur man gör det nu:

 Givet / ^ Jag är på "([^"] *) "$ / do | path | besök sökväg

Den andra är lite mer djupgående. För första gången använder vi När steg (kom ihåg det Och steg som följer När steg är också När steg). Det är ganska uppenbart vad de När steg bör göra, men hur gör vi det i Ruby-koden? Tack och lov har Capybara några praktiska metoder för att hjälpa till:

 När / ^ jag fyller i "([^"] *) "med" ([^ "] *)" $ / do | element, text | fill_in element, med: text slutet När / ^ jag klickar på "([^"] *) "$ / do | element | click_on element slutet

Vi använder Fyll i metod, som tar namnet eller id-attributet till ett element på sidan. Vi använder också Klicka på, som kommer att klicka på elementet med den angivna texten, id eller värde. Det finns också mer specifika click_link och click_button. För att se mer, kolla Capybara Readme. Bläddra runt? DSL? avsnitt för att se mer av de metoder som Capybara erbjuder.

När du kör gurka nu borde du få alla våra test, passerar:


Slutsats

Inse att det vi testar här är rätt gränssnitt, inte den underliggande koden. Om vår kod verkligen undertecknade dig för nyhetsbrevet, skulle vi också behöva testa koden som lägger till namnet och e-postadressen i vår databas etc. Bara för att vi ser vad vi ska se betyder inte att vi Jag kommer faktiskt att få nyhetsbrevet, eller hur? Det bör testas separat.

Och det testar webbapps med gurka, Capybara och Rspec-matchare. Som jag nämnde, kolla Capybara-dokumenten för mer!