Zenn
Open13

Everyday Rails - RSpec による Rails テスト入門を読んで

うだななうだなな

we don’t recommend adding the rails-controller-testing gem to your application. The official recommendation of the Rails team and the RSpec core team is to write request specs instead

Rails5からcontrollerのテストは非推奨

コントローラスペックは、コントローラの内部ロジックに焦点を当てていますが、ルーティングやミドルウェアの影響を受けないため、実際のアプリケーションの動作を完全には再現できません。

うだななうだなな

.rspec で、テスト結果を見やすくするなどの設定を記述する

--require spec_helper
--format documentation
うだななうだなな

binstub を使うかどうかは任意

使う場合は bin/rspec で起動
使わない場合は bundle exec rspec で起動

うだななうだなな

UI 関連のテストは統合テストに任せようとしています。これは Rails 開発者
の中では標準的なプラクティスです。

うだななうだなな

3. モデルスペック

バリデーションのテストケースでは、モデルをnewして、save!してバリデーションを発火させるのはやりすぎ。以下の方法がある
valid?で発火させる。
be_validを使う◎

# 保存する前に、バリデーションを発火させた状態を確認できる
expect(setting).to be_valid

itの中でletなど使わずに変数を宣言する書き方もある
各itの中で使うようであれば、@userのようにしてbeforeに移動する

it "returns notes that match the search term" do
user = User.create(
first_name: "Joe",
last_name: "Tester",
email: "joetester@example.com",
password: "dottle-nouveau-pavilion-tights-furze",
)

project = user.projects.create(
name: "Test Project",
)

describe と contextの使い分け
describe ではクラスやシステムの機能に関するアウトラインを記述し、
context では特定の状態に関するアウトラインを記述するようにします。

うだななうだなな

4. 意味のあるテストデータの作成 P47~

テストで使うデータをどう作るかという話。

  • フィクスチャ (デフォルトで使える様になってる仕組み)
  • factory (gem)
    がある
    "factory_bot_rails" をgemに追加する Rails以外の Ruby コードで Factory Botを使うことはできる。

factoryを使うときのtips

  • project_attributes = FactoryBot.attributes_for(:project) ファクトリで定義された全ての属性を含むハッシュを生成。これはデータベースにオブジェクトを保存せず、メモリ上にモデルインスタンスも作成しない。
  • シーケンスを使うと、モデルのデータをまとめて作るときに、値が重複することを防ぐことができる
 factory :user do
    sequence(:email) { |n| "tester#{n}@example.com" }
end
  • factoryの中でassociation : XXX を使うと、関連するXXXというデータを同時に作成できる
  • 作成はせず、作成済のデータを関連付けるだけにすることもできる
FactoryBot.define do
  factory :note do
    message "My important note."
    association :project
    user { project.owner } # association : userにすると、別のユーザーができてしまうので`project.owner` にする
end end

factoryの重複を減らすtips

  • 継承を表現する(入れ子構造になる)
factory :project do
    sequence(:name) { |n| "Test Project #{n}" }
    description "Sample project for testing purposes"
    due_on 1.week.from_now
    association :owner
    factory :project_due_yesterday do
      due_on 1.day.ago # 他の属性について定義しなくてよい!
    end
end
FactoryBot.create(:project_due_tomorrow)
  • traitを使用する(入れ子構造になる)
trait :due_yesterday do
      due_on 1.day.ago
end
FactoryBot.create(:project, :due_yesterday)

コールバック

  • traitとbeforeafterを組み合わせると、明示的にコールバックを呼び出せる
  • 他にも方法はあるが、ファクトリを使うたびに呼び出されないよう、traitの中で使うのが安全
trait :with_notes do
 after(:create) { |project| create_list(:note, 5, project: project) }
end
FactoryBot.create(:project, :with_notes) # traitを呼び出すとコールバックが発火する

注意

可能な限り FactoryBot.create よりも FactoryBot.build を使う。buildはデータの永続化を行わないため高速。

うだななうだなな

5. コントローラスペック P70~

  • responseは予約語。ブラウザに返すべきアプリケーションの全データを保持している
  • Rails5からcontrollerのテストは非推奨
  • 7章へ
うだななうだなな

6. フィーチャスペックで UI をテストする P95~

  • フィーチャスペック = 受入テスト 、または 統合テスト
  • のちのアップデートで、システムスペックに変わったので注意
  • rails標準では Minitest を使えるようになっているが、Capybaraを使用する例が紹介されている。ブラウザの操作をシミュレートするために Capybaraを使う。Rails 5.1からは、Capybaraはすでにインストールされている。

Capybaraのテクニック

  • テストが失敗して、ブラウザの様子が見たいときは save_and_open_page を記載すると、スクショがDLできる
  • Capybaraが使うブラウザは、JavaScript の実行はサポートしていない。JSに依存するテストがある場合は js: true というオプションを使う必要がある
うだななうだなな

7. リクエストスペックで API をテストする P111~

  • spec/requests ディレクトリに配置する
作成者以外のコメントは許可されていません