プログラミング 美徳の不幸

Ruby, Rails, JavaScriptなどのプログラミングまとめ、解説、備忘録。

続 アンチrspec

私が初めてrspecを触ったのは2012年、当時は今より全然プログラミングができなかったので与えられた情報を素直に受け取り、「どうやらBDDとかテスト駆動開発アジャイルが流行ってるらしい」という理由でcucumberなどと一緒に触ってみました。

初めてテストを書くとき、いきなりインテグレーションテストとかいっても実はテストコード自体の開発にもけっこうなスキルが必要なので何を書いていいのかわからなくなります。当時は今よりテストコードのサンプルもなく、railsのcontrollerをどうテストしたらいいのか、specの中のディレクトリ構造はどうなっていればいいのかという状態でした。

私が本格的にrspecの手ほどきを受けたのは国内でrails力が非常に高いと評判のある会社なのですが、そこでは「rspecで書いたコードがログで出力したときに英語で仕様書のようになっていて、それがそのままコードを説明しているのが望ましい」と教えられました。

つまりこういうことです。

ちょっと最近全くrspecを書いていないのでこういう感じでよかったか覚えてないのですが

describe User do
  describe '#full_name' do
    context 'when user has first_name and last_name' do
      it 'should return a string which concatenated first_name and last_name' do
        expect(user.full_name).to eq 'hoge fuga'
      end
    end

    context 'when user has first_name but does not have last_name'  do
    end
  end
end

とかやるとログで
"User#full_name when user has first_name and last_name should return a string which concatenated first_name and last_name"

みたいな英語が出力されるわけですよ。

で、サイコーなのは論理的なカバレッジが100%ならばこのログがそのままメソッドを説明する意味になっているので、ログをpull requestなんかに貼っつけてやってplease review me!的な...


私もこういう思想を教わったとき、あぁなんてすばらしいんだろう、不思議なことにRSpecのコードが(不自然だけど)英語として出力されていく、カックイーみたいな気分になったものですが、実際やれば分かるんですがまともな英語にはならないし、無理やりまともな英語にしようとするとけっこう面倒なんですよ。

さらに、これやれば確実にわかるけどコンテクストのブロック、振る舞い(it)のブロックを1つずつ分けるのって現実的に超だるいし、実行速度もitごとにDBとかtruncateしてると遅くなるんですよね。そのくせexampleの数が増えるからテスト書いたなーっていう満足度は上がるっていう。。。


上の例だとこれでよくないすか?

test '#full_name' do
  assert_equal user1.full_name, "tanaka taro", 'first_nameとlast_nameが入ってたら連結して返す'
  assert_equal user2.full_name, 'tanaka', 'first_nameがないときはlast_nameだけ返す'
end

あぁなんてシンプルなんだろう。めんどくさいdescribeのブロックも、無理やり読み下せる英語を考える必要もない。だいいちこれもログで吐き出すメリットをあまり感じないので(failしたところだけ分かればいい)、rubyのコメントと'pattern1', 'pattern2'みたいなメッセージだけでも十分だと思う。


っていうこと言うと、先の会社の人から斧投げられそうなんだけど、どうだろう? テストコード自体がサービスの直接的成長にはならない以上、タイプ数ががくっと減るだけでもrspec捨てたほうがいいと思うけど。