いわりょのBlog

IT関連で学んだことを書いていきます。

CarrierWaveの画像投稿テストがやっとできた fixture作成とアップロードテスト

長い間避けてたCarrierWave画像投稿のテストをついにやってみる。ドキュメントが英語だったので逃げてました笑

条件

rails 5.1.7
carrierwave 1.2.2

CarrierWaveを設定する

config/initializers/carrierwave.rb

CarrierWave.configure do |config|
・
・
  config.root = "/var/www/app"
  config.cache_dir = "/var/www/app/uploads/tmp"
end
app/uploaders/product_picture_uploader.rb

class ProductPictureUploader < CarrierWave::Uploader::Base

   (省略)

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

テスト用のCarrierwaveに関する設定

test/carrierwave_helper.rb

require 'fileutils'

# Carrierwave setup and teardown
carrierwave_template = Rails.root.join('test','fixtures','files')
carrierwave_root     = Rails.root.join('test','support','carrierwave')

# Carrierwave configuration is set here instead of in initializer
CarrierWave.configure do |config|
  config.root = carrierwave_root
  config.enable_processing = false
  config.storage = :file
  config.cache_dir = Rails.root.join('test','support','carrierwave','carrierwave_cache')
end

# And copy carrierwave template in
#puts "Copying\n  #{carrierwave_template.join('uploads').to_s} to\n  #{carrierwave_root.to_s}"
FileUtils.cp_r carrierwave_template.join('uploads'), carrierwave_root

at_exit do
  #puts "Removing carrierwave test directories:"
  Dir.glob(carrierwave_root.join('*')).each do |dir|
    #puts "   #{dir}"
    FileUtils.remove_entry(dir)
  end
end

下記のコードをコピペするだけで設定できます。
github.com

設定内容は、

  • CarrierWaveの対象ディレクトリを test/support/carrierwave に変更
  • テスト開始時に test/fixtures/files/uploads をコピーして、test/support/carrierwave/uploads を作成
  • テスト終了時に test/support/carrierwave 以下のディレクトリを全て削除

になります。

そして、このヘルパーメソッドをtest_helperで使えるようにrequireします

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'carrierwave_helper'  ← 追加

(省略)

テストデータ作成

$ tree ${RAILS_ROOT}/test/
test/
## 省略 ##
├── fixtures
│   ├── files
│   │   └── uploads
│   │       └── product
│   │           ├── 1
│   │           │   └── product1.jpg
│   │           └── 2
│   │               └── product2.jpg
│   │               
│   └── products.yml
├── support
│   └── carrierwave
├── carrierwave_helper.rb
└── test_helper.rb

products.ymlでディレクトリにある画像の名前を指定する

products.yml
shampoo:
  name: "good shampoo"
  price: "3000"
  description: "very good shampoo"
  picture: "product1.jpg"

Treatment:
  name: "lovely treatment"
  price: "2000"
  description: "very good shampoo"
  picture: "product2.jpg"

最後にアップロードテスト

内容な人それぞれですが、こんな感じでかけばアップロードが成功しているかをテストできます。

    test "should create product with logged in" do
        log_in_as(@user)
        get products_path
        assert_difference 'Product.count',1 do
          post products_path,  params: { product:{ name: 'so good shampoo',
                                                    price: '2000',
                                                    description: 'so good shampoo',
                                                    picture: fixture_file_upload(Rails.root.join('test','fixtures','files', 'product1.jpg')) }}
        end
        assert_redirected_to product_url(Product.last)
    end

この例だとログインして新規の商品を作成し、その商品ページに飛べるかをテストしています。