Rspecでテストコードを書くとやたらめったらコードが長くなることがありますよね、ここではShared exampleを利用してコードを共有する(DRY)方法を紹介します。
※RSpecのバージョンはRspec3を想定しています。
例えばこんなテストコードがあるとします。
describe 'Unshared' do
let(:b){ true }
let(:i){ 1 }
let(:s){ 'hello' }
context 'in context 1' 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 2' 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
end
expect…箇所が完全にコピペですね、このような箇所はShared Exampleで一箇所にまとめることができます。
shared_examplesに共有化するテストコードを書いてit_behaves_likeで呼び出します。
describe 'SharedExamples' do
shared_examples "share me" 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
let(:b){ true }
let(:i){ 1 }
let(:s){ 'hello' }
context 'in context 1' do
it_behaves_like "share me"
end
context 'in context 2' do
it_behaves_like "share me"
end
end
Shared Exampleには変数やブロックの引数を渡すことができます。
変数を引数にするには”it_behaves_like <名前>”の後にカンマ区切りで指定します。
describe 'SharedExamples Args' do
shared_examples "share me" do |arg_b, arg_i, arg_s|
it "is true" do
expect(arg_b).to eq(true)
end
it "is 1" do
expect(arg_i).to eq(1)
end
it "is hello" do
expect(arg_s).to eq('hello')
end
end
context 'in context 1' do
it_behaves_like "share me", true, 1, 'hello'
end
context 'in context 2' do
it_behaves_like "share me", true, 1, 'hello'
end
end
“it_behaves_like <名前>”の後にdo-endブロックを指定すると、Shared Exampleにブロック引数が渡ります。
以下の例ではブロック引数内で変数の定義をしています。
describe 'SharedExamples Block' do
shared_examples "share me" 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
it_behaves_like "share me" do
let(:b){ true }
let(:i){ 1 }
let(:s){ 'hello' }
end
end
end