はじめまして rspec
始めは rspec 本を読んだり、テストコードを読んだりしたんですが、全く自分で書けるようにはならなかったんですよね(当たり前ですが)。
なんとなく読めるようにはなったけれど。
そこで「テスト読める」から「テスト書ける」の思考ギャップを埋めるための tips を書いてみました。
要するに「テスト描いてる人って、どういう風に考えてるの?」ということ。
自分はテスト書ける人のそばについて、テスト書いている人の独り言を聞いていたら、書けるようになりました。
- テストそのものの概念は理解している
- context とか、should とかわかるけど…
- なんとなくテスト読めるけど、いざ自分が書くとなると…
という人が対象。
番号振ってあるところを一つづつ書いていけば、最後にはテストが書けてるはず。
1. 最初に何をテストすればよいかを明確化する
- describe を書く
- クラス名とかモジュール名を書いておけば、とりあえずはOK
- こうすると、後々 described_class メソッドとか使える
- subject を書く
- subject の中ではメソッドが呼び出されているはず
- 何 をテストすればよいか、の「何」は結局のところ「メソッド」であるから。
- subject に描いたブロックは、テスト空間内で 本当に実行されている として考える
- テスト空間とは、rspec 中でのオブジェクト空間のこと。
- テスト空間は最初はまっさらで、何もオブジェクトは存在しない。
- だから必要なオブジェクトは、「自分で」定義して、環境を整える必要がある。
- subject 中で実行した返り値 をこれからチェックすると考える
- 中にブロックで複数行渡したら、複数行実行された最後の結果だけ考える。
- 出力された結果(subject 実行後)ってどうなってればよいのか?を考える。
- ファイルが path に置かれてればいいの?
- あるインスタンスが、別の値になればいいの?
- 何かの object を返せばいいの?
- 別のメソッドが呼び出されていればいいの?
- 1 が返ればいいの? nil が返ればいいの? 例外が投げられればいいの?
- subject の中ではメソッドが呼び出されているはず
2. subject で定義した内容の前提条件を書いてく
- context を書く
- 「場合分け」を書くことが多い。
- context '引数が nil の場合' など。
- 思いつかなかったら、とりあえずは context '正常系' と書いておく。
- 必要じゃなかったら後で取り除けば良い。
- 「場合分け」を書くことが多い。
- before, let, let! などを駆使して前提条件を書いていく
- 予めこういうオブジェクトが必要とか(mock を使う)
- 他のメソッドに依存している場合は、こういうメソッドが必要、とか(stub を使う)
- let で定義したシンボルは メソッド であると理解する
- 引数で与えたシンボルが、テスト中の他の場所で出てきた時、初めて let のブロックが評価される。
- メソッドの引数は let でやったほうが都合がいい場合が多い
- let を書き換えるだけで、異なる条件の引数をチェックできるから
3. マッチャーでチェック
- この場合はこうあるべき という subject の返り値を、should を使って書く。
- should be_nil とか should == 'hoge' とか。
- けど expect { }.to とかがナウい書き方。
- 同様にして context で更に色々なケースをチェックする
- 正常系、異常系に分けて、さらにcontext を切るとスッキリする
それでも失敗したら?
一概には言えないけれど、自分が躓いた時、どういうことをしたらうまくいったか、という事を考えてみました。
- 人に聞く
- これに限る (でも人に聞ける環境であるとも限らない)
- 前提条件を見直す
- 特にテストそのものが実行されない場合は、ほとんどがこれに該当する。
- 普段意識せずとも使っていた object が無かったりすると、当然テストは通らない
- rails のモデルによっては、とあるカラムが必須だったり、validation があったりする。
- こういうのもちゃんとチェックされる。
- p メソッドを使いまくる
- 王道中の王道。天下のプリントデバッグ
- テスト中でも、テストする実装側でも p メソッドは有効。
- テスト中に p を仕込んで、ちゃんと値が渡っていることを確かめたりできる。
- p で出力できなかったら、そもそもこの前でコケてることがわかる。
完全主観で書いてみました。間違ってるところもあるかもしれません。
自分もまだまだ読みやすいテスト書いてるわけではないのですが、これからテストを書き始める誰かの参考になれば。