見出し画像

ハッシュの配列は同値テストと相性がいいですよね。

.make_hash_list_in_array(list)

今日もポンコツ感満載の絶好調で行ってみます。

メソッドのテストで同値テストは欠かせません。
一つの結果が確認できれば、何度もテストする必要がないのですが、二つ以上の異なる結果が起こり得る場合、その度にテストを起こすのはちょいと面倒です。そんな時、ハッシュの配列が用意できれば、簡単です。
[{val: 1, result: 'OK'}, {val: 2, result: 'BAD'}, {val: 3, result: 'UNKNOWN'}]
こんな形式の奴です。
テストデータをシコシコ作るのも面倒なので、そんな時に作ったメソッド.make_hash_list_in_array(list)です。

class MyClass
  def something_method(asking_value)
    if asking_value == 1
      'OK'
    elsif asking_value == 2
      'BAD'
    elsif asking_value == 3
      'UNKNOWN'
    else
      'ERROR'
    end
  end
end

module TOOLS
  # for making the test data
  def make_hash_list_in_array(list)
    #  usage:
    #  before_value = [:before,   28.0 ,  26.3   ]
    #  update_value = [:update,  "28\n", "26.3\n"]
    #  after_value  = [:after ,   28   ,  26     ]
    #  list = [before_value, update_value, after_value]
    #  make_hash_list_in_array(list)
    #    ===> [{:before=>28.0, :update=>"28\n", :after=>28},
    #          {:before=>28.0, :update=>"26.3\n", :after=>26}]
    #  If you take a block variable, it becomes an individual hash, so you can add it
    #   eg.
    #   make_hash_list_in_array(list) {|h| h[:exp] = 'appendix'}
    #     ===> [{:before=>28.0, :update=>"28\n", :after=>28, :exp=> 'appendix' },
    #           {:before=>26.3, :update=>"26.3\n", :after=>26, :exp=> 'appendix' }]
    ary, *arys = *list
    key, *value = *ary.zip(*arys)
    values = value.map { |v| key.zip(v).to_h }
                  .to_a
    if block_given?
      values.map do |h|
        yield(h)
      end
    end
    values
  end
end

require 'minitest/autorun'
class MyClassTest < MiniTest::Test
  include TOOLS

  def setup
    @my_class = MyClass.new
  end

  def test_something_method_1
    # make_hash_list_in_array内に無理矢理ブロックを使った例です。
    arg_list = [:arg,         1,          2,          3,          4]
    exp_list = [:exp,         'OK',       'BAD',      'UNKNOWN',  'ERROR']
    index    = 0
    h_list   =
      make_hash_list_in_array([arg_list, exp_list]) do |h|
        # こんな感じでブロック内に追加のハッシュを生成できます。
        index    += 1
        h[:index] = index
      end

    h_list.each do |h|
      assert_equal h[:exp],
                   @my_class.something_method(h[:arg]),
                   "#{h[:index]}番目のテストが失敗しました"
    end
  end

  def test_something_method_2
    # .with_indexを使ったこちらのパターンの方が美しいですかね。
    arg_list = [:arg,         1,          2,          3,          4]
    exp_list = [:exp,         'OK',       'BAD',      'UNKNOWN',  'ERROR']
    h_list   = make_hash_list_in_array([arg_list, exp_list])

    h_list.each.with_index(1) do |h, index|
      assert_equal h[:exp],
                   @my_class.something_method(h[:arg]),
                   "#{index}番目のテストが失敗しました"
    end
  end
end

なんてことはない、しょぼいコードですが、案外重宝に使っています。

テストデータを作るのが楽なんです。

この例の場合だと、ifが1段の深さしかないので大したことないですが、2段、3段になるとロジックから次の別のロジックへと思考を切り替えながらデータを作っていくのは、おっさんには、しんどいんですわ。
この方法だと、同じ深さの同じロジックの中でテストデータを作っていけばいいので、後でハッシュの配列に作り直してしまえばお終いです。

お試しにどうぞ。

この記事が気に入ったらサポートをしてみませんか?