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

[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

現場で使える Ruby on Rails 5速習実践ガイド [ 大場寧子 ]
価格:3828円(税込、送料無料) (2022/5/10時点)

CATEGORIES & TAGS

rails, Ruby, 単体テスト,

Author:


comment

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

関連記事

カテゴリー

むるし

フリーランスのインフラ系エンジニア。
備忘録で色々書いていきます。
お問い合わせは↓
mo-gyu@murci.net
LPIC303 Security
%d人のブロガーが「いいね」をつけました。