Rspecでテストコードを書くとやたらめったらコードが長くなることがありますよね、ここではShared contextを利用してコードを共有する(DRY)方法を紹介します。
※RSpecのバージョンはRspec3を想定しています。
例えばこんなテストコードがあるとします。
describe 'Unshared' do
context 'in context 1' do
let(:b){ true }
let(:i){ 1 }
let(:s){ 'hello' }
it "is true" do
expect(b).to eq(true)
end
it "is 1" do
expect(i).to eq(1)
end
it "is hello" do
expect(s).to eq('hello')
end
end
context 'in context 2' do
let(:b){ true }
let(:i){ 1 }
let(:s){ 'hello' }
it "is true" do
expect(b).to eq(true)
end
it "is 1" do
expect(i).to eq(1)
end
it "is hello" do
expect(s).to eq('hello')
end
end
end
例えばlet…の箇所を共有化する場合、shared_contextとinclude_contextを使用してlet…箇所を切り出すことが可能です。
以下のようになります。
shared_context "share me context" do
let(:b){ true }
let(:i){ 1 }
let(:s){ 'hello' }
end
describe 'Shared context' do
context 'in context 1' do
include_context "share me context"
it "is true" do
expect(b).to eq(true)
end
it "is 1" do
expect(i).to eq(1)
end
it "is hello" do
expect(s).to eq('hello')
end
end
context 'in context 2' do
include_context "share me context"
it "is true" do
expect(b).to eq(true)
end
it "is 1" do
expect(i).to eq(1)
end
it "is hello" do
expect(s).to eq('hello')
end
end
end
前出のShared Exampleと組み合わせると、以下のようになりますね
shared_context "share me context" do
let(:b){ true }
let(:i){ 1 }
let(:s){ 'hello' }
end
describe 'Shared context and example' do
shared_examples "share me example" do
it "is true" do
expect(b).to eq(true)
end
it "is 1" do
expect(i).to eq(1)
end
it "is hello" do
expect(s).to eq('hello')
end
end
context 'in context 1' do
include_context "share me context"
it_behaves_like "share me example"
end
context 'in context 2' do
include_context "share me context"
it_behaves_like "share me example"
end
end
Shared Example同様引数も渡せるようです。
shared_context "share me context" do |arg_b, arg_i, arg_s|
let(:b){ arg_b }
let(:i){ arg_i }
let(:s){ arg_s }
end
describe 'Shared context and example args' do
shared_examples "share me example" do
it "is true" do
expect(b).to eq(true)
end
it "is 1" do
expect(i).to eq(1)
end
it "is hello" do
expect(s).to eq('hello')
end
end
context 'in context 1' do
include_context "share me context", true, 1, 'hello'
it_behaves_like "share me example"
end
context 'in context 2' do
include_context "share me context", true, 1, 'hello'
it_behaves_like "share me example"
end
end