rspec-parameterizedとは
簡単なパラメータ化したデータのテスト(parameterized test)を書けるようにするgemです。
https://github.com/tomykaira/rspec-parameterized
事前準備
いつものようにGemfileに書いてbundle install
します。
Gemfile
group :test do
gem 'rspec-parameterized'
end
比較のために、FizzBuzzを例にして、普通のspecを書く
calculator.rb
module Calculator
def self.fizzbuzz(num)
if num % 15 == 0
"FizzBuzz"
elsif num % 3 == 0
"Fizz"
elsif num % 5 == 0
"Buzz"
else
num
end
end
end
calculator_spec.rb
require 'rails_helper'
RSpec.describe Calculator do
describe "fizzbuzz" do
subject { Calculator.fizzbuzz(num) }
context "when number is 1" do
let(:num) { 1 }
it { expect(subject).to eq 1 }
end
context "when number is 2" do
let(:num) { 2 }
it { expect(subject).to eq 2 }
end
context "when number is 3" do
let(:num) { 3 }
it { expect(subject).to eq "Fizz" }
end
context "when number is 4" do
let(:num) { 4 }
it { expect(subject).to eq 4 }
end
context "when number is 5" do
let(:num) { 5 }
it { expect(subject).to eq "Buzz" }
end
# 6..14 examples
context "when number is 15" do
let(:num) { 15 }
it { expect(subject).to eq "FizzBuzz" }
end
end
end
上記specを、rspec-parameterizedを使ってリファクタリングします。
####Nested Array Style
実際に、rspec-parameterizedを用いるとこのようになります。
calculator_spec.rb
require 'rails_helper'
RSpec.describe Calculator do
describe "fizzbuzz" do
subject { Calculator.fizzbuzz(num) }
where(:num, :answer) do
[
[1, 1],
[2, 2],
[3, "Fizz"],
[4, 4],
[5, "Buzz"],
# 6..14 examples
[15, "FizzBuzz"]
]
end
with_them do
it { expect(subject).to eq answer }
end
end
end
他にも、いくつか書き方があります。
Hash and Array Style
このとき、
[a, b]は
[1, 5],[1, 7],[1, 9]
[3, 5],[3, 7],[3, 9]
[5, 5],[5, 7],[5, 9]
の9パターンが実行されます。
(FizzBuzzだと良い例が書けませんでした...)
describe "Hash arguments" do
where(a: [1, 3, 5], b: [5, 7, 9])
with_them do
it { expect(a + b).to be_even }
end
end
Table Syntax Style (like Groovy spock)
・Ruby2.1以降である必要があります。
・using RSpec::Parameterized::TableSyntax
を書く必要があります。
using RSpec::Parameterized::TableSyntax
describe "fizzbuzz" do
subject { Calculator.fizzbuzz(num) }
where(:num, :answer) do
1 | 1
2 | 2
3 | "Fizz"
4 | 4
5 | "Buzz"
# 6..14 examples
15 | "FizzBuzz"
end
with_them do
it { expect(subject).to eq answer }
end
end
Verbose Syntax
describe "fizzbuzz" do
subject { Calculator.fizzbuzz(num) }
where do
{
"multiple of 3" => { num: 3, answer: "Fizz" },
"multiple of 5" => { num: 5, answer: "Buzz" },
"multiple of 15" => { num: 15, answer: "FizzBuzz" },
"not multiple of 3 and 5" => { num: 16, answer: 16 }
}
end
with_them do
it { expect(subject).to eq answer }
end
end
lambda parameter
describe "fizzbuzz" do
subject { Calculator.fizzbuzz(num) }
where(:num, :answer) do
[
[1, -> {should == 1}],
[2, -> {should == 2}],
[3, -> {should == "Fizz"}],
[4, -> {should == 4}],
[5, -> {should == "Buzz"}],
# 6..14 examples
[15, -> {should == "FizzBuzz"}]
]
end
with_them do
subject { Calculator.fizzbuzz(num) }
it { self.instance_exec(&answer) }
end
end
テストをpendingにしたい時
従来の記法の通り、xit使えばOKです。
with_them do
xit { expect(subject).to eq answer }
end