[英]How to test composite Rails model scopes?
考慮以下模型:
class Model < ActiveRecord::Base
scope :a, -> () { where(a: 1) }
scope :b, -> () { where(b: 1) }
scope :a_or_b, -> () { a.or(b) }
end
現在為了正確測試每個范圍,我至少會提供一個匹配的示例,而每個可能的變量都不匹配。 像這樣的東西:
RSpec.describe Model do
describe "scopes" do
describe ".a" do
subject { Model.a }
let!(:with_a_0) { create(:model, a: 0) }
let!(:with_a_1) { create(:model, a: 1) }
it { should_not include(with_a_0) }
it { should include(with_a_1) }
end
describe ".b" do
subject { Model.b }
let!(:with_b_0) { create(:model, b: 0) }
let!(:with_b_1) { create(:model, b: 1) }
it { should_not include(with_b_0) }
it { should include(with_b_1) }
end
describe ".a_or_b" do
subject { Model.a_or_b }
let!(:with_a_0_and_b_0) { create(:model, a: 0, b: 0) }
let!(:with_a_0_and_b_1) { create(:model, a: 0, b: 1) }
let!(:with_a_1_and_b_0) { create(:model, a: 1, b: 0) }
let!(:with_a_1_and_b_1) { create(:model, a: 1, b: 1) }
it { should_not include(with_a_0_and_b_0) }
it { should include(with_a_0_and_b_1) }
it { should include(with_a_1_and_b_0) }
it { should include(with_a_1_and_b_1) }
end
end
end
但是感覺就像我在.a_or_b
測試中重新測試.a
和.b
,如果我再次.a_or_b
它,使用另一個范圍,它會變得越來越大。
處理這個問題的明智方法是什么?
另外:這是單元測試還是集成測試?
這是一個艱難的。 我會說你必須在全面覆蓋和你的規范可讀性之間找到亞里士多德的平均值。 測試影響示波器行為方式的所有可能狀態的組合可能是不合理的。
它也不是真正的單元測試,因為它與 DB 層耦合。
我的方法是這樣的:
不要測試簡單的范圍(例如您的示例中的a
和b
),相信 AR 已經過良好測試,讓您的范圍名稱清晰並保留它。
在更復雜的范圍內,您可以顛倒編寫測試的方式:創建一次樣本,然后定義對不同范圍的期望(並使樣本名稱非常清晰,就像您已經在做的那樣)。
這將稍微減少規范的大小,並且更容易閱讀此類規范。 但是,如果您想對每個示波器進行全面覆蓋,它仍然會增加規格尺寸。
RSpec.describe Model do
describe "scopes" do
let!(:with_a_0_and_b_0) { create(:model, a: 0, b: 0) }
let!(:with_a_0_and_b_1) { create(:model, a: 0, b: 1) }
let!(:with_a_1_and_b_0) { create(:model, a: 1, b: 0) }
let!(:with_a_1_and_b_1) { create(:model, a: 1, b: 1) }
it { expect(described_class.a).to include(with_a_1_and_b_1).and include(with_a_1_and_b_1) }
it { expect(described_class.a).not_to include(with_a_0_and_b_0) }
# you get the idea
為了使這個^ 更具可讀性,我建議創建一個自定義 matcher ,您可以像這樣使用:
it do
expect(described_class.a)
.to retrieve(with_a_1_and_b_0, with_a_1_and_b_1)
.and not_retrieve(with_a_0_and_b_0, with_a_0_and_b_1)
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.