配列メソッド呼び出し shared_example: 小林研 Rails Tips (16)

はじめに

Rails Tips の 16 回目です。連日の model のテストを簡単に書くための shared_example の紹介の続きです。私の Shared example の雛形 (lib/templates/rspec/model/model_spec.rb)を一つずつ解説していく形でした。今回は model 編の最終回です。

#  context "複数の <%= class_name %> オブジェクトについて" do
#    let!(:targets) { <%= plural_table_name %>(*%i[foo bar baz]) }
#    subject { targets }

#    it_behaves_like "配列メソッド呼び出し" do
#      let(:test_set) do
#        {
#            foo: [nil, [true, false, true]],
#        }
#      end
#    end
#  end

配列メソッド呼び出し

今日は「配列メソッド呼び出し」になります。以前、単一メソッド呼び出しを紹介しましたが、こちらは配列のすべての要素に対して同じメソッドを呼び出し、その返り値を配列で比較するものになります。ここでは年度 (year) モデルの 5 つのオブジェクトを subject にして、それらに対して test_set のキーで示されたメソッドを呼び出します。バリューは単一メソッド呼び出しと同じで、引数と結果のペアが並んでいます。当然ながら結果は subject で示した配列と同サイズの配列になります。

context "複数の #{described_class} オブジェクトについて" do
    subject { targets }
    let!(:targets) { years(:y2017, :y2018, :y2019, :y2020, :y2021) }
    it_behaves_like "配列メソッド呼び出し" do
      let(:test_set) do
        {
          ewareki: [nil, (29..31).map { |n| "H#{n}" } + (2..3).map { |n| "R#{n}" }],
          wareki: [nil, (29..31).map { |n| "平成#{n}" } + (2..3).map { |n| "令和#{n}" }],
          wareki_nendo: [nil, (29..31).map { |n| "平成#{n}年度" } + (2..3).map { |n| "令和#{n}年度" }],
          start_day: [nil, (2017..2021).map { |n| Date.new(n, 4, 1) }],
          last_day: [nil, (2018..2022).map { |n| Date.new(n, 3, 31) }],
          sangi_only?: [nil, [true] * 5],
        }
      end
    end

最初の「配列メソッド呼び出し」の shared_example は以下のようになります。subject でメソッドで mapping したものと、結果を比較するだけです。

shared_examples_for "配列メソッド呼び出し" do
  it "上述のメソッドの結果が正しいこと" do
    test_set.each do |method, answers|
      print "\tamst: #{method}\n" if documentation_formatter?
      answers.each_slice(2) do |(v, a)|
        expect(subject.map { |o| o.send(method, *v) }).to eq a
      end
    end
  end
end

正しく動作させるための実装

ここは単にそれぞれの year のインスタンスメソッドの実装なので省略します。

おわりに

これまでモデルに関するテストをまとめて説明してきました。次は、これから説明しようと思っている request_spec でいくつか使っている locales 関係のヘルパメソッドを先に説明したいと思います。