rails Ruby 単体テスト

【Ruby】【rails】フリマアプリ商品購入機能のモデル単体テスト

2020年8月29日


メル○リのようなフリーマーケットサイトを開発する中で、商品購入機能を実装後にモデルの単体テストを行いました。本記事では、その実装手順について解説していきます。

単体テストの成功条件

テストファイル実行時にエラーが発生しなければテスト成功です。


## 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

CATEGORIES & TAGS

rails, Ruby, 単体テスト,

Author:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

むるし

インフラ系エンジニア。備忘録で色々書いていきます。
現在テックキャンプでフルコミット中。

年収訴求

CodeCamp

縛りなしWiFi

%d人のブロガーが「いいね」をつけました。