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

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

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

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

Ruby on Rails

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

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Q&A

解決済

1回答

1772閲覧

Rspec TypeError: no implicit conversion of ActiveStorage::Attached::One into String

divclass123

総合スコア35

RSpec

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

Ruby on Rails

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

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

0グッド

0クリップ

投稿2021/04/14 18:53

docker-compose exec web bundle exec rspec spec/requests/drinks_spec.rb

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

docker-compose exec web bundle exec rspec spec/requests/drinks_spec.rb

実行時に

イメージ説明

の二つのエラーが返されました

該当のソースコード

2) Drinks GET #index indexアクションにリクエストするとレスポンスに投稿済みの投稿にいいねボタンが存在する Failure/Error: expect(response.body).to include('<i class="fas fa-heart"></i>') expected "\n<!DOCTYPE html>\n<html>\n <head>\n <title>Home | Coffee Passport</title>\n \n \n\n <l...script src=\"/packs-test/js/footer-c1b52f0e268f9a453b2e.js\"></script>\n \n </body>\n</html>\n\n" to include "<i class=\"fas fa-heart\"></i>" Diff: @@ -1,146 +1,291 @@ -<i class="fas fa-heart"></i> + +<!DOCTYPE html> +<html> + <head> + <title>Home | Coffee Passport</title> + + + + <link rel="shortcut icon" type="image/x-icon" href="/assets/favicon-a4d7236eadaf81d069377833d02cf00cf2544205e227490f32ec6a4e4246e6f9.ico" /> + <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.9.0/css/all.css"> + <meta name=”viewport” content=”width=device-width, initial-scale=1”> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> + <script src="js/jquery.bgswitcher.js"></script> + + <script type="text/javascript" src="https://js.pay.jp/v1/"></script> + <link rel="stylesheet" media="all" href="/assets/application-017a54c06c441b96417cac32ae71c6dd87c24a8c18bdc9b79749fe432d887534.css" /> + <script src="/packs-test/js/application-4113f1ad96723f7c97cd.js"></script> + + </head> + + <body id="app"> + + + + <div class = "header",id="slideshow"> + + <a href="/"> + <img class="logo" src="/assets/logo-a4d7236eadaf81d069377833d02cf00cf2544205e227490f32ec6a4e4246e6f9.png" /> +</a> + + + <a href="/users/123"> + <img src="https://instagram.fdel2-2.fna.fbcdn.net/v/t51.2885-19/44884218_345707102882519_2446069589734326272_n.jpg?_nc_ht=instagram.fdel2-2.fna.fbcdn.net&_nc_ohc=s0l7r_rFmQYAX9IB4c9&oh=4d9b567520c4a9e98172a986afa3859b&oe=6028878F&ig_cache_key=YW5vbnltb3VzX3Byb2ZpbGVfcGlj.2" class= 'user-img'> +</a> + <div class="header-nav"> + <div class = "header-user-name"> + <i class="fas fa-user"></i><a class = "h-user-name"><a href="/users/123">はらそう</a></a> + </div> + + + <div class="post"> + <i class="fas fa-pen-alt"></i><a href="/drinks/new">投稿する</a> + </div> + <div class="buy-form"> + <i class="fas fa-mug-hot"></i><a href="/buy">商品を購入</a> + </div> + <div class="searching-link"> + <i class="fas fa-search"></i><a href="/drinks/searchingform">検索</a> + </div> + + + </div> + </div> + + + + <div class="main-wrapper"> + + + +<div class='main'> + + <div class='item-contents'> + + <h2 class='title'>Timeline</h2> + <ul class='item-lists'> + + + + </ul> + </div> +</div> + + + + + + + +<div class='main'> + + <div class='item-contents'> + + <h2 class="title">Selected</h2> + <ul class='item-lists'> + + + <li class='list'> + + <a href="/users/124"> + <div class="user-info-timeline"> + <img src="https://instagram.fdel2-2.fna.fbcdn.net/v/t51.2885-19/44884218_345707102882519_2446069589734326272_n.jpg?_nc_ht=instagram.fdel2-2.fna.fbcdn.net&_nc_ohc=s0l7r_rFmQYAX9IB4c9&oh=4d9b567520c4a9e98172a986afa3859b&oe=6028878F&ig_cache_key=YW5vbnltb3VzX3Byb2ZpbGVfcGlj.2" class= 'user-img-timeline'> + <div class="username-timeline"> + はらそう + </div> + </div> +</a> + <div class='item-img-content'> + <a href="/drinks/62"> + <img class="item-img" src="http://www.example.com/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBRdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--0d36c203df0139814374a04091e3c6eb93f17f73/ethiopia.jpg" /> + + </div> + <div class='item-info'> + <h3 class="item-name"> + TOKYOロースト + </h3> + <div class='item-price'> + <span>350円<br>(税込み)</span> + </div> + <div class='item-explain'> + これはコーヒーの説明です + </div> + <div class='item-tag'> + + + </div> + <div class="like-and-comment"> + <div class="like" id="like-link-62"> + <a data-remote="true" rel="nofollow" data-method="post" href="/like/62"> + <div class = "iine__button"><i class="far fa-heart"></i>0</div> +</a></div> + + + + <a href="/drinks/62"> + <i class="far fa-comment fa-lg"></i> +</a> </div> +</a> </div> + </li> + + + + </ul> + </div> +</div> + </div> + <footer id="footer"> + <router-view></router-view> + <navbar></navbar> + </footer> + + <script src="/packs-test/js/footer-c1b52f0e268f9a453b2e.js"></script> + + </body> +</html>

この+の部分は実際に返されたHTML?

spec/requests/drinks_spec.rb

require 'rails_helper' # bundle exec rspec spec/requests/tweets_spec.rb RSpec.describe "Drinks", type: :request do before do @user = FactoryBot.create(:user) @drink = FactoryBot.create(:drink) # 投稿済みの投稿や、テキストが存在するか確かめる必要が、 # あるので、createでテスト用のDBに値を保存 post login_path, params: { session: { email: @user.email, password: @user.password } } end describe 'GET #index' do it 'indexアクションにリクエストすると正常にレスポンスが返ってくる' do get root_path expect(response.status).to eq 200 end it 'indexアクションにリクエストするとレスポンスに投稿したユーザーの名前が存在する' do get root_path expect(response.body).to include(@drink.user.nickname) end it 'indexアクションにリクエストするとレスポンスに投稿済み投稿に画像URLが存在する' do get root_path expect(response.body).to include(@drink.image) end it 'indexアクションにリクエストするとレスポンスに投稿済み投稿にコーヒーの値段が存在する' do get root_path expect(response.body).to include('350円') end it 'indexアクションにリクエストするとレスポンスに投稿済みの投稿にコーヒー名が存在する' do get root_path expect(response.body).to include(@drink.name) end it 'indexアクションにリクエストするとレスポンスに投稿済みの投稿にコーヒーの説明が存在する' do get root_path expect(response.body).to include("これはコーヒーの説明です") end it 'indexアクションにリクエストするとレスポンスに投稿済みの投稿にいいねボタンが存在する' do get root_path #binding.pry expect(response.body).to include('<i class="fas fa-heart"></i>') end end end

spec/factories/drinks.rb

FactoryBot.define do factory :drink do name {"TOKYOロースト"} price {350} explain {"これはコーヒーの説明です"} region_id {2} body_id {2} acidity_id {2} processing_id {2} likes_count {2} association :user after(:build) do |drink| drink.image.attach(io: File.open('app/assets/images/ethiopia.jpg'), filename: 'ethiopia.jpg') end end end

試したこと

実は、

it 'indexアクションにリクエストするとレスポンスに投稿済み投稿にコーヒーの値段が存在する' do get root_path expect(response.body).to include(@drink.price) end

の場合にとかやっていた場合は
TypeError: no implicit conversion of Integer into String

とエラーが出ていました。
調べたところ、文字列と値が混合してると起きるエラーみたいなので、
実際にHTMLで値段の部分が「350円」なので、そこをテストするようにしたら、パスできました。

画像も同様に

it 'indexアクションにリクエストするとレスポンスに投稿済み投稿にコーヒーの画像が存在する' do get root_path expect(response.body).to include("http://www.example.com/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBRdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--0d36c203df0139814374a04091e3c6eb93f17f73/ethiopia.jpg") end

 とやりましたが、当たり前ですが、画像のURLが毎回変わるのでテストがパスできません。

あと、いいねボタンがあるかどうかテストしたいのですが、

it 'indexアクションにリクエストするとレスポンスに投稿済みの投稿にいいねボタンが存在する' do get root_path #binding.pry expect(response.body).to include('<i class="fas fa-heart"></i>') end

このようにテストしましたが、以上のようなエラーで上手くいきません
アイコンのテストのやり方が分かりません。そもそもいいねボタンが表示されてるかどうかテストする必要があるかどうかは微妙かもしれませんが、drinks#indexのHTMLの重要な構成要素だと考えたので、テストの必要ありと考えました。

ご教授いただけると幸いです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

rb

1 it 'indexアクションにリクエストするとレスポンスに投稿済み投稿にコーヒーの値段が存在する' do 2 get root_path 3 expect(response.body).to include(@drink.price) 4end

ここのテストが通らないのはおっしゃっている通り、文字列(response.body)と数値(@drink.price)を比較しているからだと思います。起きている事象としてはこんな感じだと思います。

irb

1irb(main):004:0> body = '350円' # 便宜上省略した文字列を定義 2=> "350円" 3irb(main):005:0> body.include?(350) # bodyの中に350が含まれるかをチェック 4Traceback (most recent call last): 5 5: from /Users/tanakakenzou/.rbenv/versions/2.6.3/bin/irb:23:in `<main>' 6 4: from /Users/tanakakenzou/.rbenv/versions/2.6.3/bin/irb:23:in `load' 7 3: from /Users/tanakakenzou/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>' 8 2: from (irb):5 9 1: from (irb):5:in `include?' 10TypeError (no implicit conversion of Integer into String)

irb

1# こうすれば文字列同士の比較になるのでエラーにならない 2irb(main):006:0> body.include?('350') # 350を文字列にしてみる 3=> true

なので、テストの書き方としては

実際にHTMLで値段の部分が「350円」なので、そこをテストするようにしたら、パスできました。

で良いのではないかなと思います。テスト内では期待値の部分を変数を使わず、ベタ書きするのはよくやります。
参考:テストコードの期待値はDRYを捨ててベタ書きする ~テストコードの重要な役割とは?~ - Qiita

どうしても変数を使いたい場合は、式展開などが良いかも知れません。

rb

1expect(response.body).to include("#{@drink.price}円")

画像のテストの箇所に関しては、ここ↓で画像URLの文字列と比較できていないのかなと思います。

rb

1expect(response.body).to include(@drink.image)

↓こんな感じで確認できそうです。

rb

1binding.pry 2# @drink.image が何を返しているか 3# @drink.image.class(多分Stringではない?) 4expect(response.body).to include(@drink.image)

なので画像URLをとるためにurl_forなどを使うとできるかもしれません。ちょっと確証がないのですが、試してみて下さい????出来なかった場合は、Active Storage urlとかでGoogle検索していくとやりたいことが見つかると思います。

Active Storage の概要 - Railsガイド


最後のいいねボタンに関しては、パッと理由がわからなかったので一旦上記だけ回答しておきました????


rb

1before do 2 @user = FactoryBot.create(:user) 3 @drink = FactoryBot.create(:drink) 4 # 投稿済みの投稿や、テキストが存在するか確かめる必要が、 5 # あるので、createでテスト用のDBに値を保存 6 post login_path, params: { session: { email: @user.email, 7 password: @user.password } } 8end

本題と関係ないところですが、一点気になったところがあったので、書いておきます。上記なのですが、RSpecでなにか変数を定義したい場合は let を使う方が一般的です。下記記事に色々Tipsが書いてありますので時間あるの時、その辺りも見直してみると良いかも知れません????
「RSpec で example の外で定義したローカル変数を使うのはアリか?」に対する僕の見解と解決策 - give IT a try
RSpecのletを使うのはどんなときか?(翻訳) - Qiita

↓僕だったらこんな感じで書くというのをのせておきます

rb

1RSpec.describe "Drinks", type: :request do 2 before { post login_path, params: { session: { email: user.email, password: user.password } } } 3 4 describe 'GET #index' do 5 let(:user) { create(:user) } # userはbeforeの中で参照されるのでlet!にしない 6 let!(:drink) { create(:drink) } # drinkはあらかじめ作成しておく必要があるのでlet! 7 8 # 色々 9 end 10end

投稿2021/04/15 00:27

編集2021/04/15 05:55
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問