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.
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
Gemfile
s? 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:
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:
Detta är hemsidan
Anmäl dig till vårt nyhetsbrev!
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!
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!
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: Given
s, När
s, och Sedan
s:
Given
linjer beskriver vad förhandstillståndet borde finnas.När
linjer beskriver de åtgärder du tar.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:
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!