新来的程序员。我是一名学生,我的项目是Reddit的克隆。目前我已经了解了RSPEC。我必须开始编写自己的模型测试,以便在进一步的练习中使用。有问题的模型没有创建,它将在下一次作业中创建。有人能检查一下我是否做对了吗?
在下一个检查点中,我们将添加一个Vote模型。这个模型将包含验证功能。包含验证确保aVote的value属性是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
如果你需要的话,至少可以用两种方法使它更清晰、更易读:
- 推出你自己的RSpec helper。
使用第三方库,这些库基本上包含了已经为您编写的帮助程序。他们会将您的验证码更改为如下内容:
describe Vote do it { is_expected.to validate_inclusion_of(:value).in_array([-1, 1]) } end
整洁,嗯?:)但我不认为这是你在这次练习中所期望的。
希望这对你有帮助!