scramble cadenza

技術ネタのガラクタ置き場

はじめまして rspec

始めは rspec 本を読んだり、テストコードを読んだりしたんですが、全く自分で書けるようにはならなかったんですよね(当たり前ですが)。
なんとなく読めるようにはなったけれど。

そこで「テスト読める」から「テスト書ける」の思考ギャップを埋めるための tips を書いてみました。
要するに「テスト描いてる人って、どういう風に考えてるの?」ということ。

自分はテスト書ける人のそばについて、テスト書いている人の独り言を聞いていたら、書けるようになりました。

  • テストそのものの概念は理解している
  • context とか、should とかわかるけど…
  • なんとなくテスト読めるけど、いざ自分が書くとなると…

という人が対象。
番号振ってあるところを一つづつ書いていけば、最後にはテストが書けてるはず。

1. 最初に何をテストすればよいかを明確化する

  1. describe を書く
    • クラス名とかモジュール名を書いておけば、とりあえずはOK
    • こうすると、後々 described_class メソッドとか使える
  2. subject を書く
    • subject の中ではメソッドが呼び出されているはず
      • をテストすればよいか、の「何」は結局のところ「メソッド」であるから。
    • subject に描いたブロックは、テスト空間内で 本当に実行されている として考える
      • テスト空間とは、rspec 中でのオブジェクト空間のこと。
      • テスト空間は最初はまっさらで、何もオブジェクトは存在しない。
      • だから必要なオブジェクトは、「自分で」定義して、環境を整える必要がある。
    • subject 中で実行した返り値 をこれからチェックすると考える
      • 中にブロックで複数行渡したら、複数行実行された最後の結果だけ考える。
    • 出力された結果(subject 実行後)ってどうなってればよいのか?を考える。
      • ファイルが path に置かれてればいいの?
      • あるインスタンスが、別の値になればいいの?
      • 何かの object を返せばいいの?
      • 別のメソッドが呼び出されていればいいの?
      • 1 が返ればいいの? nil が返ればいいの? 例外が投げられればいいの?

2. subject で定義した内容の前提条件を書いてく

  1. context を書く
    • 「場合分け」を書くことが多い。
      • context '引数が nil の場合' など。
    • 思いつかなかったら、とりあえずは context '正常系' と書いておく。
      • 必要じゃなかったら後で取り除けば良い。
  2. before, let, let! などを駆使して前提条件を書いていく
    • 予めこういうオブジェクトが必要とか(mock を使う)
    • 他のメソッドに依存している場合は、こういうメソッドが必要、とか(stub を使う)
    • let で定義したシンボルは メソッド であると理解する
      • 引数で与えたシンボルが、テスト中の他の場所で出てきた時、初めて let のブロックが評価される。
    • メソッドの引数は let でやったほうが都合がいい場合が多い
      • let を書き換えるだけで、異なる条件の引数をチェックできるから

3. マッチャーでチェック

  1. この場合はこうあるべき という subject の返り値を、should を使って書く。
    • should be_nil とか should == 'hoge' とか。
    • けど expect { }.to とかがナウい書き方。
  2. 同様にして context で更に色々なケースをチェックする
    • 正常系、異常系に分けて、さらにcontext を切るとスッキリする

それでも失敗したら?

一概には言えないけれど、自分が躓いた時、どういうことをしたらうまくいったか、という事を考えてみました。

  • 人に聞く
    • これに限る (でも人に聞ける環境であるとも限らない)
  • 前提条件を見直す
    • 特にテストそのものが実行されない場合は、ほとんどがこれに該当する。
    • 普段意識せずとも使っていた object が無かったりすると、当然テストは通らない
      • rails のモデルによっては、とあるカラムが必須だったり、validation があったりする。
      • こういうのもちゃんとチェックされる。
  • p メソッドを使いまくる
    • 王道中の王道。天下のプリントデバッグ
    • テスト中でも、テストする実装側でも p メソッドは有効。
    • テスト中に p を仕込んで、ちゃんと値が渡っていることを確かめたりできる。
    • p で出力できなかったら、そもそもこの前でコケてることがわかる。

完全主観で書いてみました。間違ってるところもあるかもしれません。
自分もまだまだ読みやすいテスト書いてるわけではないのですが、これからテストを書き始める誰かの参考になれば。