RSpec実装方針+テストで使用したgem紹介+詰まりポイントメモ
RSpecでテストを書く時のメモ
実装方針、使用するgemはなんなのか、詰まりポイントなどメモとして残します。
実装方針
- 基本的にrequest specを書く
- model, formなど必要に応じて
- controllerは基本的に書かない、request specで担保
- カバレッジ100%にする
- simplecovで計測
実装進め方
- API作成
- RSpec作成
- 作成したテストが全てsuccessになることを確認
- simplecovで修正ファイルがカバレッジ100%か確認
- RuboCopが通ることを確認
- CircleCIで全体のテストが全てsuccessになることを確認
テストするべき点
- ステータスコード、エラーメッセージ確認
- レコード
- 作成されること
- テーブルのレコードが増えていることを確認
- 作成したレコードが存在することを確認
- 更新されること
- 各値がA→Bに変わっているか確認
- 削除されること
- テーブルのレコードが減っていることを確認
- 削除したレコードが存在しないことを確認
- rollbackされること
- レコードの変更が行われていないことを確認
- レスポンス bodyが正しく出力されているか
RSpec書き方
- let、beforeでテストに必要なデータの準備をする
- describeでテストの対象を分ける
- contextでテストの条件を分ける
- itで状態がどうなるか書く
便利なGem
rspec-request_describer
describeの文字列から自動でsubjectを定義してくれます
describe 'POST /user/setting' do
# post('/user/setting')
- is_expected またはsubjectを呼び出すだけでリクエストを送ってくれます
- パラメータの設定はlet(:params)を設定するだけです
FactoryBot
テストデータの作成に使われる
FactoryBot.define do
factory :users do
name { 1 }
end
end
create(:users)
Faker
ダミーデータを生成してくれる
Faker::Internet.mac_address => "85:d7:54:4f:68:c3"
Timecop
時間操作ができる。時間依存のテストの時に使える。特定の日時にしたり、止めたり
Timecop.travel(Time.now + 1.years)
=> 2015-12-01 10:46:23 +0900
Database Rewinder
テスト後にデータベースのレコードを削除してくれる
rspec-json_matcher
jsonの検証で正規表現やオブジェクトクラスで検証など詳細にできるようになります
過去にハマったテストパターン
期待する値は決め打ちで書いたほうがよいこともある
以下の例だが
mobile_phoneはnilで来る想定ではなかったが実はnilになっててテストが通ってしまってたということが起きていた
expect_response_body.to be_json_as(
success: true,
mobile_phone: user.mobile_phone, NG
mobile_phone: '012-3456-7890' OK
)
全てそうしろというわけではないが、変数使うにしろどのような値が渡っているのか目視確認した方がよい
Aws.configやlocaleなどシステムの設定をテストで変更する場合
- 設定はロールバックされないので他のテストに影響がでます。afterなどで元に戻すか、変更しなくて良い実装にしましょう
時間に依存するテスト
- Timecopを使用してテストを行う
- timeの比較で一見同じ時間同士の比較なのに一致しないことがあります。ミリ秒が含まれている可能性があるので注意
たまに落ちるテスト
- 特定の条件下で稀に落ちるテストがあるので、発見し次第バックログに積むこと
- 対象のCircleCIのURL
- ローカルの場合エラーログ、あればseed番号