質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

1回答

2639閲覧

モデルの単体テストコードでエラーが起きる

yuu0000

総合スコア4

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

0グッド

0クリップ

投稿2021/07/08 03:37

formオブジェクトの単体テストコードで発生しているエラーを解決したい

お世話になっております。

現在、form_objectモデルの単体テストコードを記述しているのですが、実装上で起きたエラー内容が読み取れずどの部分を修正すればいいのかつまずいてしまったため、ご相談させて下さい。

今回エラーが起きている部分は、正常型で値が正しく入力されていれば投稿できるエラー検証になります。

form_objectでは、投稿に関するモデルになっており、

  • tagテーブル(タグ付けテーブル)
  • uploadテーブル(投稿テーブル)
  • upload_tag_relation(タグとの中間テーブル)

今回は、upload_form.rbに記載されているバリデーションを単体テストコードで検証するという実装をしているところで、エラーが生じてしまっている状態です。

発生している問題・エラーメッセージ

$ bundle exec rspec spec/models/upload_form_spec.rb 

1) UploadForm 新規投稿 正常に投稿できるとき すべての値が正しく入力されていれば投稿できる Failure/Error: expect(@upload_form).to be_valid expected #<UploadForm:0x00007fe26c894f08 @upload=#<Upload id: nil, title: nil, text: nil, url: nil, working_day: nil, day_off: nil, cafe_wifi_id: nil, cafe_charging_id: nil, cafe_smoking_id: nil, user_id: nil, created_at: nil, updated_at: nil>, @title="testcafe", @text="content", @url="http", @working_day="平日10:00~20:00", @day_off="不定休", @cafe_wifi_id=0, @cafe_charging_id=0, @cafe_smoking_id=0, @image=#<ActiveStorage::Attached::One:0x00007fe2671f4130 @name="image", @record=#<Upid: nil, title: nil, text: nil, url: nil, working_day: nil, day_off: nil, cafe_wifi_id: nil, cafe_charging_id: nil, cafe_smoking_id: nil, user_id: nil, created_at: nil, updated_at: nil>>, @name="東京", @user_id=552, @validation_context=nil, @error#<ActiveModel::Errors:0x00007fe269733018 @base=#<UploadForm:0x00007fe26c894f08 ...>, @errors=[#<ActiveModel::Error attribute=cafe_wifi_id, type=other_than, options={:value=>0, :count=>0}>, #<ActiveModel::Error attribute=cafe_charging_id, type=other_than, options={:value=>0, :count=>0}>, #<ActiveModel::Error attribute=cafe_smoking_id, type=other_than, options={:value=>0, :count=>0}>]>> to be valid, but got errors: Cafe wifiは0以外の値にしてください, Cafe chargingは0以外の値にしてください, Cafe smokingは0以外の値にしてください # ./spec/models/upload_form_spec.rb:13:in `block (4 levels) in <top (required)>'

該当のソースコード

app/models/upload_form.rb

models

1class UploadForm 2 include ActiveModel::Model 3 attr_accessor :title, :text, :url, :working_day, :day_off, :cafe_wifi_id, :cafe_charging_id, :cafe_smoking_id, 4 :user_id, :image, :name 5 6 with_options presence: true do 7 validates :title, length: { maximum: 40 } 8 validates :text, length: { maximum: 1000 } 9 validates :cafe_wifi_id 10 validates :cafe_charging_id 11 validates :cafe_smoking_id 12 validates :user_id 13 validates :image 14 validates :name 15 end 16 17 with_options numericality: { other_than: 0 } do 18 validates :cafe_wifi_id 19 validates :cafe_charging_id 20 validates :cafe_smoking_id 21 end 22 23 delegate :persisted?, to: :upload 24 25 def initialize(attributes = nil, upload: Upload.new) 26 @upload = upload 27 attributes ||= default_attributes 28 super(attributes) 29 end 30 31 def save(tag_list) 32 33 ActiveRecord::Base.transaction do 34 @upload.update(title: title, text: text, url: url, working_day: working_day, day_off: day_off, cafe_wifi_id: cafe_wifi_id, cafe_charging_id: cafe_charging_id, cafe_smoking_id: cafe_smoking_id, user_id: user_id, image: image) 35 36 @upload.upload_tag_relations.each(&:delete) 37 38 tag_list.each do |tag_name| 39 tag = Tag.where(name: tag_name).first_or_initialize 40 tag.save 41 42 upload_tag_relation = UploadTagRelation.where(upload_id: upload.id, tag_id: tag.id).first_or_initialize 43 upload_tag_relation.update(upload_id: upload.id, tag_id: tag.id) 44 45 end 46 end 47 # upload = Upload.create(title: title, text: text, url: url, working_day: working_day, day_off: day_off, cafe_wifi_id: cafe_wifi_id, cafe_charging_id: cafe_charging_id, cafe_smoking_id: cafe_smoking_id, user_id: user_id, image: image) 48 # map = Map.create(address: address, latitude: latitude, longitude: longitude, upload_id: upload_id) 49 end 50 51 def to_model 52 upload 53 end 54 55 private 56 57 attr_reader :upload 58 59 def default_attributes 60 { 61 title: upload.title, 62 text: upload.text, 63 url: upload.url, 64 working_day: upload.working_day, 65 day_off: upload.day_off, 66 cafe_wifi_id: upload.cafe_wifi_id, 67 cafe_charging_id: upload.cafe_charging_id, 68 cafe_smoking_id: upload.cafe_smoking_id, 69 image: upload.image, 70 name: upload.tags.pluck(:name).join(",") 71 } 72 end 73end

app/models/upload.rb

models

1class Upload < ApplicationRecord 2 has_one_attached :image 3 has_one :map 4 belongs_to :user 5 has_many :upload_tag_relations, dependent: :destroy 6 has_many :tags, through: :upload_tag_relations 7 has_many :favorites, dependent: :destroy 8 has_many :comments, dependent: :destroy 9 extend ActiveHash::Associations::ActiveRecordExtensions 10 belongs_to :cafe_smoking 11 belongs_to :cafe_charging 12 belongs_to :cafe_wifi 13end

app/models/tag.rb

models

1class Tag < ApplicationRecord 2 has_many :upload_tag_relations 3 has_many :uploads, through: :upload_tag_relations 4 5 validates :name, uniqueness: true 6 7end

app/models/upload_tag_relaiton.rb

models

1class UploadTagRelation < ApplicationRecord 2 belongs_to :tag 3 belongs_to :upload 4 5 validate :upload_id 6 validate :tag_id 7end 8

app/spec/factories/upload_form.rb

factories

1FactoryBot.define do 2 factory :upload_form do 3 title { 'testcafe' } 4 text { 'content' } 5 url { 'http' } 6 working_day { '平日10:00~20:00' } 7 day_off { '不定休' } 8 cafe_charging_id { 0 } 9 cafe_smoking_id { 0 } 10 cafe_wifi_id { 0 } 11 name { '東京' } 12 after(:build) do |upload_form| 13 upload_form.image.attach(io: File.open('public/images/test_image2.jpeg'), filename: 'test_image2.jpeg') 14 end 15 end 16end

app/spec/models/upload_form_spec.rb

require 'rails_helper' RSpec.describe UploadForm, type: :model do before do @user = FactoryBot.create(:user) @upload_form = FactoryBot.build(:upload_form, user_id: @user.id) sleep 0.1 # 0.1秒待機 end describe '新規投稿' do context '正常に投稿できるとき' do it 'すべての値が正しく入力されていれば投稿できる' do expect(@upload_form).to be_valid end it 'urlが空でも投稿できる' do @upload_form.url = nil expect(@upload_form).to be_valid end it 'working_dayが空でも投稿できる' do @upload_form.working_day = nil expect(@upload_form).to be_valid end it 'day_offが空でも投稿できる' do @upload_form.day_off = nil expect(@upload_form).to be_valid end end context '正常に投稿できないとき' do it 'titleが空だと投稿できない' do @upload_form.title = nil @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Titleを入力してください') end it 'titleが40文字以上だと投稿できない' do @upload_form.title = 'a' * 41 @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Titleは40文字以内で入力してください') end it 'textが空だと投稿できない' do @upload_form.text = nil @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Textを入力してください') end it 'textが1000文字以上だと投稿できない' do @upload_form.text = 'a' * 1001 @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Textは1000文字以内で入力してください') end it 'cafe_wifi_idが空だと投稿できない' do @upload_form.cafe_wifi_id = nil @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Cafe wifiを入力してください') end it 'cafe_wifi_idの値が0だと投稿できない' do @upload_form.cafe_wifi_id = '0' @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Cafe wifiは0以外の値にしてください') end it 'cafe_charging_idが空だと投稿できない' do @upload_form.cafe_charging_id = nil @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Cafe chargingを入力してください') end it 'cafe_charging_idの値が0だと投稿できない' do @upload_form.cafe_charging_id = '0' @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Cafe wifiは0以外の値にしてください') end it 'cafe_smoking_idが空だと投稿できない' do @upload_form.cafe_smoking_id = nil @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Cafe smokingを入力してください') end it 'cafe_smoking_idの値が0だと投稿できない' do @upload_form.cafe_charging_id = '0' @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Cafe wifiは0以外の値にしてください') end it 'user_idが空だと投稿できない' do @upload_form.user_id = nil @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Userを入力してください') end it 'nameが空だと投稿できない' do @upload_form.name = nil @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Nameを入力してください') end it 'imageが空だと投稿できない' do @upload_form.image = nil @upload_form.valid? expect(@upload_form.errors.full_messages).to include('Imageを入力してください') end end end end

試したこと

  • テストコードを実行すると、正常型である正常に投稿できるときのテストコードに対してエラーが起きているため、それ以外の異常型に関しては修正する部分が無い。
  • エラーコードを確認してみたところ、@upload=以下~~の部分でnilとなっているためこの部分がテストコードが上手くいかない原因ではないかと考えました。
  • @uploadもテストコード上に何かしらの記述をする必要があるのか考えてみましたが、validation自体はupload_form_spec.rbに記述しているためどのように修正すればいいのか分かりませんでした。

補足情報(FW/ツールのバージョンなど)

  • rubymine
  • ruby(3.0.1)
  • Ruby on rails (6.1.3.1)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

バリデーションエラーのメッセージのとおりではないでしょうか?

Cafe wifiは0以外の値にしてください, Cafe chargingは0以外の値にしてください, Cafe smokingは0以外の値にしてください

それらの値に0を明記したものをFactoryBotで生成しているように見えます。

投稿2021/07/08 03:40

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuu0000

2021/07/08 04:08

ご連絡ありがとうございます! ご指摘頂いた通り、factoriesで0と表記してしまっておりました。 解決しました! ありがとうございます。 また、私の知識不足でもありますが、テストコードでエラーが起きた場合は、エラーメッセージのどの部分に着目する必要があるのでしょうか?、、
maisumakun

2021/07/08 04:50

「expected ○○、but got ××」が、「○○になると書いたけど実際には××という結果が得られた」という意味です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問