首次RSPEC测试,确保值为1或-1

时间:2015-05-16 22:07:54

标签: ruby-on-rails ruby rspec

新程序员在这里。我是一名正在研究Reddit克隆项目的学生。目前我已被介绍给RSPEC。我必须开始编写自己的模型测试以用于进一步的练习。有问题的模型没有创建,它将在下一个任务中。有人可以检查一下我是否做得正确吗?

  

在下一个检查点,我们将添加一个投票模型。这个模型会   以包含验证为特色。包含验证确保a   vote的value属性为1或-1。如果投票已初始化   除了任何其他值,它将无法保存。

     
      
  1. 创建VoteSpec:
  2.   

规格/模型/ 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
  

编写一个断言验证的规范按预期工作。

     

使用RSpec的expect()。到eq()语法。你可能还记得中的规格   在Ruby练习中,你可以断言某些东西应该等于假   或者是真的。

     

您将无法运行测试,因为我们没有   生成了我们正在测试的模型。

以下是我的实施:

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

最好的问候。

编辑:这是一个修订版:

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

我也试过这个代码,它起初工作但现在在下一个任务中失败了:

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

4 个答案:

答案 0 :(得分:3)

在这个稍微特殊的情况下,您可以使用绝对值。

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

答案 1 :(得分:2)

您可以将RSpec compound expectationsor一起使用:

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

答案 2 :(得分:1)

Jonathan,根据您的指示,您应该尝试保存/验证投票,看看结果是真还是假。您还应该使用let来使代码更清晰,并使用build以确保在您明确这样做之前不会保存投票。以下是我将如何处理这种情况:

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

可以vote.save

随意替换vote.valid?

答案 3 :(得分:0)

在我看来,测试的内容已经在任务本身中了:

  

此模型将包含包含验证。包含验证可确保投票的值属性为1或-1。如果使用任何其他值初始化投票,则不会保存。

让我们一步一步走:

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

现在我们知道该怎么做了,让我们去写一些代码:

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

现在我们有适合您需求的代码:它验证模型。它有几个问题:

  • 除了value字段
  • 之外,如果有任何其他验证,它将失败
  • 这不是规范的编写方式
  • 有点冗长

让我们解决这些问题(我将删除评论):

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

如果需要,您可以通过至少两种方式使其更清晰,更易读:

  1. 推出自己的RSpec助手。
  2. 使用第三方库,它们基本上包含已经为您编写的帮助程序。他们会将您的验证验证码更改为:

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

    干净,对吧? :)但我不认为这是你在本练习中所期望的。

  3. 希望这有帮助!