「EFFECTIVE TESTING WITH RSPEC 3: BUILD RUBY APPS WITH CONFIDENCE」の2章を読んだ

あとから自分で読み直せるように、ブログにまとめつつ読んでいます。

書くことから(From Writing)

あなたのSpecアウトプットをカスタマイズする(Customizing Your Specs' Output)

RSpecはほかのテストフレームワークと同様、大量のテストケースのために効率化されてるから、デフォルトでのアウトプットは詳細が隠されている。一度覗いてみよう。

フォーマットの過程(The Progress Formatter)

RSpec.describe 'A cup of coffee' do
  let(:coffee) { Coffee.new }

  it 'costs $1' do
    expect(coffee.price).to eq(1.00)
  end

  context 'with milk' do
    before { coffee.add :milk }

    it 'costs $1.25' do
      expect(coffee.price).to eq(1.25)
    end
  end
end

contextブロックは、いくつかのexampleをまとめ、それらのセットアップコードを共通にする。 今回の場合だと「ミルク有り(with milk)」だ。

contextとdescribeはエイリアスだ(同じ挙動だ)。 同じように使っても構いはしないけど、contextは「テストしているオブジェクトに対する変更のためのフレーズ」として使われることが多いかな。

今回の場合だと、「ミルク有り(with milk)」が「一杯のコーヒー(a cup of coffee)」を修飾しているね。

The Documentation Formatter

RSpecドキュメンテーションフォーマッターも持っている。試してみよう。 rspecの実行時に以下のパスを付けるんだ。

--format documentation(または単に -f d)

Failuresセクションに記載されているのは以下だ。

  • expectationの失敗
  • なにを求めていて、そして実際は何が得られたか
  • expectationが失敗したファイルとそれが何行目か

Syntax Highlighting

CodeRayというGemを使えばもっと見やすくなる。 RSpecは標準搭載しているけれど、もしハイライトが上手くいってなかったらインストールしよう。

遅いテストを確認する(Identifying Slow Example)

この本では、どうやってspecを早くすればいいか繰り返し説明する。 もし、遅いテストに出くわしたときは、以下のオプションが有効だ。

$ rspec --profile 2

これで遅いテストワースト2が表示されるよ。

必要のあるテストだけ走らせる(Running Just What You Need)

$ rspec -e milk -fd

このオプションで、「milk」という文字列が入ったexampleが実行される。

特定の失敗を走らせる(Running Specfic Failures)

失敗したとき、最後のコマンドをコピーして実行してみよう。

$ rspec ./spec/coffee_spec.rb:11

これで特定の失敗だけ走らせることができる。

もし君のテキストエディターにキーバインドがあるなら強力だから設定したほうがいい。 vimEmacsSublime Text、Atom、RubyMineなどはRSpec用のプラグインがある。

失敗したものを全てもう一度走らせる(Rerunning Everything That Failed)

設定は必要だけど、可能だ。

RSpec.configure do |config|
  config.example_status_persistence_file_path = 'spec/examples.txt'
end
$ rspec --only-failures

こうすれば、「失敗フラグ」を記載されたファイルが作成され、失敗したものだけを抽出できる。

さて、次は実際のspecファイルに手を加えることで、どの例を走らせるか操作する方法を説明する。

特定の例に焦点を当てる(Foucsing Specfic Example)

単純に f を加えればいい。

  • context は fcontext に
  • it は fit に
  • describe は fdescribeに

f は focused を表す(焦点を当てる)。

以下の設定も忘れないように。

RSpec.configure do |config|
  config.filter_run_when_matching(focus: true)
end

これで、fが付いたものだけテストが走る。 目立たなくて見逃しそうだと思ったら、以下でも構わない。

fcontext 'with milk' do # fを付けただけの例

context 'with milk', focus: true do #こちらでも結果は同じ

しかし、こういった変更はあくまでも一時的にしておこう。

最後には、fcontext を context に戻すのを忘れないように。

進行中の作業にマークを付ける(Marking Work in Progress)

BDDでは、途中で要件を足したくなったりする。 さきほどのケースに以下を加えてみよう。

    it 'is light in color' #色が明るい
    it 'is cooler than 200 degrees Fahrenheit' #華氏200度より冷たい

これらはPendingされる。

不完全な要件をマークする

コミットする前にこのようにマークしておこう。

pendingメソッドを使えば、コメントアウトを使わずに「進行中」を表現できる。

it 'is light in color' do
  pending 'color not implemted yet'
  expect(coffee.color).to be(:light)
end

pendingは実装が終わったら消しておこう。(特殊な色での失敗扱いになるからすぐに気づく)

コラム:inspectを実装すればデバッグしやすい

#<Coffee:0x00007f919e946100 @ingredients=[:milk]>は、インスタンスにinspectメソッドを実行した結果だから、Coffeeクラス内でそのメソッドを実装して読みやすくしておけばデバッグしやすいかもしれない。

他のコマンド

pendingの代わりにskipを使えば、その部分を無視する。

fit の代わりにxitを使えば、フォーカルする代わりにその部分を無視する。

まとめ

1章よりはサクっとまとめれたけどまだ長い…。 もっと端的にいこう。