0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Ruby on Rails】factory_botを用いたモデルテストの実行手順(複数モデル干渉可)

Last updated at Posted at 2020-07-23

#はじめに
個人アプリのテストをおざなりにしていましたが、現場に入って最初に行うであろう(予想)テスト業務を滞りなく行うために、学び直した備忘録。ここではモデルのテストについて記述します。

##RSpecの導入
まずはRSpecを利用するために、
・rspec-rails
そしてダミーのインスタンスを簡単に生成できる
・factory_bot

この2つをインストールします。

Gemfile
group :development, :test do
#省略
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end

bundle installを実行

ターミナル
$ bundle install

##RSpecの設定
Rspec用の設定ファイルを下記コマンドで作成します。

ターミナル
$ rails g rspec:install

そして生成された「.rspec」に下記を記述

.rspec
--format documentation

出力をフォーマットする方法をRSpecに指示する記述です。テスト結果がすっきりと見やすくなります。

ここできちんと導入できているかチェックします。

ターミナル
$ bundle exec rspec

以下の様な結果が出力されれば準備は完了です。

ターミナル
No examples found.


Finished in 0.0006 seconds (files took 0.46206 seconds to load)
0 examples, 0 failures

##factory_botを使用する準備
まず「spec」ディレクトリ直下に「factries」というディレクトリを追加します。

そしてその「factories」内に「Model名の複数形.rb」という名前でファイルを生成して下さい。(例:items.rb)

実際のModelのファイル名と見分けがつかなくなることから複数形で作成することを推奨します。

ここは適宜自身のテストを行う、Model名に合わせて下さい。

今回は「items.rb」という名前で作成します。
下記の様に記述して下さい。

items.rb
FactoryBot.define do

  factory :item do
    name              {"ネックレス"}
    status            {"K18ネックレスです"}
    brand             {"C.ARA"}
    user   #外部モデル
    after(:build) do |item|   #外部モデル(複数)
      item.images << build(:image, item: item)
    end 
  end

end

適宜それぞれアプリケーションのカラム名に合わせ、データをセットして下さい。
user, imagesにおいては、テストしたいModelに紐づいているModelです。
テストするModelに紐づいているモデルがあれば上記同様「factories」内に「Model名の複数形.rb」という名前でファイルを生成して下さい。

下記の2つのファイルはテストするModelに紐づいているModelです。

users.rb
FactoryBot.define do
  
  factory :user do
    nickname {"こんちゃん"}
    image {"test.jpeg"}
    password {"12345678"}
    password_confirmation {"12345678"}
    #Fakerを使用している場合
    sequence(:email) {Faker::Internet.email}
    #していない場合
    email {"test@test.com"}
  end

end
images.rb
FactoryBot.define do
  
  factory :image do
    src {"test.jpg"}
    item
  end

end

facrory_botを利用する事により、テストを書く際のインスタンスを生成する記述をかなり省略することができます。

#factory_botを利用しない場合のインスタンスの生成方(外部キー省略)
item = Item.new(name: "ネックレス", status: "k18ネックレスです", brand: "C.ARA")
#factory_botを利用する場合
item = FactoryBot.build(:item)

そしてfactory_botの記述を省略するために下記の様に記述します。

rails_helper.rb
#省略
RSpec.configure do |config|
  #下記追記
  config.include FactoryBot::Syntax::Methods
  #省略
end

##テストを書いていく
さぁテストを書いていきます。
今回はModelのテストを書くので、「spec」ディレクトリ以下に「models」ディレクトリを作成しさらにその中に「item_spec.rb」を作成しましょう。

ディレクトリ構造
spec/models/item_spec.rb

テストを記述します。
まずは基本的な全てのプロパティに値が入っているときに保存できるかをチェックします。

item_spec.rb
require 'rails_helper'

describe Item do
  describe '#create' do

    it "allcomplete => save" do
      item = build(:item)
      expect(item).to be_valid
    end

  end
end

it ~ doの間はそのexampleの説明を記述します。(日本語でもOK)
上記はインスタンスを生成(factory_botにより)し、それが保存できるかをチェックするテストです。

テストを実行してみましょう。

ターミナル
$ bundle exec rspec

下記の様になれば成功です。
エラーが出る場合はfactory_botのプロパティ名、データ型、またはバリデーションが間違っていないかチェックしましょう。

ターミナル
Item
  #create
    allcomplete => save

Finished in 0.2394 seconds (files took 2.48 seconds to load)
1 example, 0 failures

では次にテスト項目を増やしテストを実行しましょう。

item_spec.rb
require 'rails_helper'
describe Item do
  describe '#create' do

    it "allcomplete => save" do
      item = build(:item)
      expect(item).to be_valid
    end

    it "name must exist" do
      item = build(:item, name: nil)
      item.valid?
      expect(item.errors[:name]).to include("can't be blank")
    end

    it "status == nil otherComplete => save?" do
      item = build(:item, status:nil)
      expect(item).to be_valid
    end

    it "brand == nil otherComplete => save?" do
      item = build(:item, brand:nil)
      expect(item).to be_valid
    end

  end
end

上から順に

・全てに値が入っていれば保存できる
・nameに値が入っていなければ保存できない
 ※解説
 ・validメソッド
  インスタンスを保存する際にlaravelによって保存できない様になっているかを確かめられる
 ・errordメソッド
  なぜ保存できないのかを確認できる
・statusに値が入っていなくても保存できる
・brandに値が入っていなくても保存できる

この四項目をテストしていきます。

ターミナル
$ bundle exec rspec
ターミナル
Item
  #create
    allcomplete => save
    name must exist
    status == nil otherComplete => save?
    brand == nil otherComplete => save?

Finished in 0.26776 seconds (files took 2.52 seconds to load)
4 examples, 0 failures

全てパスしました。

この様にfactory_botを使用することで、簡単にダミーデータを作成し、少ない記述で、かつ柔軟にテストを行うことができます。

どなたかの助けになれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?