LoginSignup
25
22

More than 3 years have passed since last update.

Active Storage 導入環境下での単体テスト

Last updated at Posted at 2020-08-06

まずActive Storageって何?

ファイルアップロードを行うための機能で、
これを使えばフォームで画像の投稿機能などが簡単に作れる。
また、クラウドストレージサービスへのファイルのアップロードも
簡単にできちゃいます。

自分の場合は画像をアップロードできる機能があるアプリケーションを作成していたので、
Active Storageを導入していました。
特徴としては画像用のカラムを用意する必要がないこと。
今回はこの特徴で、エラーがでまくっていたのですが...

本題のテストのこと

今回のエラーの原因は
①FactoryBotで、ダミーのimageデータを作ってしまっていた
②spec.rbで、fixture_file_uploadメソッドを使っていなかった

以上の2つが主な原因でエラーを吐きまくっていました。

特に②に関しては、見当違いのことを調べていたばかりに中々たどり着きませんでした..


それでは①から。

例えばproductというモデル/テーブルがあるとして

Active Storageを使っていない場合
imageカラム(画像用のカラム)が必要

Active Storageを使っている場合
imageカラム(画像用のカラム)が必要ない

ですよね。

上記を踏まえてFactoryBotの記述を見直すと

Active Storageを使っていない場合

products.rb
FactoryBot.define do
  factory :product do
    image             { 'test_image.jpg' }
    name              { '化粧水' }
    explanation       { '良い化粧水です' }
    price             { '2000' }
    user
  end
end

Active Storageを使ってる場合

products.rb
FactoryBot.define do
  factory :product do
    name              { '化粧水' }
    explanation       { '良い化粧水です' }
    price             { '2000' }
    user
  end
end

こうなるのは当然ですよね。
だってActive Storage環境下ではimageカラム必要ないですし。
(全然気付いていなかった..)

これで①の部分は解決しました。


fixture_file_uploadメソッド

続いて②の方を。
このメソッドはRSpecで用意されているメソッドです。

全然テストが通らなかったときのspec.rb ↓↓↓↓

product_spec.rb
require 'rails_helper'


describe Product do

  describe '#create' do
    before do
      @product = build(:product)
    end



    # 1. imageが存在すれば登録できること
    it 'is valid with an image' do
      expect(@product).to be_valid
    end

    # 2. nameが空では登録できないこと
    it 'is invalid without a name' do
      @product.name = nil
      @product.valid?
      expect(@product.errors[:name]).to include('を入力してください')
    end

                        .
                        .
                        .
                        .
                        .

  end
end

修正後のspec.rb ↓↓↓↓

product_spec.rb
require 'rails_helper'


describe Product do

  describe '#create' do
    before do
      @product = build(:item)
      @product.image = fixture_file_upload("/files/test_image.jpg")
    end



    # 1. imageが存在すれば登録できること
    it 'is valid with an image' do
      expect(@product).to be_valid
    end

    # 2. nameが空では登録できないこと
    it 'is invalid without a name' do
      @product.name = nil
      @product.valid?
      expect(@product.errors[:name]).to include('を入力してください')
    end

                        .
                        .
                        .
                        .
                        .

  end
end

fixture_file_upload("/files/test_image.jpg")
とはなんぞやということなんですけども、
下記のディレクトリの通りにテスト画像を配置しています。

spec
  ├ factories
  ├ fixtures
  │     └ files
  │         ├ test_image.jpg
  │         └ .keep
  ├ models
  :
  :

これを、before do ~ end の間でコールバック(予約)しておいて、
テストコードが実行される前にテスト用の画像を生成しているわけです。

これで②も無事に解決です。


解決してしまえばなんてことない原因でしたが、
たどり着くまでに相当な時間と気力を消費してしまいました。

もっと検索力上げないとな...

同じような原因でテストが通らない方の参考になれば幸いです。

25
22
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
25
22