アラフォ〜プログラミング未経験会社員のエンジニアへの道

神奈川県横浜市在住。アラフォーで小学生の息子あり。プログラミング勉強中でHTML/CSS, Ruby, Ruby on Rails, Javascriptなど。 いずれAI関連サービスを開発したい。

[アラフォプログラミング未経験] Gemを利用した効率的なテストコードを学ぶ

今回は、「RSpec」のコードをより効率的に書く方法について勉強しました。

初学の時はほんと頭に残らずに流れていきましたが、

こうやってアウトプットしてみると、

「あっそういうことか!」

「う、忘れてるぅ」

とか気づかされる。


そして、使い慣れると効率的な手法だと実感しますね。。。


目次

factory_botというgemを導入

factory_botというgemを導入し、specファイルの記述を効率化します。

また、テストコードを書く際には常に気をつけなければいけない原則があるので、

この原則についても学習していきます。


factory_bot

簡単にダミーのインスタンスを作成することができるGemです。

他のファイルで予め各クラスのインスタンスに定めるプロパティを設定しておき、

specファイルからメソッドを利用してその通りのインスタンスを作成します。

FactoryBot.define do

  factory :user do
    nickname                            {"abe"}
    email                      {"kkk@gmail.com"}
    password                  {"00000000"}
    password_confirmation   {"00000000"}
  end

end

factory_botにおける最も基本的なメソッド

factory_botにおける最も基本的なメソッドである

buildメソッドとcreateメソッドを紹介します。


buildメソッド

引数にシンボル型で取ったクラス名のインスタンスを、factory_botの記述をもとに作成します。

例えば前述のusers.rbが存在する場合、下記2つの変数userの値は同じ値になります。



factory_botによるインスタンスの生成

#factory_botを利用しない場合
user = User.new(nickname: "abe", email: "kkk@gmail.com", 
password: "00000000", password_confirmation: "00000000")

#factory_botを利用する場合
user = FactoryBot.build(:user)
 ||<





** createメソッド

buildとほぼ同じ働きをしますが、

createの場合はテスト用のDBに値が保存されます。


注意すべき点として、1回のテストが実行され、

終了する毎にテスト用のDBの内容がロールバックされます。(保存された値がすべて消去されてしまう)



従って、binding.pry等でテストの実行を一時停止しないと

テスト用のDBに保存された値をSequel Pro等で確認することはできません。



factory_botによるインスタンスの生成
>|javascript|
#createしたインスタンスはDBに保存される
user = FactoryBot.create(:user)

factory_botの記法の省略

factory_botによってインスタンスを作成する際に、
レシーバーであるクラスのFactoryBotという記述を省略することができます。

そのためには、spec/rails_helper.rbを以下のように編集します。

rails_helper.rb

#省略
RSpec.configure do |config|
  #下記の記述を追加
  config.include FactoryBot::Syntax::Methods

  #省略

end
>||



すると、先ほどのuser_spec.rbの記述はFactoryBotを省いて以下のように省略できます。

user_spec.rb
>|javascript|
  #nicknameが空では登録できないこと
  it "is invalid without a nickname" do
    user = build(:user, nickname: "")
    user.valid?
    expect(user.errors[:nickname]).to include("can't be blank")
  end