#はじめに
個人アプリのテストをおざなりにしていましたが、現場に入って最初に行うであろう(予想)テスト業務を滞りなく行うために、学び直した備忘録。ここではモデルのテストについて記述します。
##RSpecの導入
まずはRSpecを利用するために、
・rspec-rails
そしてダミーのインスタンスを簡単に生成できる
・factory_bot
この2つをインストールします。
group :development, :test do
#省略
gem 'rspec-rails'
gem 'factory_bot_rails'
end
bundle installを実行
$ bundle install
##RSpecの設定
Rspec用の設定ファイルを下記コマンドで作成します。
$ rails g rspec:install
そして生成された「.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」という名前で作成します。
下記の様に記述して下さい。
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です。
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
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の記述を省略するために下記の様に記述します。
#省略
RSpec.configure do |config|
#下記追記
config.include FactoryBot::Syntax::Methods
#省略
end
##テストを書いていく
さぁテストを書いていきます。
今回はModelのテストを書くので、「spec」ディレクトリ以下に「models」ディレクトリを作成しさらにその中に「item_spec.rb」を作成しましょう。
ディレクトリ構造
spec/models/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
では次にテスト項目を増やしテストを実行しましょう。
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を使用することで、簡単にダミーデータを作成し、少ない記述で、かつ柔軟にテストを行うことができます。
どなたかの助けになれば幸いです。