ごあいさつ & はじめに
本日より、株式会社OCEAN GATEのイッカツ開発チームの一員として、Qiitaにどんどん記事を投稿していきます!
今はまだプログラミング初心者ですが、業務で学んだことをアウトプットしていきます!
よろしくお願いします!
さて、本題に入ります。
modelにはscopeという、クエリをまとめられる書き方があります。
そのscopeのテストの書き方を学んだのでまとめていきます。
scopeのテスト
- model
scope :deleted, -> { where(is_deleted: true) }
上記のplace.rb
のdeleted
に対し、次のようにSpecを書けます。
- spec
describe 'scope' do
describe 'deleted' do
let!(:place) { create(:place) } # --①
subject { Place.is_deleted } # --②
it { is_expected.to include place } # --③
end
end
ここで何をしているかを説明していきます。
①では、FactoryBotを使ってplaceのデータを作成しています。
②では、modelに書かれているis_deleted
scopeをPlaceモデルに使っています。
そして、subjectとして設定しています。
③では、②のsubjectの配列が、①のデータの配列を含んでいることをテストしています。
include
はマッチャです。
非常にスッキリとしています!
belongs_to のアソシエーションがある場合
belongs_to
というアソシエーションがあるときのテストの書き方でかなり悩みました。
そのため、その内容も書いていきます。
- model
belongs_to :place
scope :place_ornaments, -> (place_id) { where(place_id: place_id) }
今回は、placeにひもづくornamentモデルを使っていきます。
- spec
describe 'place_ornaments' do
let!(:place) { create(:place) } # --④
let!(:ornament) { create(:ornament, place: place) } # --⑤
subject { Ornament.place_ornaments(place.id) } # --⑥
it { is_expected.to include ornament }
end
④では、FactoryBotを使ってplaceのデータを作成しています。
そうしないと、ornamentが作れないためです。
⑤では、ornamentのデータ作成時に④のplace
を渡しています。
このplace:
を使えるの?と思うかもしれません。
実は、FactoryBotで定義していれば使えるのです!
factory :ornament do
place
end
ornamentはplace_id
を持っているので、FactoryBotにはplaceが必要になります。
そのplaceに、④のplaceを渡しておけばbelongs_toのあるscopeのテストも実行できます。
scopeで変数を使っている場合
上記のplace_ornaments
では、place_id
が引数として渡されています。
そのため、引数を指定しないとこのscopeが使用できません。
そこで、⑥のように、place.id
をscopeの後に渡してあげればscopeを使用できるようになります。
おわりに
このようにscopeのテストは意外と簡単に書けてしまいます!
テストはこわくない!