2012-12-22 13 views
5

In meiner Rails 3-Anwendung, habe ich ein RSpec spec, das Verhalten eines bestimmten Feldes (Rolle im Benutzer Modell) zu gewährleisten, überprüft, ob der Wert innerhalb einer Liste der gültigen Werte ist.Reusing RSpec Verhalten Validierung

Jetzt werde ich genau die gleiche Spezifikation für ein anderes Feld haben, in einem anderen Modell mit einem anderen Satz gültiger Werte. Ich möchte den gemeinsamen Code extrahieren, anstatt ihn lediglich zu kopieren und einzufügen, indem ich die Variablen ändere.

Ich frage mich, ob dies der Fall wäre, ein geteiltes Beispiel oder andere RSpec Wiederverwendungstechnik zu verwenden.

Hier ist der relevante RSpec Code:

describe "validation" do 
    describe "#role" do 
    context "with a valid role value" do 
     it "is valid" do 
     User::ROLES.each do |role| 
      build(:user, :role => role).should be_valid 
     end 
     end 
    end 

    context "with an empty role" do 
     subject { build(:user, :role => nil) } 

     it "is invalid" do 
     subject.should_not be_valid 
     end 

     it "adds an error message for the role" do 
     subject.save.should be_false 
     subject.errors.messages[:role].first.should == "can't be blank" 
     end 
    end 

    context "with an invalid role value" do 
     subject { build(:user, :role => 'unknown') } 

     it "is invalid" do 
     subject.should_not be_valid 
     end 

     it "adds an error message for the role" do 
     subject.save.should be_false 
     subject.errors.messages[:role].first.should =~ /unknown isn't a valid role/ 
     end 
    end 
    end 
end 

Was wäre der beste Fall sein, diesen Code wiederverwenden, aber Rolle (das Feld überprüft wird) und User :: ROLES (die Sammlung von Extrahieren gültige Werte) in Parameter, die an diesen Code übergeben werden?

Antwort

2

Ich denke, das ist ein durchaus sinnvoller Anwendungsfall für gemeinsame Beispiele. z.B. so etwas wie dieses:

diese
describe "validation" do 
    describe "#role" do 
    behaves_like "attribute in collection", :role, User::ROLES 
    end 
end 

nicht getestet, aber ich denke, es sollte funktionieren:

shared_examples_for "attribute in collection" do |attr_name, valid_values| 

    context "with a valid role value" do 
    it "is valid" do 
     valid_values.each do |role| 
     build(:user, attr_name => role).should be_valid 
     end 
    end 
    end 

    context "with an empty #{attr_name}" do 
    subject { build(:user, attr_name => nil) } 

    it "is invalid" do 
     subject.should_not be_valid 
    end 

    it "adds an error message for the #{attr_name}" do 
     subject.save.should be_false 
     subject.errors.messages[attr_name].first.should == "can't be blank" 
    end 
    end 

    context "with an invalid #{attr_name} value" do 
    subject { build(:user, attr_name => 'unknown') } 

    it "is invalid" do 
     subject.should_not be_valid 
    end 

    it "adds an error message for the #{attr_name}" do 
     subject.save.should be_false 
     subject.errors.messages[attr_name].first.should =~ /unknown isn't a valid #{attr_name}/ 
    end 
    end 
end 

Dann Sie es in Ihren Angaben wie folgt aufrufen können.

+0

Erstaunlich, danke. – kolrie

2

Sie können Ihre spec mit shared_examples Technik auf diese Weise trocken:

shared_examples "no role" do 
    it "is invalid" do 
     subject.should_not be_valid 
    end 
    end 

    context "with an empty role" do 
    subject { Factory.build(:user, :name => nil) } 
    it_behaves_like "no role" 
    end 

    context "with an invalid role value" do 
    subject { Factory.build(:user, :name => '') } 
    it_behaves_like "no role" 
    end 

Aber was ist Ihre Idee paar specs..I denke, es ist zu viel trocken. Ich bin überzeugt, dass die Spezifikation zuerst lesbar sein muss und erst dann DRY'ing. Wenn Sie einige Spezifikationen löschen, wird es wahrscheinlich Kopfschmerzen für zukünftiges Lesen/Refactoring/Ändern dieses Codes geben.

+0

Einverstanden. Ich war auf der Suche nach einem guten Weg, es zu tun, oder jemand, der mir wirklich sagte, was du gerade getan hast. Ich werde kopieren und einfügen und kleine Stücke DRY. Vielen Dank. – kolrie

+0

Sollte das nicht 'shared_examples_for' und nicht' shared_examples' sein? –

+0

'shared_examples' wird funktionieren – alex

Verwandte Themen