Ruby for Newbies Testen von Web-Apps mit Capybara und Gurke

Ruby ist eine der beliebtesten Sprachen im Internet. Wir führen hier eine Session zu Nettuts + durch, die Sie in Ruby einführt, sowie die großartigen Frameworks und Tools, die mit der Ruby-Entwicklung einhergehen. In dieser Episode erfahren Sie, wie Sie Ihre Sinatra-Apps mit Cucumber, Capybara und Rspec testen.

Im vorherigen Tutorial dieser Serie haben wir uns mit Rspec befasst und wie Sie damit testgetriebene Entwicklung durchführen können. Ich erwähnte, dass wir uns in der nächsten Episode mit Rspec beschäftigen würden, um Web-Apps zu testen. Einige Kommentatoren erwähnten jedoch, dass sie daran interessiert wären, mit Cucumber getestet zu werden. Daher testen wir stattdessen eine sehr einfache Web-App. Eigentlich verwenden wir einen Teil von Rspec, um die gleiche Matchersyntax zu erhalten, wie Sie es beim letzten Mal gesehen haben, aber der eigentliche Testaufbau ist in Cucumber.


Ich bevorzuge einen Screencast?


Schritt 1: App erstellen

Wir werden eine unglaublich einfache Sinatra-App zum Testen erstellen. Als Erstes erstellen wir einen Projektordner und werfen diesen in ein Gemfile:

Was? Du weißt es nicht Gemfiles? Raus unter diesem Rock und hol dir Episode 8 nach

 quelle: rubygems edelstein "sinatra" edelstein "schrotflinte" edelstein "gurke" edelstein "capybara" edelstein "rspec"

Nun laufe Bundle installieren in diesem Verzeichnis. Mit den Edelsteinen sind wir bereit! (Falls Sie RVM verwenden, können Sie diese Edelsteine ​​optional nur für dieses Projekt installieren, indem Sie sie ausführen rvm --rvmrc --create 1.9.2@cucumber_example; Führen Sie das vorher aus Bundle installieren)

Öffnen Sie also eine Datei mit dem Namen myapp.rb; hier ist unsere super einfache app; Es simuliert lediglich eine Website, auf der Sie sich möglicherweise für einen Newsletter anmelden können.

 erfordern "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

Wenn Sie sich mit Sinatra nicht auskennen, sollten Sie sich Dan Harpers ausgezeichnete Sessions mit Sinatra anhören. Das bringt Sie in kürzester Zeit mit den Grundlagen zum Laufen.

Wenn Sie mit Sinatra vertraut sind, werden Sie feststellen, dass wir hier drei Pfade erstellen. Auf der Startseite ('/') rendern wir nur das index.erb Vorlage (mehr zu den Vorlagen in einer Minute). Wenn wir eine Post-Anfrage an den Pfad bekommen /Danke dir, Wir nehmen die Werte der Name und Email Parameter und weisen sie Instanzvariablen zu. Instanzvariablen sind in jeder Vorlage, die wir rendern, verfügbar danke.erb. Endlich um /bilden, wir machen das form.erb Vorlage.

Nun lassen Sie uns diese Vorlagen erstellen. Sinatra sucht nach Vorlagen in einem Ordner "Views", also legen wir sie dort ab. Wie du gesehen hast myapp.rb, Wir verwenden ERB zum Rendern der Vorlagen, daher handelt es sich natürlich um ERB-Vorlagen. Wenn wir eine haben layout.erb Vorlage, es werden alle unsere anderen Vorlagen verpackt. Also, lass uns das tun:

layout.erb

     DIE APP   

DIE APP

<%= yield %>

Dieser Anruf an Ausbeute Dort werden die anderen Vorlagen eingefügt. Und diese anderen Vorlagen sind ziemlich einfach:

index.erb

 

Dies ist die Startseite

Melden Sie sich für unseren Newsletter an!

form.erb

 

Füllen Sie dieses Formular aus, um unseren Newsletter zu erhalten.

danke.erb

 

Hallo, <%= @name %>. Sie erhalten jetzt unsere E-Mail an <%= @email %>

Also gibt es unsere App. Um es manuell zu testen, können Sie dies in ein einfügen config.ru Datei:

 erfordern "./myapp", um MyApp auszuführen

Und dann renn Schrotflinte im Terminal. Dies startet einen Webserver, wahrscheinlich auf Port 9393. Sie können jetzt unsere Web-App testen und testen. Aber wir wollen dieses Testen automatisieren, richtig? Machen wir das!


Schritt 2: Einstellen unserer Testumgebung

Gurke versteht sich als "verhaltensorientierte Entwicklung mit Eleganz und Freude". Während mir die Freude ein bisschen weit hergeholt erscheint, denke ich, dass wir beide dieser Eleganz zustimmen werden. Nun, Cucumber hat es.

Da die verhaltensorientierte Entwicklung zum Teil dazu dient, die Anforderungen des Kunden zu verstehen, bevor Sie mit dem Programmieren beginnen, zielt Cucumber darauf ab, die Tests für Kunden lesbar zu machen (AKA, Nichtprogrammierer). Sie werden hier also sehen, dass alle Ihre Tests in scheinbar reinem Text (es ist eigentlich Gherkin) geschrieben ist..

Denken Sie daran, wie wir mit Rspec separate Spec-Dateien haben, um die verschiedenen Funktionalitäten zu beschreiben? In der Gurkensprache sind dies Features, und sie gehören alle zu "Features". Mappe. Erstellen Sie in diesem Ordner zwei weitere Ordner namens "Support". und? step_definitions.?

In der? Unterstützung? Ordner öffnen Sie ein env.rb. Dieser Code richtet unsere Testumgebung ein. Was wir brauchen:

 required_relative "? /? / myapp" erfordern "Capybara" erfordern "Capybara / Gurke" erfordern "rspec". World do Capybara.app = MyApp schließt Capybara :: DSL mit RSpec :: Matchers ein

Dies erfordert die verschiedenen Bibliotheken, die wir benötigen und verwenden umfassen um ihre Methoden in unsere Umgebung zu laden. Was ist das für ein Capybara, das wir verwenden? Im Grunde ist es die Funktionalität, mit der wir unsere Web-App verwenden können, um sie zu testen. Es ist wichtig zu setzen Capybara.app zu unserer App. Ich sollte erwähnen, dass, wenn wir dies mit einer Rails-App machen würden, der größte Teil dieses Setups für uns automatisch durchgeführt würde.

(Hinweis: Im Screencast habe ich umfassen RSpec :: Expectations unnötig; Lass es aus.)

Okay, lass uns ein paar Tests schreiben!


Schritt 3 Schreiben der Tests

Beginnen wir mit unserer Homepage. Öffne die Datei home_pages.feature (im Ordner "features") und beginnen Sie damit:

 Feature: Viewer besucht die Startseite Um die Seite zu lesen Als Zuschauer möchte ich die Startseite meiner App sehen

Dies ist eine übliche Methode zum Starten einer Feature-Datei. Sieht nicht wirklich Code aus, oder? Nun, es ist Gherkin, eine domänenspezifische Sprache (DSL), mit der Sie das Verhalten von Software beschreiben können, ohne zu beschreiben, wie dieses Verhalten implementiert wird. Was wir bisher geschrieben haben, läuft in keiner Weise, erklärt aber den Zweck der Funktion. Hier ist die allgemeine Struktur:

 Um [Ziel] Als [Rolle] möchte ich [Funktion]

Sie müssen dieser Vorlage nicht folgen: Sie können alles einfügen, was Sie möchten. Der Zweck besteht darin, das Merkmal zu beschreiben. Dies scheint jedoch ein allgemeines Muster zu sein.

Als Nächstes wird eine Liste von Szenarien angezeigt, in denen die Funktion beschrieben wird. Hier ist der erste:

 Szenario: Startseite anzeigen Gegeben, ich bin auf der Startseite. Dann sollte ich "Dies ist die Startseite" sehen.

Jedes Szenario kann aus bis zu drei Teilen bestehen: Gegebens, Wanns und Danns:

  • Gegeben - Gegeben Zeilen beschreiben, welche Vorbedingung vorhanden sein sollte.
  • Wann - Wann Zeilen beschreiben die Aktionen, die Sie ausführen.
  • Dann - Dann Zeilen beschreiben das Ergebnis.

Es gibt auch Und Linien, die tun, was auch immer die Linie über ihnen tut. Zum Beispiel:

 Gegeben, ich bin auf der Startseite und bin angemeldet. Dann sollte ich "Welcome Back!" Sehen. Und ich sollte "Einstellungen" sehen

In diesem Fall der erste Und Linie wirkt als a Gegeben Linie, und die zweite fungiert als Dann Linie.

Wir werden ein paar sehen Wann Zeilen in Kürze. Aber jetzt lass uns diesen Test durchführen. Um das zu tun, renne Gurke im Terminal. Sie werden wahrscheinlich so etwas sehen:

Gurken-Feature-Dateien sind so geschrieben, dass sie für Nicht-Programmierer lesbar sind. Daher müssen Schrittdefinitionen für undefinierte Schritte implementiert werden. Zum Glück gibt uns Cucumber zunächst einige Schnipsel.

Wenn Sie diese Ausschnitte betrachten, können Sie sehen, wie dies funktioniert. Jeder Schritt wird mit einem regulären Ausdruck abgeglichen. Alle angegebenen Werte werden erfasst und als Blockparameter übergeben. Innerhalb des Blocks tun wir alles, was wir als Ergebnis dieses Schrittes erwarten. Dies kann ein Einrichtungscode in sein Gegeben Schritte, einige Berechnungen oder Aktionen in Wann Schritte und einen Vergleich in Dann Schritte.

Cucumber lädt alle Dateien im Ordner "features / step_definitions". für Schritte, also lassen Sie uns? sinatra_steps.rb? Datei und fügen Sie diese beiden Schritte hinzu:

 Gegeben / ^ Ich bin auf der Startseite $ / do besuche "/" Ende Dann / ^ sollte ich sehen "([^"] *) "$ / do | text | page.hould_content text end

In diesem kleinen Ausschnitt hier verwenden wir Gurke, Rspec und Capybara. Erstens haben wir die Gurke Gegeben und Dann Methodenaufrufe. Zweitens verwenden wir die Capybara-Methoden Besuch (um eine URL zu besuchen) und has_content?. Aber Sie sehen den Anruf nicht an has_content? da wir die RSpec-Matcher geladen haben, können wir unsere Tests so ablesen, wie sie es mit Rspec tun würden. Wenn wir RSpec auslassen wollten, würden wir einfach schreiben page.has_content? Text.

Wenn du jetzt rennst Gurke Sie werden sehen, dass unsere Tests bestehen:

Fügen wir zwei weitere Szenarien für unsere Homepage hinzu:

Szenario: Überschrift auf der Startseite finden Gegeben bin ich auf der Homepage. Dann sollte ich "MEIN APP" in der Auswahl "h1" sehen. Szenario: Findet den Link zum Formular Gegeben ich bin auf der Homepage. Dann sollte ich "Registrieren" sehen für unseren Newsletter. " in einem Link

Diese erfordern zwei weitere Dann Schritte, wie Sie finden, wenn Sie versuchen, dies auszuführen. Fügen Sie diese zu hinzu sinatra_steps.rb:

 Dann / ^ Ich sollte "([^"] *) "im Selector" ([^ "] *)" $ / do | text, Selector | sehen page.should have_selector Auswahl, Inhalt: Textende Dann / ^ Ich sollte "([^"] *) "in einem Link $ / do | text | page.should_link.tould_link.tould_hine_link sehen

Sie sollten in der Lage sein zu erkennen, was diese tun: Der erste sucht nach Text innerhalb eines bestimmten Elements auf der Seite. Die zweite sucht nach einem Link mit dem angegebenen Text (ja, das hätten Sie tun können Dann sollte ich in der Auswahl "a" "Anmelden" sehen., aber ich wollte dir eine andere Capybara / Rspec-Methode

Wieder rennen Gurke; Sie sehen alle unsere Tests bestanden:

Lassen Sie uns jetzt? Features / form_page.feature? Wirf das hier rein:

 Feature: Viewer registriert sich für den Newsletter Um den Newsletter zu erhalten Als Benutzer der Website möchte ich mich für den Newsletter anmelden können Szenario: Formularseite anzeigen Gegeben bin ich auf "/ form" Dann sollte ich sehen "Füllen" Hier erhalten Sie unseren Newsletter. " Szenario: Formular ausfüllen Wenn ich auf "/ form" stehe, wenn ich mit "John Doe" "Name" ausfülle und mit "[email protected]" "email" "ausfülle". Und ich klicke auf "Anmelden!" Dann sollte ich sehen "Hallo, John Doe. Sie erhalten neu unseren E-Mail-Newsletter unter [email protected]".

Das erste Szenario hier ist ziemlich einfach, obwohl wir das schreiben müssen Gegeben Schritt für ist. Sie können wahrscheinlich jetzt herausfinden, wie das geht:

 Gegeben / ^ Ich bin auf "([^"] *) "$ / do | Pfad | Besuchspfadende

Der zweite ist etwas tiefer. Zum ersten Mal verwenden wir Wann Schritte (denken Sie daran, die Und Schritte, die dem folgen Wann Schritt sind auch Wann Schritte). Es ist ziemlich offensichtlich, was diese sind Wann Schritte sollten tun, aber wie machen wir das im Ruby-Code? Zum Glück hat Capybara ein paar nützliche Methoden, um zu helfen:

 Wenn / ^ füge ich "([^"] *) "mit" ([^ "] *)" $ / do | element, text | fill_in Element mit: text end Wenn / ^ klicke ich auf "([^"] *) "$ / do | element | click_on Elementende

Wir benutzen die ergänze Methode, die den Namen oder das ID-Attribut eines Elements auf der Seite übernimmt. Wir benutzen auch klicke auf, Klicken Sie auf das Element mit dem angegebenen Text, der angegebenen ID oder dem angegebenen Wert. Es gibt auch die spezifischeren click_link und klicktaste. Weitere Informationen finden Sie in der Capybara-Readme-Datei. Stöbern Sie im? DSL? Weitere Informationen zu den Methoden, die Capybara anbietet.

Wenn du rennst Gurke Jetzt sollten Sie alle Tests bestehen und bestanden haben:


Fazit

Stellen Sie fest, dass wir hier nur die Benutzeroberfläche testen, nicht den zugrunde liegenden Code. Wenn unser Code Sie wirklich für den Newsletter angemeldet hat, müssen wir auch den Code testen, der den Namen und die E-Mail-Adresse in unserer Datenbank hinzufügt bekomme eigentlich den Newsletter, oder? Das sollte separat getestet werden.

Und das testet Web-Apps mit Matchern von Cucumber, Capybara und Rspec. Wie bereits erwähnt, lesen Sie in den Capybara-Dokumenten nach!