当ブログではPRや広告を掲載しています

【Rails】RSpecで画像投稿テストをやる方法(refile)

プログラミング
この記事はこんな人向け
  • Rails 初学者
  • RSpec で画像投稿のテストを書きたい
  • refile などのgemを使っている
スポンサーリンク

何をやるのか、とその前提

最終目的

この記事では、RSpecを用いて画像投稿のテスト、対象モデルのバリデーションテストを行う手順を解説していきます。

画像は単数でのテストとなりますが、このやり方を応用すれば複数画像の投稿テストも可能です。
「複数画像のテストをやりたいんだ!」という人も、ぜひ一読いただき、自分の環境で応用できないか試してみてください。

前提条件

Rails で画像を扱うのに、専用のgemを入れてコーディングする場合も多いです。

なので、この記事での手順は、“refile”“carrierwave”などのgemを使用して実装している前提とします。

また、作成しているアプリの方では既に画像アップロード周辺の機能を実装済みとします。

テストコードの書き方

画像を保存しているカラムについて

今回は users テーブルに紐づく形で、画像を登録する設定とします。

このとき、モデルでは以下のように “profile_image” などの任意の名称で画像を保存するカラムを指定します。

app/models/user.rb
class User < ApplicationRecord
...
  attachment :profile_image
...
end

これで user と紐づいた形で profile_image に画像が保存されるようになりますが、前述の gem を使用している場合は、schemaファイルに profile_image カラムが現れません。

これは gem の仕様で、内部的に画像保存用カラムを持っているので、実際にDBを見ると定義されていることが確認できます。

下準備

実際にテストコードを書いていく前に、少し準備をする必要があります。

画像を配置

まず、テストで使用する画像をあらかじめどこかに置いておきます。

今回は以下のパスでフォルダを作成し、「test.jpg」というファイルを用意しました。
※画像ファイルの拡張子は png などでも構いません。

spec/fixtures/images/test.jpg

FactoryBot でダミーデータを定義

次にダミーデータの定義です。
“factory_bot_rails”のgemを使うので、以下のようにGemfileに追加し、bundle install しておいてください。(既にあれば追加不要です)

Gemfile
gem "factory_bot_rails"

そして FactoryBot で以下のようにファイルを作成して、ダミーデータを定義しておきます。

spec/factories/users.rb
FactoryBot.define do
  factory :user do
    name { Faker::Lorem.characters(number: 10) }
    email { Faker::Internet.email }
    introduction { Faker::Lorem.characters(number: 20) }
    password { 'password' }
    password_confirmation { 'password' }
  end
end

モデルのバリデーションテスト

それではモデルのテストを以下のように書いていきます。

spec/models/user_spec.rb
RSpec.describe 'Userモデルのテスト', type: :model do
  context 'プロフィール画像' do
    it '画像がvalid' do
      user.profile_image = Rack::Test::UploadedFile.new(File.join(Rails.root, 'spec/fixtures/images/test.jpg'))
      is_expected.to eq true
    end
  end
end

User モデルで指定していた、profile_image のカラムに対して画像を指定する内容となっています。

下記の部分が、画像をアップロードしてバイナリ形式でプログラムが処理できるようにする、というものです。(まあ呪文のようなものだと思ってください笑)

Rack::Test::UploadedFile.new(File.join(Rails.root, 'spec/fixtures/images/test.jpg'))

これでテストを実行すると、バリデーションがOKでテストをパスします。

フォーム画面から画像登録のテスト

次に、画像をフォーム画面から投稿するテストコードの書き方を解説します。

専用のgemをインストール

画面を操作したように振る舞うテストを実行するために、”capybara”というgemを使用します。

Gemfile に以下を追加し、bundle install してgemを入れてください。

Gemfile
gem 'capybara'

画面操作のテスト

以下のパスのように、フォルダとファイルを作成します。(ファイル名はなんでもOKです)

spec/system/profile_spec.rb
require 'rails_helper'
describe 'ユーザ情報編集のテスト' do
  let(:user) { create(:user) }

  before do
    visit edit_user_path(user)
  end

  context '更新成功をテスト' do
    before do
      @user_old_profile_image = nil
      attach_file 'user[profile_image]', File.join(Rails.root, 'spec/fixtures/images/test.jpg')
      click_button 'Update User' # ボタンの名称に変更してください
    end
    it 'profile_imageが正しく更新される' do
      expect(user.reload.profile_image).not_to eq @user_old_profile_image
    end
  end
end

このテストの流れは、大きく以下のようになっています。

  1. FactoryBotで定義したデータをuser変数に展開する
  2. ユーザー情報編集画面に遷移する
  3. 更新前の profile_image の内容を変数に持っておく
  4. フォーム上で profile_image に画像を選択した状態にする
  5. 更新ボタン(“Update User”)を押す
  6. user変数の profile_image が、更新前と異なっていることを確認する

特に、以下の部分は少し注意が必要で、モデルの画像テストで使用したコードと少し異なっています。

attach_file 'user[profile_image]', File.join(Rails.root, 'spec/fixtures/images/test.jpg')

これはフォームの input要素に対して、ファイルの場所を教えてあげているだけで、実際にファイルを取得してバイナリ形式で処理するのはコントローラーになるので、ここでは場所を教えているだけなんです。

なお、’user[profile_image]’ となっている箇所はフォームで input となっているものの name 属性に指定している名前を書くようにしてください。

まとめ

RSpec での画像テストのやり方を解説しました!

今回は user モデルに画像が紐づく形となっており、ざっくりまとめると以下のような流れでテストができました。

  • 必要なgemを入れておく
  • テストに使う画像を用意する
  • FactoryBot でダミーデータを定義する
  • モデルのバリデーションテストを書く
  • capybara で画面操作のテストを書く
  • テスト実行

この記事では画像1つでの例でしたが、このやり方を応用すれば、画像が複数の場合のテストも可能ですので、ぜひ試してみてください。

コメント