配列を持ったインスタンス変数のテストコード 【rspec】【初心者】

Twitterのindexアクションで定義されているであろう@tweetsのテストコードはどのように書いていくかを見ていきます。

 

tweets_controller_spec.rb

describe 'GET #index' do
    it "populates an array of tweets ordered by created_at DESC" do
    end
  end

(ここではindexアクションのビューの遷移のテストコードは省きます)

 

tweets_controller.rb

class TweetsController < ApplicationController

  def index
    @tweets = Tweet.includes(:user).order("created_at DESC")
  end

 

factory_botではダミーのインスタンスを一つしか生成していません。

create_list

そこでcreate_listメソッドを利用し、factory_botの設定ファイルに存在しているリソースを複数作成し、それを変数に代入します。

 

it "populates an array of tweets ordered by created_at DESC" do
      tweets = create_list(:tweet, 3) 
      get :index
    end

 

create_listメソッドは第一引数に作成したいリソースをシンボル 型で、第二引数に作成したい個体数を数字で渡します。

 

ここで、tweetを3つ作ると、それに伴いuserも3名分作成されます。その際、同じemailで作成してしまうとUserモデルのバリデーションに引っかかりエラーが起きます。

そのため、FakerというGemで、ダミーデータを生成します。

 

Faker

まずは"faker", "~> 2.8"をGemに追加し、bundle installします。

そしてtweets.rbを以下のように編集してください。

tweets.rb

FactoryBot.define do
  factory :tweet do
    text {"hello!"}
    image {"hoge.png"}
    created_at { Faker::Time.between(from: DateTime.now - 2, to: DateTime.now) }
    user
  end
end

ここではこのように書くんだな、という風な認識で大丈夫です。

 

テストコードをさらに編集していきます。

describe 'GET #index' do
    it "populates an array of tweets ordered by created_at DESC" do
      tweets = create_list(:tweet, 3) 
      get :index
      expect(assigns(:tweets)).to match(tweets.sort{ |a, b| b.created_at <=> a.created_at } )
    end

    it "renders the :index template" do
    end
  end
#

 

matchマッチャ 

引数に配列クラスのインスタンスをとり、expectの引数と比較するマッチャ です。

sortメソッド

example内で定義しているtweetsの中身の順番を、created_atを基準に降順で並び替えるメソッド。@tweetsはcreated_atで降順にソートしている(.order("created_at DESC")ため、この状態を再現する必要がある。

 

以上で、配列を持ったインスタンス変数のテストコードの基本は終了です。

他人に説明する感覚で、一行一行何を書いているか理解していきましょう!