RSpec 失败 - 日期比较
RSpec failing - date comparison
所以我有一个 RSpec 测试失败了,我确信这个测试是问题所在,因为从功能的角度来看它工作正常。
总之,end_time应该不是before_start的时候。保存模型后可以正常工作,只有 RSpec 失败,任何指针将不胜感激
chain_plan_spec.rb
# frozen_string_literal: true
# == Schema Information
#
# Table name: chain_plans
#
# id :bigint not null, primary key
# end_time :datetime
# start_time :datetime
# created_at :datetime not null
# updated_at :datetime not null
# faction_id :bigint not null
#
# Indexes
#
# index_chain_plans_on_faction_id (faction_id)
#
# Foreign Keys
#
# fk_rails_... (faction_id => factions.id)
#
require 'rails_helper'
RSpec.describe ChainPlan, type: :model do
it { is_expected.to validate_presence_of :start_time }
it { is_expected.to validate_presence_of :end_time }
it { is_expected.to validate_presence_of :faction }
it 'does not have a start date/time before an end date/time' do
cp = described_class.new
cp.start_time = Date.now
cp.end_time = cp.start - 1.minute
cp.save!
expect(cp).not_to be_valid
end
# TODO: end is 0 minute
# TODO start is 0 minute
end
chain_plan.rb
# frozen_string_literal: true
# == Schema Information
#
# Table name: chain_plans
#
# id :bigint not null, primary key
# end_time :datetime
# start_time :datetime
# created_at :datetime not null
# updated_at :datetime not null
# faction_id :bigint not null
#
# Indexes
#
# index_chain_plans_on_faction_id (faction_id)
#
# Foreign Keys
#
# fk_rails_... (faction_id => factions.id)
#
class ChainPlan < ApplicationRecord
belongs_to :faction
has_many :chain_plan_slots
validates :start_time, presence: { on: :create, message: "can't be blank" }
validates :end_time, presence: { on: :create, message: "can't be blank" }
validates :faction, presence: { on: :create, message: "can't be blank" }
validate :end_date_after_start_date?
private
def end_date_after_start_date?
return if end_time.blank? || start_time.blank?
errors.add(:end_date, 'must be after the start date') if end_time < start_time
end
end
我认为问题是 Date.now
,这不是一个正确的命令 - 至少从 documentation 我找不到 class now
的方法 Date
。请改用 Time.now
。这对我来说很好。
测试验证时不要使用 expect(object).not_to be_valid
或 expect(object).to be_valid
。这只是假阳性和假阴性的配方,因为您实际上并不是在测试单个行为 - 而是在测试设置时同时测试每一个验证。
RSpec.describe ChainPlan, type: :model do
it 'does not allow an end_time which is after the start_time' do
cp = described_class.new(
start_time: Time.current,
end_time: Time.current - 1.minute
)
cp.valid?
expect(cp.errors.messages_for(:end_time)).to include 'must be after the start date'
end
it "allows a valid start_time/end_time combo" do
cp = described_class.new(
start_time: Time.current,
end_time: Time.current.advance(10.minutes)
)
cp.valid?
expect(cp.errors).to_not have_key :end_date
end
end
而是设置对象,然后对其调用 valid?
以触发验证。在错误对象上写入期望以测试实际行为而不是地毯式轰炸。例如,在这里您会完全错过将错误添加到密钥 :end_date
而不是 :end_time
.
的地方
验证本身也可以改进:
class ChainPlan < ApplicationRecord
belongs_to :faction
has_many :chain_plan_slots
validates :start_time, presence: { on: :create, message: "can't be blank" }
validates :end_time, presence: { on: :create, message: "can't be blank" }
validates :faction, presence: { on: :create, message: "can't be blank" }
validate :end_date_after_start_date?, if: ->{ end_time.present? && start_time.present? }
private
def end_date_after_start_date?
errors.add(:end_time, 'must be after the start date') if end_time < start_time
end
end
所以我有一个 RSpec 测试失败了,我确信这个测试是问题所在,因为从功能的角度来看它工作正常。
总之,end_time应该不是before_start的时候。保存模型后可以正常工作,只有 RSpec 失败,任何指针将不胜感激
chain_plan_spec.rb
# frozen_string_literal: true
# == Schema Information
#
# Table name: chain_plans
#
# id :bigint not null, primary key
# end_time :datetime
# start_time :datetime
# created_at :datetime not null
# updated_at :datetime not null
# faction_id :bigint not null
#
# Indexes
#
# index_chain_plans_on_faction_id (faction_id)
#
# Foreign Keys
#
# fk_rails_... (faction_id => factions.id)
#
require 'rails_helper'
RSpec.describe ChainPlan, type: :model do
it { is_expected.to validate_presence_of :start_time }
it { is_expected.to validate_presence_of :end_time }
it { is_expected.to validate_presence_of :faction }
it 'does not have a start date/time before an end date/time' do
cp = described_class.new
cp.start_time = Date.now
cp.end_time = cp.start - 1.minute
cp.save!
expect(cp).not_to be_valid
end
# TODO: end is 0 minute
# TODO start is 0 minute
end
chain_plan.rb
# frozen_string_literal: true
# == Schema Information
#
# Table name: chain_plans
#
# id :bigint not null, primary key
# end_time :datetime
# start_time :datetime
# created_at :datetime not null
# updated_at :datetime not null
# faction_id :bigint not null
#
# Indexes
#
# index_chain_plans_on_faction_id (faction_id)
#
# Foreign Keys
#
# fk_rails_... (faction_id => factions.id)
#
class ChainPlan < ApplicationRecord
belongs_to :faction
has_many :chain_plan_slots
validates :start_time, presence: { on: :create, message: "can't be blank" }
validates :end_time, presence: { on: :create, message: "can't be blank" }
validates :faction, presence: { on: :create, message: "can't be blank" }
validate :end_date_after_start_date?
private
def end_date_after_start_date?
return if end_time.blank? || start_time.blank?
errors.add(:end_date, 'must be after the start date') if end_time < start_time
end
end
我认为问题是 Date.now
,这不是一个正确的命令 - 至少从 documentation 我找不到 class now
的方法 Date
。请改用 Time.now
。这对我来说很好。
测试验证时不要使用 expect(object).not_to be_valid
或 expect(object).to be_valid
。这只是假阳性和假阴性的配方,因为您实际上并不是在测试单个行为 - 而是在测试设置时同时测试每一个验证。
RSpec.describe ChainPlan, type: :model do
it 'does not allow an end_time which is after the start_time' do
cp = described_class.new(
start_time: Time.current,
end_time: Time.current - 1.minute
)
cp.valid?
expect(cp.errors.messages_for(:end_time)).to include 'must be after the start date'
end
it "allows a valid start_time/end_time combo" do
cp = described_class.new(
start_time: Time.current,
end_time: Time.current.advance(10.minutes)
)
cp.valid?
expect(cp.errors).to_not have_key :end_date
end
end
而是设置对象,然后对其调用 valid?
以触发验证。在错误对象上写入期望以测试实际行为而不是地毯式轰炸。例如,在这里您会完全错过将错误添加到密钥 :end_date
而不是 :end_time
.
验证本身也可以改进:
class ChainPlan < ApplicationRecord
belongs_to :faction
has_many :chain_plan_slots
validates :start_time, presence: { on: :create, message: "can't be blank" }
validates :end_time, presence: { on: :create, message: "can't be blank" }
validates :faction, presence: { on: :create, message: "can't be blank" }
validate :end_date_after_start_date?, if: ->{ end_time.present? && start_time.present? }
private
def end_date_after_start_date?
errors.add(:end_time, 'must be after the start date') if end_time < start_time
end
end