ruby on rails -第一个RSPEC测试,确保值为1或-1



新来的程序员。我是一名学生,我的项目是Reddit的克隆。目前我已经了解了RSPEC。我必须开始编写自己的模型测试,以便在进一步的练习中使用。有问题的模型没有创建,它将在下一次作业中创建。有人能检查一下我是否做对了吗?

在下一个检查点中,我们将添加一个Vote模型。这个模型将包含验证功能。包含验证确保aVote的value属性是1或-1。如果一个投票被初始化如果是其他值,则不会保存

  1. 创建VoteSpec:

规范/模型/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练习中,您可以断言某些东西应该等于false还是真实的。

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

下面是我的实现:
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

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

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

您可以使用RSpec复合期望与or:

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

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?

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

该模型将以包含验证为特征。包含验证确保投票的值属性为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 helper。
  2. 使用第三方库,这些库基本上包含了已经为您编写的帮助程序。他们会将您的验证码更改为如下内容:

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

    整洁,嗯?:)但我不认为这是你在这次练习中所期望的。

希望这对你有帮助!

相关内容

  • 没有找到相关文章

最新更新