LoginSignup
2
2

More than 1 year has passed since last update.

【Rails】RspecのFormオブジェクトモデル単体テストコードのエラー

Last updated at Posted at 2022-11-18

はじめに

rails初学者の者です。オンラインでプログラミングを学習させて頂いてるのですが、さらに理解を深めていきたいと思い、学習したことを備忘録として、残して理解を深めていきたいと思います。
また、間違った点など、ありましたら、ご指摘いただけると幸いです。よろしくお願いします。

前提

Formオブジェクトクラスを作成して、モデル単体のテストコードの実装を行なっていました。具体的のスクールの課題でメルカリのコピーアプリのようなものを作成していた中で、今回のテストコードの実装がありました。

概要

商品購入機能を実装し、購入するにあたって、
「クレジットカード情報」
カード情報、有効期限、セキュリティコード
「配送先情報」

create_addresses.rb
class CreateAddresses < ActiveRecord::Migration[6.0]
  def change
    create_table :addresses do |t|
      t.string         :post_code,           null:false
      t.integer        :prefecture_id,       null:false
      t.string         :city,                null:false
      t.string         :address,             null:false
      t.string         :building_name,       null:false
      t.string         :phone_number,        null:false
      t.references     :purchase,            null:false,foreign_key: true
      t.timestamps
    end
  end
end

郵便番号、都道府県、市区町村、番地、建物名、電話番号、
を入力する必要がありました。

カード情報は、「Pay.jp」を導入して行なっています。
さらに、「配達先情報」と「購入者情報」を同時に二つのテーブルに保存させるため、
「purchase_addressクラス」を作成しています。

purchase_address.rb
class PurchaseAddress
  include ActiveModel::Model
  attr_accessor :post_code, :prefecture_id, :city, :address, :building_name, :phone_number, :user_id, :product_id, :token

  with_options presence: true do
    validates :address
    validates :user_id
    validates :product_id
    validates :token
    validates :post_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "is invalid. Include hyphen(-)"}
    validates :city
    validates :phone_number, format: {with: /\A\d{10,11}\z/}
  end

    validates :prefecture_id, numericality: { other_than: 1, message: "can't be blank" }

    def save
      purchase = Purchase.create(user_id: user_id, product_id: product_id)

      Address.create(post_code: post_code, prefecture_id: prefecture_id, city: city, address: address, building_name: building_name,
                     phone_number: phone_number, purchase_id: purchase.id)
    end
end

テストコードの概要

purchase_address_spec.rb
require 'rails_helper'

RSpec.describe PurchaseAddress, type: :model do
  describe '商品購入記録の保存' do
    before do
       @user = FactoryBot.create(:user)
       @product = FactoryBot.create(:product)
       @purchase_address = FactoryBot.build(:purchase_address,user_id: @user.id, product_id: @product.id)
    end

    context '内容に問題ない場合' do
      it 'すべての値が正しく入力されていれば購入できること' do
        expect(@purchase_address).to be_valid
      end
      it '建物名が空でも購入できること' do
        @purchase_address.building_name = ''
        expect(@purchase_address).to be_valid
      end
    end

    context '内容に問題がある場合' do
      it '郵便番号は空では保存できないこと' do
        @purchase_address.post_code = ''
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("Post code can't be blank")
      end
      it '郵便番号は『3桁ハイフン4桁』半角英数字でないと保存できないこと' do
        @purchase_address.post_code = '123-1234'
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("Post code is invalid. Include hyphen(-)")
      end
      it '都道府県に「---」が選択されている場合は購入できないこと' do
        @purchase_address.prefecture_id = '1'
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("Prefecture can't be blank")
      end
      it '市区町村が空だと購入できないこと' do
        @purchase_address.city = ''
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("City can't be blank")
      end
      it '番地が空だと購入できないこと' do
        @purchase_address.address = ''
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("Address can't be blank")
      end
      it '電話番号が空だと購入できないこと' do
        @purchase_address.phone_number = nil
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("Phone number can't be blank")
      end
      it '電話番号が9桁以下だと購入できないこと' do
        @purchase_address.phone_number = '090123456'
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("Phone number is invalid")
      end
      it '電話番号が12桁以上だと購入できない' do
        @purchase_address.phone_number = '090123456789'
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("Phone number is invalid")
      end
      it '電話番号が半角数値でないと購入できないこと' do
        @purchase_address.phone_number = '09012341234'
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("Phone number is invalid")
      end
      it 'tokenが空では購入できないこと' do
        @purchase_address.token = nil
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("Token can't be blank")
      end
      it 'user_idが紐づいていなければ購入できないこと' do
        @purchase_address.user_id = ''
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("User can't be blank")
      end
      it 'product_idが紐づいていなければ購入できないこと' do
        @purchase_address.product_id = ''
        @purchase_address.valid?
        expect(@purchase_address.errors.full_messages).to include("Product can't be blank")
      end

    end
  end
end

今回は商品を購入する場合、ユーザーと商品が紐づいてるidが必要であったため、
@purchase_addressにuser_idとproduct_idを代入しています。この辺も記述の仕方がよく分からなくて、調べたり、メンターの方に実装方針を確認をさせていただきました。

before do
       @user = FactoryBot.create(:user)
       @product = FactoryBot.create(:product)
       @purchase_address = FactoryBot.build(:purchase_address,user_id: @user.id, product_id: @product.id)
    end

FactoryBotの中身です。↓

purchase_address.rb
FactoryBot.define do
  factory :purchase_address do
    post_code { '123-1234'}
    prefecture_id { 3 }
    city { '横浜市緑区' }
    address { '3-4' }
    building_name { '青山ビル' }
    phone_number { '09012341234' }
    token {"tok_abcdefghijk00000000000000000"}

    association :user_id
    association :product_id
  end
end

困っていたエラー文

PurchaseAddress
  商品購入記録の保存
    内容に問題ない場合
      すべての値が正しく入力されていれば購入できること
      建物名が空でも購入できること
    内容に問題がある場合
      郵便番号は空では保存できないこと
      郵便番号は『3桁ハイフン4桁』半角英数字でないと保存できないこと
      都道府県に「---」が選択されている場合は購入できないこと
      市区町村が空だと購入できないこと (FAILED - 1)
      番地が空だと購入できないこと
      電話番号が空だと購入できないこと
      電話番号が9桁以下だと購入できないこと
      電話番号が12桁以上だと購入できない
      電話番号が半角数値でないと購入できないこと
      tokenが空では購入できないこと
      user_idが紐づいていなければ購入できないこと
      product_idが紐づいていなければ購入できないこと

Failures:

  1) PurchaseAddress 商品購入記録の保存 内容に問題がある場合 市区町村が空だと購入できないこと
     Failure/Error: @user = FactoryBot.create(:user)
     
     ActiveRecord::RecordInvalid:
       Validation failed: Password is invalid
     # ./spec/models/purchase_address_spec.rb:6:in `block (3 levels) in <top (required)>'

Finished in 3.19 seconds (files took 1.27 seconds to load)
14 examples, 1 failure

Failed examples:

rspec ./spec/models/purchase_address_spec.rb:37 # PurchaseAddress 商品購入記録の保存 内容に問題がある場合 市区町村が空だと購入できないこと

エラーなのですが、毎回、異なるexampleでエラーが発生してました。
Validation failed: Password is invalid
直訳すると、パスワードが無効です。とのことでした。

users.rb
FactoryBot.define do
  factory :user do
    name { Faker::Name.initials(number: 2) }
    email                 { Faker::Internet.free_email }
    password              { '1a1a1a1a' }#指定するまではFakerを使用していました。
    password_confirmation { password } 
    first_name            { '太郎' }
    last_name             { '田中' }
    first_name_kana       { 'タロウ' }
    last_name_kana        { 'タナカ' }
    birthday              { '1900-01-01' }
    
  end
end

passwordの部分は元々Fakerを使用していて、指定しなおしたらテストコードが通るようになりました。
バリデーションの影響で通過できない、passwordが適用されていたということでしょうか。

PurchaseAddress
  商品購入記録の保存
    内容に問題ない場合
      すべての値が正しく入力されていれば購入できること
      建物名が空でも購入できること
    内容に問題がある場合
      郵便番号は空では保存できないこと
      郵便番号は『3桁ハイフン4桁』半角英数字でないと保存できないこと
      都道府県に「---」が選択されている場合は購入できないこと
      市区町村が空だと購入できないこと
      番地が空だと購入できないこと
      電話番号が空だと購入できないこと
      電話番号が9桁以下だと購入できないこと
      電話番号が12桁以上だと購入できない
      電話番号が半角数値でないと購入できないこと
      tokenが空では購入できないこと
      user_idが紐づいていなければ購入できないこと
      product_idが紐づいていなければ購入できないこと

Finished in 3.22 seconds (files took 0.89895 seconds to load)
14 examples, 0 failures

一旦通るようになったので、備忘録として残しておくことにしました。この後、なぜそうなっていたのかを追求していこと思います。また、このようにアウトプットしようと思ったのは、自分の言葉で説明するのが得意ではなく、もちろん根本的な知識が足りないからだと思っています。しかしながら、少しずつでも続けていき、理解を深めていきたいと思っています。また、些細なことでも構わないので間違った箇所などありましたら、ご指摘いただければと思っております。今回はご覧になって頂けた方、ありがとうございました。

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