再現テストの話

テストコードで再現テストをしてから、bugfixするやつ。

不具合にテストを書いて立ち向かう - t-wadaのブログ

これうまく行ったら超気持ちいいけど、いつも気持ちいいとは限らないのでメモ。

バグのパターンがユニットテストとしてエッジすぎ

だいたい再現テストコードがエッジなパターンすぎて、
仕様を説明する助けとして不適切になってしまう。

describe 'somemethod' do
  subject { describe_class.new(params).somemethod }
  context 'A' do
   let(:params) { 'a' }
   it { is_expected.to eq ('A') }
  end

  context 'B' do
   let(:params) { 'b' }
   it { is_expected.to eq ('B') }
  end

  # 再現テストのコンテキストがハイコンテキスト
  context 'B and hogehogehoe' do
   let(:params) { 'a' }
   before do
     # ハイコンテキストな記述 
   end

   it { is_expected.to eq ('A') }
  end
end

↑この程度なら全然いいんだけど野生のコードはこんなのじゃすまない。

このままマスターに入れてマージすると、仕様を説明することを阻害するよなぁ的に。

しかし、マージしておかないと同じバグを繰り返すかもしれないので、対策としてそのハイコンテキストなテストを別ファイルに切り出したりしてる。

コンテキストやフィクチャでテストのファイル分ける

1つクラスに1つのテストファイルがデフォルトですが、
テストファイルがって大きくなってきたら、コンテキストやフィクスチャ、メソッド単位でテストファイルを分割しても問題ないわけです。

なので、コンテキストが揃わないケースでは、別ファイルにコンテキストを分けてしまう。

そうすれば、仕様のキャッチアップにはよりプリミティブな浅いコンテキストのテストケースを読めるようにしておく。

そして再現テストは別ファイルで自動テストされるようにしておく。

というわけです。

なんかうまくいかない時に選ぶ他の手段

その他にもこのケースには下記の対応方法があるけど、場合によってはこれらも選んじゃう。

まとめ

基本的にバグに対して再現テストを書いて立ち向かって見てるけど、、、、
書きあがったテストコードがぐちゃぐちゃしちゃうのが悩み。

ぐちゃぐちゃでもいいから、別ファイルにテストコードを分けてコミットして再現テスト -> 修正すると良さそう。

そのやり方も万能じゃない。

そもそも再現テスト書いて、不具合に立ち向かうのをサボりたくなるときもある。