このエントリーをはてなブックマークに追加

2017年1月2日月曜日

私たちのFactoryGirlとRspecの使用ルール その1

こんにちは、Taroです。
新年明けましておめでとうございます。

最近、私たちはRailsのテストにRspecを使用しております。
(テストレコードの作成にはFactoryGirlを使用しています。)
今回は私たちのグループ内における基本的な使用ルールについて記載したいと思います。

その1と題しておりますが、その2があるかは未定です。
使っている中で、ルールを更新した場合は、その2、その3としてブログを書いていきたいと思います。

そもそもなぜ基本ルールなどを作成しようとしたのか?
RspecにしろFactoryGirlにしろ、それに沿った使い方をしていれば問題ないのではないか?
当初は私たちもそう考えておりました。
しかし、あまりに優秀すぎるが故、以下の悩みが生じました。
  • 1. 学習コストが高い
    便利な用法が数多く存在するが、それ故に統一感がなくなる可能性がある。
  • 2. 思わぬところでエラーが発生する可能性がある
    特にFactoryGirlですが、Aさんが手の込んだテストモデルを作成し、Bさんがそれをまた改修した場合、Aさんが担当したテストに影響が出る可能性があります。
  • 3. テスト実行に時間がかかるようになる
    せっかくだからと、コールバックメソッドを呼び続けると、全体で見たときのテスト実行に時間をとられることになってしまいます。

このような問題への一つの解として、基本的なルールを設けることとしました。

Rspec編


1. describe、context、itの階層で使用する


Rspecには他にもspecifyやexampleも存在しますが、基本は上記の3つの階層でテストを分類します。
  • describe・・・テストしたい対象(ex. Item#add、items/index)
  • context・・・テストの条件(ex. ログインに成功したとき or ログインに失敗したとき)
  • it・・・リクエストパラメータの違いなどで生じる結果(ex. リクエストパラメータが◯○のときは△△)
また、どうしてもcontextとitの間に階層がほしい場合はspecifyの使用を許可しています。
(ただ、現状specifyを利用するといったテストはないので、そこまで必要ではないのかもしれません。)

describe 'Item#add' do
    context '同一の商品名がない場合' do
        it 'successが返る' do
           expect(Item.add('pokemon')).to eq('success')
        end
    end
    context '同一の商品名がある場合' do
         it 'falseが返る' do
           expect(Item.add('pokemon')).to eq('false')
         end
    end
end

2. 10個以上のテストレコードを作成したい場合は、トランザクションを張る


これはテスト実行速度を少しでもあげるための策です。
ApplicationRecord.transaction do
# テストレコードの作成 end

FactoryGirl編


FactoryGirlの方が特にパフォーマンスなどに影響を与えるため、試行錯誤しております。

1. デフォルトのモデルは初期値を与えるだけで、個別に値設定したい場合は、createメソッドの引数で指定する


デフォルトのモデルはきれいな状態で残しておきます。

2. traitにてパーツを量産しない


ただし、以下の条件の場合は作成できます。
これは、パーツの名前と継承したモデル名で、どんなモデルなのか判断しやすいためです。

2-1. enumで定義されているカラム

例えば、itemsテーブルにカテゴリを定義するcategoryカラムがあったとします。
1〜4までのカテゴリがあり、それぞれにenumでカテゴリ名が定義されているとします。このような場合は、traitとそれを継承したモデルを作成します。
trait :game do
    category 1
end
factory :item_game, traits: [:game], parent: :item

2-2. 過去、未来、現在で固定する

trait :past do
    started_at Time.now.yesterday.beginning_of_day
    ended_at Time.now.yesterday.end_of_day
end
factory :item_past, traits: [:past], parent: :item

2-3. 関連データを生成する場合

関連データを作成してくれることは非常に便利ですが、テストが遅くなる原因となります。
また、別に関連データ自体必要ない人もいるため、こちらもtraitでパーツにして必要な人のみ使用します。
# Item belongs_to Companyとします
trait create_company do
    company
end
factory :item_create_company, traits: [:create_company], parent: :item

現状まとめますと、以上になります。
今後もRSpec、FactoryGirlは使用していこうと思いますので、ルールを更新したら、その2、その3というかたちで記事を書いていきたいと思います。
また、このブログを読んだ方で、何かご意見などございましたらコメントをお待ちしております!

0 件のコメント:

コメントを投稿