メル○リのようなフリーマーケットサイトを開発する中で、商品購入機能を実装後にモデルの単体テストを行いました。本記事では、その実装手順について解説していきます。
単体テストの成功条件
テストファイル実行時にエラーが発生しなければテスト成功です。
## cardsテーブル
|Column|Type|Options|
|------|----|-------|
|card_id|string|null: false|
|customer_id|string|null: false|
|user_id|integer|null: false|
### Association
$ bundle exec rspec spec/models/card_spec.rb
Card
#create
user_id, customer_id, card_idが存在すれば登録できること
user_idが無い場合は登録できないこと
customer_idが無い場合は登録できないこと
card_idが無い場合は登録できないこと
Finished in 2.26 seconds (files took 17.81 seconds to load)
4 examples, 0 failures
実装手順
以下の手順で実装していきます。
❶ 事前準備
❷ cardモデルにvalidation追加
❸ card_specファイルの作成
❹ factory_botでインスタンスを作成する
❺ 動作確認
❶ 事前準備
RSpecおよびfactory_botの導入
Gemをインストールします。
テストを行うためのフレームワークRSpecを使用するためにrspec-railsと、ダミーのインスタンス作成用のfactory_bot_railsを導入します。
web-consoleは、test環境で動かすと不具合が起きる可能性があるためdevelopment環境へ移動します。
Gemfile
group :test do
gem 'rspec-rails'
gem 'factory_bot_rails'
end
group :development do
gem 'web-console', '>= 3.3.0'
end
$ bundle install
RSpecの設定
RSpec用の設定ファイルを作成します。
$ rails g rspec:install
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
rails_helper.rb
/ 共通の設定を記載して、ファイルを読み込んで適用します。
spec_helper.rb
/ 共通の設定を記載して、ファイルを読み込んで適用します。RSpecをRails無しで使う場合に使用
RSpecの挙動確認
テストコマンドを実行して以下の結果となれば正常です。
$ bundle exec rspec
No examples found.
Finished in 0.00031 seconds (files took 0.19956 seconds to load)
0 examples, 0 failures
❷ cardモデルにvalidation追加
マイグレーションファイルのnull制約と合わせて、モデルにもバリデーションを設定します。presenceでは、指定された属性が空(nilや空文字)でないことを確認します。
app/models/card.rb
class Card < ApplicationRecord
validates :user_id, presence: true
validates :customer_id, presence: true
validates :card_id, presence: true
end
❸ card_specファイルの作成
RSpecのファイル構造は本アプリケーションのフォルダ配置に合わせて以下のようになります。
ここでcardモデルのspecファイルを作成します。
spec/models/card_spec.rb
require 'rails_helper'
describe Card do
describe '#create' do
it "user_id, customer_id, card_idが存在すれば登録できること" do
card = build(:card)
expect(card).to be_valid
end
it "user_idが無い場合は登録できないこと" do
card = build(:card, user_id: nil)
card.valid?
expect(card.errors[:user_id]).to include("を入力してください")
end
it "customer_idが無い場合は登録できないこと" do
card = build(:card, customer_id: nil)
card.valid?
expect(card.errors[:customer_id]).to include("を入力してください")
end
it "card_idが無い場合は登録できないこと" do
card = build(:card, card_id: nil)
card.valid?
expect(card.errors[:card_id]).to include("を入力してください")
end
end
end
今回は、各カラムが空であれば登録できないことをテストするので、idをnilにしてcardモデルを作成(build)し、validationが通ればtrue,NGならばエラー文を返します。(valid?)
注意点として、エラー文「”を入力してください”」はconfig/locale/ja.ymlに記載の文と同一でないとエラーとなります。
また、インスタンス作成のbuildについては、factory_botを使用しない場合Card.newとなります。factory_botでは主にインスタンス作成のみのbuildとDB保存まで行うcreateメソッドが使われます。
config/locale/ja.yml
errors:
format: "%{attribute}%{message}"
messages:
accepted: を受諾してください
blank: を入力してください
❹ factory_botでインスタンスを作成する
spec/factories/cards.rb
FactoryBot.define do
factory :card do
id {1}
user_id {1}
customer_id { "cus_xxxxxxxxxxxxxx" }
card_id { "car_yyyyyyyyyyyyyyy" }
end
end
各値は適当で構いません。
❺ 動作確認
モデルのspecファイルを実行して、正常終了することを確認します。
$ bundle exec rspec spec/models/card_spec.rb
Card
#create
user_id, customer_id, card_idが存在すれば登録できること
user_idが無い場合は登録できないこと
customer_idが無い場合は登録できないこと
card_idが無い場合は登録できないこと
Finished in 2.26 seconds (files took 17.81 seconds to load)
4 examples, 0 failures
|
|
|
|