2015-05-16 2 views
6

Neuer Programmierer hier. Ich bin ein Student, der an meinem Projekt arbeitet, das ein Reddit-Klon ist. Zur Zeit wurde ich in RSPEC eingeführt. Ich muss anfangen, meine eigenen Model-Tests zu schreiben, um sie in weiteren Übungen zu verwenden. Das betreffende Modell wird nicht erstellt, es wird in der nächsten Zuweisung sein. Kann jemand bitte überprüfen, ob ich das richtig gemacht habe?Erster RSPEC-Test, sicherstellen, dass der Wert 1 oder -1 ist

In the next checkpoint, we'll add a Vote model. This model will feature an inclusion validation. Inclusion validation ensures that a vote's value attribute is either 1 or -1. If a vote is initialized with any other value, it will not save.

  1. Create VoteSpec:

spec/models/vote_spec.rb

describe Vote do 
    describe "validations" do 
    describe "value validation" do 
     it "only allows -1 or 1 as values" do 
     # your expectations here 
     end 
    end 
    end 
end 

Write a spec that asserts the validations work as expected.

Use RSpec's expect().to eq() syntax. As you may recall from the specs in the Ruby exercises, you can assert that something should equal false or true.

You won't be able to run the tests because we haven't generated the model we're testing.

Unten ist meine Implementierung:

describe Vote do 
    describe "validations" do 

    before do  
     2.times { @vote.create(value: 1) } 
     3.times { @vote.create(value: -1) } 
     2.times { @vote.create(value: 3) } 
    end 

    describe "value validation" do 
     it "only allows -1 or 1 as values" do 
     expect (@vote.value).to eq(-1) 
     end 

     it "only allows -1 or 1 as values" do 
     expect (@vote.value).to eq(1) 
     end 
    end 
    end 
end 

Mit freundlichen Grüßen.

Edit: Hier ist eine Überarbeitung:

describe Vote do 
    describe "validations" do 

    before do  
     2.times { Vote.create(value: 1) } 
     3.times { Vote.create(value: 0) } 
     2.times { Vote.create(value: 3) } 
    end 

    describe "value validation" do 
     it "only allows -1 as value" do 
     expect (@vote.value).to eq(-1) 
     end 
     it "only allows 1 as value" do 
     expect (@vote.value).to eq(1) 
     end 

     it "it prohibits other values" do 
     expect(@vote.value).to_not be_valid 
     end 
    end 
    end 
end 

Ich habe auch mit diesem Code versucht, die anfangs gearbeitet, aber nicht jetzt in der nächsten Einsatz:

require 'rails_helper' 

    describe Vote do 
    describe "value validation" do 

     it "allows -1" do 
     value = Vote.create(value: -1) 
     expect(value).to be_valid 
     end 

     it "allows +1" do 
     value = Vote.create(value: +1) 
     expect(value).to be_valid 
     end 

     it "prohibits other values" do 
     value = Vote.create(value: 0) 
     expect(value).to_not be_valid 
     end 

    end 
end 

▶ rspec spec 
...FFF 

Failures: 

    1) Vote value validation allows -1 
    Failure/Error: value = Vote.create(value: -1) 
    NoMethodError: 
     undefined method `update_rank' for nil:NilClass 
    # ./app/models/vote.rb:12:in `update_post' 
    # ./spec/models/vote_spec.rb:7:in `block (3 levels) in <top (required)>' 

    2) Vote value validation allows +1 
    Failure/Error: value = Vote.create(value: +1) 
    NoMethodError: 
     undefined method `update_rank' for nil:NilClass 
    # ./app/models/vote.rb:12:in `update_post' 
    # ./spec/models/vote_spec.rb:12:in `block (3 levels) in <top (required)>' 

    3) Vote value validation prohibits other values 
    Failure/Error: expect(value).to eq(false) 

     expected: false 
      got: #<Vote id: nil, value: 0, user_id: nil, post_id: nil, created_at: nil, updated_at: nil> 

     (compared using ==) 
    # ./spec/models/vote_spec.rb:18:in `block (3 levels) in <top (required)>' 

Finished in 0.30485 seconds (files took 3.28 seconds to load) 
6 examples, 3 failures 

Failed examples: 

rspec ./spec/models/vote_spec.rb:6 # Vote value validation allows -1 
rspec ./spec/models/vote_spec.rb:11 # Vote value validation allows +1 
rspec ./spec/models/vote_spec.rb:16 # Vote value validation prohibits other values 
+0

'@ vote.create' wird fehlschlagen' @ vote' existiert nicht. Ich denke du meinst "Vote.create". –

+0

Danke @AndyWaite Das macht Sinn. Ansonsten sieht mein Test gut aus? –

+0

Es gibt einige andere Probleme. Zum Beispiel überprüfen Ihre 'expect'-Anweisungen das gleiche Ergebnis, aber Sie erwarten in jedem Fall andere Werte. –

Antwort

3

In diesem etwas speziellen Fall Sie könnten einfach den absoluten Wert verwenden.

it "only allows -1 or 1 as values" do 
    expect (@vote.value.abs).to eq(1) 
end 
+0

Nichts Gutes dabei. Was passiert, wenn "Wert" in beiden Fällen "1" ist, wenn "1" und "-1" eingestellt sind? Dieser Test wird Ihnen nichts darüber sagen. Setzen Sie Logik nicht in Ihre Tests ein, es macht sie nur schwer zu verstehen und führt zu bösen Fehlern. – hakcho

+0

Dies ist eine gute Möglichkeit, dies zu testen – iGbanam

2

Sie können RSpec verwenden compound expectations mit or:

it "only allows -1 or 1 as values" do 
    expect (@vote.value).to eq(1).or eq(-1) 
end 
+0

Vielen Dank! Ich ziehe es vor, es so zu lesen. Würden Sie lesen: "Wenn eine Abstimmung mit einem anderen Wert initialisiert wird, wird sie nicht gespeichert." wie muss ich eine andere Aussage für diesen Test erstellen? –

1

Jonathan, nach Ihren Anweisungen, sollten Sie die Abstimmung zu speichern/zu validieren versuchen und sehen, ob das Ergebnis wahr oder falsch ist. Sie sollten auch let verwenden, um Ihren Code sauberer zu machen, und build, um sicherzustellen, dass die Abstimmung nicht gespeichert wird, bis Sie dies explizit tun. Hier ist, wie ich mit dieser Situation umgehen würde:

describe Vote do 
    describe "validations" do 
    let(:vote) { Vote.new(value: vote_value) } 

    context "when the value is 1" do 
     let(:vote_value) { 1 } 

     it "successfully saves" do 
     expect(vote.save).to eq(true) 
     end 
    end 

    context "when the value is -1" do 
     let(:vote_value) { -1 } 

     it "successfully saves" do 
     expect(vote.save).to eq(true) 
     end 
    end 

    context "when the value is 0" do 
     let(:vote_value) { 0 } 

     it "does not save" do 
     expect(vote.save).to eq(false) 
     end 
    end 
    end 
end 

Fühlen Sie sich frei diejenigen vote.save von vote.valid?

+0

Danke, dass Sie sich die Zeit genommen haben, mir zu helfen. Dieser Code ist für mich sehr lesenswert. Leider scheitert das auch, Fehler/Fehler: lasst (: vote) {Vote.build (value: vote_value)} NoMethodError: undefined Methode 'build 'für #

+0

Sorry, normalerweise benutze ich' build 'mit Fabrikmädchen, wenn ich das Objekt nicht erstellen möchte. Ich habe gerade den Code auf etwas aktualisiert, das jetzt funktionieren sollte, indem Sie 'Vote.new' – JSFernandes

+0

verwenden, möchten Sie vielleicht die Zeile für den Wert 0 ändern:" erfolgreich speichert "für" nicht speichern ". – floum

0

Es scheint mir, was zu Test zu ersetzen, ist bereits in der Aufgabe selbst:

This model will feature an inclusion validation. Inclusion validation ensures that a vote's value attribute is either 1 or -1. If a vote is initialized with any other value, it will not save.

Lassen Sie uns zu Fuß Schritt für Schritt:

describe Vote do 
    describe 'validations' do 
    it 'should treat -1 vote value as valid' do 
     # 1. Prepare the environment. That comes right from the task: we need 
     # to create a model with a vote value of -1. 
     # 2. Do something. Again, from the task: let's try saving it. 
     # 3. Verify the result. From the tasks again: it should save. 
    end 
    end 
end 

Jetzt wissen wir was zu tun, gehen wir und einige Code schreiben:

describe Vote do 
    describe 'validations' do 
    it 'should treat -1 vote value as valid' do 
     # 1. Prepare the environment. That comes right from the task: we need 
     # to create a model with a vote value of -1. 
     vote = Vote.new(value: -1) 

     # 2. Do something. Again, from the task: let's try saving it. 
     result = vote.save 
     # (according to ActiveRecord specifications `.save` returns 
     # `true` when it succeeds saving, and `false` otherwise. 

     # 3. Verify the result. From the tasks again: it should save. 
     expect(result).to be_true 
    end 

    it 'should treat 1 vote value as valid' do 
     # Prepare the environment 
     vote = Vote.new(value: 1) 
     # Do something 
     result = vote.save 
     # Verify the result 
     expect(result).to be_true 
    end 

    it 'should treat 0 vote value as invalid' do 
     # Prepare the environment 
     vote = Vote.new(value: 0) 
     # Do something 
     result = vote.save 
     # 3. Verify the result. From the task: it should *not* save. 
     expect(result).to be_false 
    end 
    end 
end 

Jetzt haben wir den Code, der Ihren Bedürfnissen entspricht: es überprüft das Modell.Es gibt ein paar Probleme mit ihm:

  • Es im Falle fehlschlagen wird es andere Validierungen neben dem value Feld
  • Es ist nicht die Art und Weise Spezifikationen geschrieben werden
  • Es ist ein wenig ausführliche

Lassen Sie uns Adresse diejenigen (ich werde die Kommentare Streifen):

describe Vote do 
    describe 'validations' do 
    let(:overrides) { { } } 
    let(:params) { { value: 1 }.merge(overrides) } # valid by default 
    subject { Vote.new(params).save } 

    context 'vote == -1 is valid' do 
     let(:overrides) { { value: -1 } } # override one parameter 
     it { is_expected.to be_true } 
    end 

    context 'vote == 1 is valid' do 
     let(:overrides) { { value: 0 } } 
     it { is_expected.to be_true } 
    end 

    context 'vote == 0 is invalid' do 
     let(:overrides) { { value: 0 } } 
     it { is_expected.to be_false } 
    end 
    end 
end 

Sie c eine machen dies noch sauberer und besser lesbar in mindestens zwei Möglichkeiten, sollten Sie es brauchen:

  1. Roll out Ihre eigenen RSpec Helfer.
  2. Verwenden Sie Bibliotheken von Drittanbietern, die im Wesentlichen solche Helfer enthalten, die bereits für Sie geschrieben wurden. Sie ändern Ihren Validierungsverifizierungscode in etwas wie:

    describe Vote do 
        it { is_expected.to validate_inclusion_of(:value).in_array([-1, 1]) } 
    end 
    

    Ordentlich, nicht wahr? :) Aber ich denke nicht, dass das in dieser Übung von dir erwartet wird.

Hoffe, das hilft!

Verwandte Themen