LoginSignup
24
11

More than 5 years have passed since last update.

rspec-parameterized ことはじめ

Last updated at Posted at 2018-12-11

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

実際のビジネスロジックに適用させるとどうなるか

こうなりました。
rspec-parameterizedを使って、RSpecをリファクタリングした話

24
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
11