みなさんこんにちは!宮水です。
最近Rspecを書くことが多くなったので、改めて勉強することにしました。
Rspecとは
テストにも単体テストとか結合テストとか境界値テストとか命令網羅とか色々あると思うのですが、そもそもRspecってなんだろう...って思って自分で答えられなかったので調べてみました。
RSpec is a Behaviour-Driven Development tool for Ruby programmers. BDD is an approach
to software development that combines Test-Driven Development, Domain Driven Design,
and Acceptance Test-Driven Planning. RSpec helps you do the TDD part of that equation,
focusing on the documentation and design aspects of TDD.
RspecはBehaviour-Driven Developmentがテストできるツールで振る舞いをテストする、つまり仕様を中心にテストすることができるみたいです。(これは先輩が言っていたのですが、specって言葉自体が「仕様」って意味なんですね。)
ビヘイビア駆動開発:ビヘイビア駆動開発 - Wikipedia
Rspecを書いててよく迷うのは、「何をテストするべきか」です。
BDDについて理解すれば、「何をテストするべきか」「何をテストしないべきか」わかりやすくなるかもしれません。
以下のブログにTDDとBDDで書いたテストの考え方の例があってわかりやすかったです。
RSpecで始めるBDD | Hello, Stupid World!
例で言うと・・・
数字でない文字が渡された場合にエラーを返すクラスがあったとします。これをTDDで記述した場合、いくつかのテストメソッドが作られます。
数字だけの場合のテストメソッド、英字だけの場合のテストメソッド、
数字と英字がまじった場合のテストメソッドなど。
しかし、それらのテストメソッドはそれぞれ関連性がありません。BDDではまず振る舞いを記述します。
上記例で言うと、数値チェックを行うという振る舞いを記述し、その下に
各テストケースが記述されます。
つまり、各テストケースは数値チェックに対するものという関連性が
生まれます。
1個1個テストを書くんじゃなくて、「振る舞い」で複数のテストをグループ分けするんですね。
次にdescribeやcontextの使い分けです。先輩に教わりました。
describe で「検証の対象」を書く
context で「検証の条件」を書く
it で「期待される挙動」を書く(it を主語に見立てて動詞から書き始めるとベスト)
stub_env は before 内に書く
expect(…) の中には「検証の対象」を書き、 .to eq (…) の中には「期待される値」を書く
describeやcontextを適切に使い分けると、テストが読みやすくなりますね!
「RspecによるRailsテスト入門」
続いて、王道の以下の本を読みました。
Everyday Rails… Aaron Sumner 著 et al. [Leanpub PDF/iPad/Kindle]
Rspecで書けるテストの種類や、Rspecで使える機能について一通り学ぶことができました。
ざっと読んだだけなので、今後必要になったときに都度読み返そうと思います!
モデルスペック
- 能動形で書く
- 起きて欲しいことと起きて欲しくないことを書く
- 境界値テストをする
コントローラースペック
- 適切な形式(html, jsonなど)で返すか
- 認証、権限系
フィーチャースペック
- モデルとコントローラーが一緒にうまくいくかテストする(受け入れテスト・結合テスト)
- Capybara(ブラウザの操作シュミレートしてくれる)
- 環境変数を使いたいときはstub_envを使う
- webdriver:ブラウザと同じこと(サーバーにリクエストを送る、HTMLを受け取ってパースする、等)をサーバー上で行うためのソフトウェア。 Capybara はいくつかのソフトウェアの中からどれを使うか選ぶことができ、そのソフトウェアをdriverと呼ぶ。
- ヘッドレスドライバ:CIなどでテストを使いたい際に、テストをブラウザではなくCLIで行ってくれる。
beforeとlet
- beforeはdescribeやcontextを実行するたびに呼ばれる。
- letは呼ばれたときに初めて実行する。
- let!はその場で即座に実行される。
モックとスタブ
- モックは本物のオブジェクトのふりをするオブジェクト。データベースにアクセスしない。
- スタブは、ダミーメソッドのこと。
その他
Timecop難しいよね
Rspecのテストの中でも一番苦手なのは、日付が関係するテストです。
github.com
TimecopってRspec標準の機能ではなく、別のgemだったんですね...知らなかった。
Timecop.freezeとか使うと常に同じ時間でテストをすることができます。
今度から使い方がわからなくなったらこのドキュメントのUsageみよっと。