2015-05-16 6 views
6

Nowy programator tutaj. Jestem studentem pracującym nad moim projektem, który jest klonem Reddita. Obecnie jestem wprowadzony do RSPEC. Muszę zacząć pisać własne testy modelowe do wykorzystania w kolejnych ćwiczeniach. Model, o którym mowa, nie jest tworzony, będzie w następnym zadaniu. Czy ktoś może sprawdzić, czy zrobiłem to poprawnie?Pierwszy test RSPEC, upewnij się, że wartość wynosi 1 lub -1

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.

Poniżej jest moje wykonanie:

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 

poważaniem.

Edycja: Oto przegląd:

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 

Próbowałem również z tego kodu, który pracował na początku, ale teraz nie w następnym Zadanie:

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' zakończy się niepowodzeniem' @ vote' nie istnieje. Myślę, że masz na myśli "Vote.create". –

+0

Dzięki @AndyWaite Ma to sens. Poza tym, czy mój test wygląda dobrze? –

+0

Istnieje kilka innych problemów. Na przykład twoje instrukcje 'oczekiwać' sprawdzają ten sam wynik, ale spodziewasz się różnych wartości w każdym przypadku. –

Odpowiedz

3

W tym lekko konkretnym przypadku możesz po prostu użyć wartości bezwzględnej.

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

Nic dobrego w tym nie robi. Co się stanie, jeśli "wartość" będzie równa "1" w obu przypadkach, gdy ustawione na "1" i "-1"? Ten test niczego ci nie powie. Nie umieszczaj logiki w swoich testach, tylko utrudnia im rozumowanie i prowadzi do nieprzyjemnych błędów. – hakcho

+0

To jest dobry sposób na przetestowanie tego – iGbanam

2

Można użyć RSpec compound expectations z or:

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

Dziękujemy! Wolę to czytać w ten sposób. Czy przeczytałbyś "Jeśli głos zostanie zainicjowany z inną wartością, nie zostanie zapisany". jako konieczność stworzenia kolejnego oświadczenia na potrzeby tego testu? –

1

Jonathan, zgodnie z instrukcjami, należy próbować zapisać/potwierdzić głos i zobaczyć, czy wynik jest prawdziwe, czy fałszywe. Powinieneś również użyć kodu let, aby kod był czystszy i build, aby upewnić się, że głosowanie nie zostanie zapisane, dopóki tego nie zrobisz. Oto, jak bym sobie taką sytuację:

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 

krępuj się zastąpić te vote.save przez vote.valid?

+0

Dziękuję za poświęcenie czasu, aby mi pomóc. Ten kod jest dla mnie bardzo czytelny. Niestety to również się nie udaje, Niepowodzenie/Błąd: let (: głosuj) {Vote.build (value: vote_value)} NoMethodError: niezdefiniowana metoda 'build 'dla #

+0

Niestety, używam zazwyczaj' build 'z dziewczyną z fabryki, gdy nie chcę tworzyć obiektu. Właśnie zaktualizowałem kod do czegoś, co powinno teraz działać, używając 'Vote.new' – JSFernandes

+0

możesz chcieć zmienić linię dla wartości 0:" pomyślnie zapisuje "dla" nie zapisuje ". – floum

0

Wydaje mi się co do testu jest już w dziele samego:

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.

LET'S spacer krok po kroku:

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 

Teraz, gdy wiemy, co do zrobienia, chodźmy napisać kod:

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 

Teraz mamy kod, który odpowiada Twoim potrzebom: sprawdza poprawność modelu.Istnieje kilka problemów z tym:

  • To nie w przypadku istnieją inne walidacje, oprócz pola
  • value To nie jest droga specyfikacje są napisane
  • To trochę rozwlekły

adres Miejmy tych (ja rozebrać komentarze):

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 

Ty c spraw, aby był jeszcze bardziej czytelny i czytelny na co najmniej dwa sposoby, jeśli go potrzebujesz:

  1. Rozwiń własne helpery pomocnicze.
  2. Użyj bibliotek zewnętrznych, które zasadniczo zawierają już napisane dla Ciebie programy pomocnicze. Zmienią kod weryfikacyjny sprawdzania na taki, jak:

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

    Schludny, huh? :) Ale nie sądzę, że tego się od ciebie oczekuje w tym ćwiczeniu.

Mam nadzieję, że to pomoże!

Powiązane problemy