Ruby on rails rspec型号规格与工厂规格
我从测试开始,不清楚什么时候应该使用Ruby on rails rspec型号规格与工厂规格,ruby-on-rails,rspec,factory-bot,Ruby On Rails,Rspec,Factory Bot,我从测试开始,不清楚什么时候应该使用let 我应该在下面的延迟加载模型测试中使用let,还是因为每次测试的数据都有点不同,所以我可以保持原样?正如我在一些示例中看到的,控制器测试更重要,因为每个动作测试的:任务都是相同的 模型规格 require 'rails_helper' RSpec.describe Task, type: :model do describe "model validations" do it "has a valid factory" do
let
我应该在下面的延迟加载模型测试中使用let
,还是因为每次测试的数据都有点不同,所以我可以保持原样?正如我在一些示例中看到的,控制器测试更重要,因为每个动作测试的:任务都是相同的
模型规格
require 'rails_helper'
RSpec.describe Task, type: :model do
describe "model validations" do
it "has a valid factory" do
expect(build(:task)).to be_valid
end
it "is invalid without executor" do
expect(build(:task, executor_id: nil)).not_to be_valid
end
it "is invalid without assigner" do
expect(build(:task, assigner_id: nil)).not_to be_valid
end
it "is invalid without content" do
expect(build(:task, content: nil)).not_to be_valid
end
it "is invalid without deadline" do
expect(build(:task, deadline: nil)).not_to be_valid
end
it "is invalid with deadline in the past" do
expect(build(:task, deadline: Faker::Time.between(DateTime.now - 1, DateTime.now - 2))).not_to be_valid
end
end
end
工厂
FactoryGirl.define do
factory :task do
content { Faker::Lorem.sentence }
deadline { Faker::Time.between(DateTime.now + 2, DateTime.now + 3) }
association :executor, factory: :user
association :assigner, factory: :user
end
end
我建议您保持现有状态,不要使用let
。别担心考试会干涸。它们彼此不交互,因此您不会遇到应用程序逻辑中的代码复制问题
您可以使用shoulda matchers
gem实现您的目标:
我建议您保持现有状态,不要使用let
。别担心考试会干涸。它们彼此不交互,因此您不会遇到应用程序逻辑中的代码复制问题
您可以使用shoulda matchers
gem实现您的目标:
的好处是让
来自于不是您上面使用的形式的测试。想象一下这个群体:
context "completing tasks" do
let(:completing_a_task){ task.complete }
context "that aren't due yet" do
let(:task){ create(:not_due_task) }
it "should not send an email" do
expect( TaskMailer ).not_to receive(:deliver_message)
expect{ completing_a_task }.not_to raise_error
end
end
context "overdue" do
let(:task){ create(:overdue_task) }
it "should send an email" do
expect( TaskMailer ).to receive(:deliver_message)
expect{ completing_a_task }.not_to raise_error
end
end
end
通过允许后期绑定,您可以进行最小的更改,但提供最大的覆盖率。为了设置测试所需的适当行为,您需要的合作者越多,您就越有可能从let
中获益。虽然您不需要在测试套件中特别驾驶,但测试的巨大设置块是一种气味,let
技术是一种很好的工具,即使在您的领域呈现复杂性的情况下,也可以帮助您争取清晰和简单。我自己的例子中还没有合作者,但希望这个概念仍然足够清晰。让
的好处来自于不是您上面使用的形式的测试。想象一下这个群体:
context "completing tasks" do
let(:completing_a_task){ task.complete }
context "that aren't due yet" do
let(:task){ create(:not_due_task) }
it "should not send an email" do
expect( TaskMailer ).not_to receive(:deliver_message)
expect{ completing_a_task }.not_to raise_error
end
end
context "overdue" do
let(:task){ create(:overdue_task) }
it "should send an email" do
expect( TaskMailer ).to receive(:deliver_message)
expect{ completing_a_task }.not_to raise_error
end
end
end
通过允许后期绑定,您可以进行最小的更改,但提供最大的覆盖率。为了设置测试所需的适当行为,您需要的合作者越多,您就越有可能从
let
中获益。虽然您不需要在测试套件中特别驾驶,但测试的巨大设置块是一种气味,let
技术是一种很好的工具,即使在您的领域呈现复杂性的情况下,也可以帮助您争取清晰和简单。我自己的例子中还没有合作者,但希望这个概念仍然足够清晰。Nick,我使用的是shoulda matchers,只是没有在这里复制代码。据我所知,这些只是检查验证的存在。使用这段代码,我想确保我的工厂和对象工作正常。@SzilardMagyar应该使用matchers
检查大部分值,而不是验证是否存在。例如,如果使用的是validate\u presence\u of
,则可以跳过内置的Rails presence validator并自行重新创建它(错误。如果content.blank?
,则添加(:content,“不能为空”)。而shoulda matcher将按预期工作。您可以在源代码中看到它检查实际的空白值:Nick,我使用的是shoulda matchers,只是没有在这里复制代码。据我所知,这些只是检查验证的存在。使用这段代码,我想确保我的工厂和对象工作正常。@SzilardMagyar应该使用matchers
检查大部分值,而不是验证是否存在。例如,如果使用的是validate\u presence\u of
,则可以跳过内置的Rails presence validator并自行重新创建它(错误。如果content.blank?
,则添加(:content,“不能为空”)。而shoulda matcher将按预期工作。您可以在源代码中看到它对照实际的空白值进行检查:Jim,您也可以用factory复制此代码以准确地看到差异吗?@SzilardMagyar Factorys实现了一个完全不同的目标。工厂的工作是提供域对象(并可能将它们持久化到数据库)。您在上面编写的这一节测试与我为我的一个应用程序中的每个有意义的模型编写的测试基本相同。我的let
语句经常包含工厂输出本身,或在工厂创建的对象上调用的域方法。希望有帮助!吉姆,例如,我没有看到你使用来自let(:task){create(:not_due_task)}
或来自'let(:task){create(:过期任务)}的任务,所以不要真正理解你的例子。@SzilardMagyar,我明白了!测试确实包含完成任务的,该任务本身在let
中定义。由于let的后期绑定特性,在运行示例时,not-due任务将在completing a_task
中接收.complete
调用。这是答案的本质;您不需要按顺序设置,而是在浏览上下文时进行合成和调整。你自己试试看。谢谢吉姆!你也可以看看这个吗?:?吉姆,你也可以用工厂复制这段代码来准确地看到差异吗?@SzilardMagyar工厂实现了一个完全不同的目标。工厂的工作是提供域对象(并可能将它们持久化到数据库)。您在上面编写的这一节测试与我为我的一个应用程序中的每个有意义的模型编写的测试基本相同。我的let
语句经常包含工厂输出本身,或在工厂创建的对象上调用的域方法。希望有帮助!吉姆,例如,我没有看到你使用来自let(:task){create(:not_due_task)}
或来自'let(:task){create(:过期任务)}的任务,所以不要真正理解你的例子。@SzilardMagyar,我明白了!该测试确实包含com