2017-06-27 3 views
0

Eine Rails 4.2-Anwendung verfügt über mehrere Modelle mit Attributen, die URLs enthalten. Die URL-Validierung erfolgt am Modell mit validates :website_url, format: { with: /\A(https?|ftp):\/\/(-\.)?([^\s\/?\.#-]+\.?)+(\/[^\s]*)?\z/i }.Überprüfung der URL (Regex) mit RSpec

Ich muss die URL-Validierung mit RSpec 3.5 testen. Es ist wichtig sicherzustellen, dass einige bekannte XSS-Muster die Validierung nicht bestehen und dass die am häufigsten verwendeten URL-Muster die Validierung bestehen.

Im Idealfall würde ich vermeiden, einen Test für jede gültige und ungültige URL, die ich testen, hinzuzufügen, so dass die rspec -fd Ausgabe nicht verschmutzt ist. Dies würde jedoch wahrscheinlich zwei Tests erfordern (einen für gültige URLs und andere für ungültige URLs) und zu jedem Test mehrere Erwartungen hinzufügen (eine Erwartung pro URL), was nicht als gute Idee erscheint.

Die beste Lösung, die ich bisher gefunden habe, sind die folgenden gemeinsamen Beispiele. Können Sie sich eine bessere Möglichkeit vorstellen, die URL-Validierung gründlich zu testen?

RSpec.shared_examples "url validation" do |attribute| 
    INVALID_URLS = [ 
     "invalidurl", 
     "inval.lid/urlexample", 
     "javascript:dangerousJs()//http://www.validurl.com", 
     # Literal array is required for \n to be parsed 
     "http://www.validurl.com\n<script>dangerousJs();</script>" 
    ] 

    VALID_URLS = [ 
     "http://validurl.com", 
     "https://validurl.com/blah_blah" 
    ] 

    context "with invalid URLs in #{attribute}" do 
    INVALID_URLS.each do |url| 
     it "is invalid with #{url}" do 
     object = FactoryGirl.build(factory_name(subject), attribute => url) 
     object.valid? 
     expect(object.errors[attribute]).to include("is invalid") 
     end 
    end 
    end 

    context "with valid URLs in #{attribute}" do 
    VALID_URLS.each do |url| 
     it "is valid with #{url}" do 
     object = FactoryGirl.build(factory_name(subject), attribute => url) 
     expect(object).to be_valid 
     end 
    end 
    end 

Innerhalb der Modelldaten:

include_examples "url validation", :website_url 

bearbeiten: context für gültige und ungültige URLs hinzugefügt so rspec -fd Ausgabe besser organisiert ist, auch mit einer großen Anzahl von Tests URL-Validierung in zufälligen ausgeführt Auftrag.

Antwort

1

Ihre Lösung ist nicht schlecht. Es macht Sinn für mich weiterhin mit mehr shared_examples zu brechen:

RSpec.shared_examples "an invalid URL for attribute" do |url, attribute| 
    let(:object) { FactoryGirl.build(factory_name(subject), attribute => url) } 
    before(:each) { object.valid? } 
    specify { expect(object.errors[attribute]).to include("is invalid") } 
end 

RSpec.shared_examples "a valid URL for attribute" do |url, attribute| 
    let(:object) { FactoryGirl.build(factory_name(subject), attribute => url) } 
    specify { expect(object).to be_valid } 
end 

RSpec.shared_examples "URL validation" do |attribute| 
    [ "invalidurl", 
    "inval.lid/urlexample", 
    # ... 
    ].each do |url| 
    it_behaves_like "a valid URL for attribute", url, attribute 
    end 

    [ "http://validurl.com", 
    "https://validurl.com/blah_blah" 
    ].each do |url| 
    it_behaves_like "an invalid URL for attribute", url, attribute 
    end 
end 

Die wiederholten let(:object) nervt mich, aber ich habe nicht eine sofortige Lösung dafür.

+0

Danke für Ihre Antwort. Ich habe es auch versucht und konnte nicht vermeiden, die Objekterstellung zu wiederholen. Selbst innerhalb desselben "shared_examples" -Blocks war das Übergeben der URL von innerhalb der Schleife an den "let" -Block mühsam. – BrunoFacca

+0

@BrunoFacca Nur um zu verdeutlichen, funktioniert die obige Lösung für Ihren Anwendungsfall? Lassen Sie es mich wissen, wenn Sie irgendwelche Probleme haben. –

+0

Es funktioniert. Könnten Sie jedoch bitte die Vorteile einer Aufschlüsselung auf diese Weise erklären (3 gemeinsame Beispiele erstellen)? Es scheint mir, dass, obwohl dieser Ansatz clever/anspruchsvoll ist, er eine zusätzliche Komplexität einführt, ohne Wiederholungen oder LOC zu reduzieren. Angesichts Ihrer Erfahrung vermisse ich wahrscheinlich etwas. – BrunoFacca