やりたいこと
配列の中に数値が格納されていて、数値の桁数が全て8桁であることを検証したい。というケースがありました。
allマッチャ
all
というマッチャで、配列の要素全てに対してマッチャを適用できるのですが、「数値の桁数が◯桁であること」を検証してくれるマッチャはないので、自分でなんとかしないといけませんでした。
mapで変換してから検証する
map
メソッドを使って、数値の配列を桁数の配列に変換し、all
マッチャに渡す方法。
it { expect(nums.map{|num|num.abs.to_s.size}).to all(eq 8) }
うーん…
なんだか気持ち悪い
ループで回してしまう
it '全ての数が8桁であること' do
nums.each do |num|
expect(num.abs.to_s.size).to eq 8
end
end
うーん…
大して変わらない
気持ち悪さの原因
どちらもexpect
に渡すのが、検証したい対象を変換したもの になっているのが気持ち悪さの原因のような気がします。
expect
には数値を渡して、マッチャが「マイナスを取って文字列にしたら長さが8であること」を検証してくれたらいいのになあ。と思っていました。
satisfyマッチャ
satisfy
というマッチャを見つけました。これはブロックを受け取って、そのブロックがtrueを返すことを検証してくれます。
辞書を引いてみると、(人を)満足させるとか**(要件を)満たす**という意味らしいです。
これを使えば気持ち悪くない書き方ができそうです。
it { expect(nums).to all(satisfy {|num| num.abs.to_s.size == 8 } ) }
ちょっと自然な感じになりました。
ただ、カッコが多くて見づらいのでブロックを分けます。
be_8_digits = -> num { num.abs.to_s.size == 8 }
it { expect(nums).to all(satisfy &be_8_digits) }
スッキリしました。
expect
の中が、検証すべき対象になったので、subject
でまとめてis_expected.to
することもできます。
まとめ
- expectの中には、テスト対象そのものを入れたい
- マッチャのために変換したものを入れると、意味が分かりづらくなる
- satisfyマッチャを使うとブロックを使って柔軟な検証ができる!
- expectの中が汚れないので気持ちが良い