I have a simple test to check that a carrierwave uploader works.
I use minitest for this, and the test works when run on its own, but not under Rails’s rake test...
environment.
(Code for the test is included below.)
Things that work:
- If I run
ruby test/uploaders/image_file_uploader_test.rb
the test passes.
- If I run
testrb test/uploaders/image_file_uploader_test.rb
the test passes.
- If I manually call all the lines in the test from IRB (not the Rails console), the code does what’s expected
- If I create a small Rake TestTask to run the file (task also copied below), the test passes.
Things that do not work:
- If I call
rake test test/uploaders/image_file_uploader_test.rb
I get dropped into the debugger (stack trace below)
- If I call
zeus rake test test/uploaders/image_file_uploader_test.rb
I also get dropped into the debugger
What is strange:
If I head up the call stack in the debugger to the line in the test which has caused the failure – uploader.store!(@file)
– and call it directly with (rdb:1) p uploader.store!(@file)
, it works! By which I mean, the method returns as expected and the file appears in the correct directory.
Thoughts?
I may be doing something really dumb here. It must be something to do with the Rake task loading the Rails environment, right? Am I doubly-including things or something? Is it something to do with the initializer in the Rails environment? (N.B., when I execute store!
from the debugger, it stores the file in the location specified in the test, so it is overridding the Rails initializer successfully).
The backtraces
From bundle exec rake test test/uploaders/*_test.rb
# Running tests:
/Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/carrierwave-0.9.0/lib/carrierwave/uploader/store.rb:75: `' (NilClass)
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:926:in `_run_suite'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/parallel_each.rb:71:in `block in _run_suites'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/parallel_each.rb:71:in `map'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/parallel_each.rb:71:in `_run_suites'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:877:in `_run_anything'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1085:in `run_tests'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1072:in `block in _run'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1071:in `each'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1071:in `_run'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1059:in `run'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:795:in `block in autorun'
/Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/carrierwave-0.9.0/lib/carrierwave/uploader/store.rb:75:
(rdb:1) where
--> #1 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/carrierwave-0.9.0/lib/carrierwave/uploader/store.rb:75:in `rmdir'
#2 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/carrierwave-0.9.0/lib/carrierwave/uploader/store.rb:61:in `with_callbacks'
#3 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/carrierwave-0.9.0/lib/carrierwave/uploader/store.rb:58:in `store!'
#4 /Users/leo/Projects/PortfolioSite/test/uploaders/image_file_uploader_test.rb:38:in `test_upload_of_file'
#5 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1258:in `run'
#6 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:933:in `_run_suite'
#7 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/parallel_each.rb:71:in `_run_suites'
#8 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:877:in `_run_anything'
#9 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1085:in `run_tests'
#10 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1072:in `_run'
#11 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1059:in `run'
(rdb:1) up 3
#4 /Users/leo/Projects/PortfolioSite/test/uploaders/image_file_uploader_test.rb:38:in `test_upload_of_file'
(rdb:1) list
[33, 42] in /Users/leo/Projects/PortfolioSite/test/uploaders/image_file_uploader_test.rb
33 end
34
35 # The whole point of this is to upload a file.
36 def test_upload_of_file
37 uploader = ImageFileUploader.new
=> 38 uploader.store!(@file)
39 # Ensure the uploaded file is correct.
40 assert_equal Digest::SHA2.file(@file).hexdigest, Digest::SHA2.file("#{STORE_PATH}/#{FILENAME}").hexdigest
41 end
42
(rdb:1) p uploader.store!(@file)
[:store_versions!]
(rdb:1)
After the call to p uploader.store!(@file)
, the file has been saved
From zeus test test/uploaders/image_file_uploader_test.rb
(this is pretty similar to the above)
/Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/carrierwave-0.9.0/lib/carrierwave/uploader/store.rb:75: `' (NilClass)
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:62:in `loop'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:62:in `go'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:78:in `block (3 levels) in go'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:78:in `fork'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:78:in `block (2 levels) in go'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:73:in `each'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:73:in `block in go'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:62:in `loop'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:62:in `go'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:78:in `block (3 levels) in go'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:78:in `fork'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:78:in `block (2 levels) in go'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:73:in `each'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:73:in `block in go'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:62:in `loop'
from /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:62:in `go'
from -e:1:in `<main>'
/Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/carrierwave-0.9.0/lib/carrierwave/uploader/store.rb:75:
(rdb:1) where
--> #1 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/carrierwave-0.9.0/lib/carrierwave/uploader/store.rb:75:in `rmdir'
#2 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/carrierwave-0.9.0/lib/carrierwave/uploader/store.rb:61:in `with_callbacks'
#3 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/carrierwave-0.9.0/lib/carrierwave/uploader/store.rb:58:in `store!'
#4 /Users/leo/Projects/PortfolioSite/test/uploaders/image_file_uploader_test.rb:38:in `test_upload_of_file'
#5 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1258:in `run'
#6 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:933:in `_run_suite'
#7 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/parallel_each.rb:71:in `_run_suites'
#8 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:877:in `_run_anything'
#9 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1085:in `run_tests'
#10 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1072:in `_run'
#11 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/minitest-4.7.5/lib/minitest/unit.rb:1059:in `run'
#12 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus/m.rb:203:in `execute'
#13 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus/m.rb:121:in `run'
#14 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus/m.rb:106:in `run'
#15 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus/rails.rb:190:in `test'
#16 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:116:in `command'
#17 /Users/leo/.rvm/gems/ruby-2.0.0-p195@portfolio_site/gems/zeus-0.13.3/lib/zeus.rb:80:in `go'
(rdb:1) up 3
#4 /Users/leo/Projects/PortfolioSite/test/uploaders/image_file_uploader_test.rb:38:in `test_upload_of_file'
(rdb:1) list
[33, 42] in /Users/leo/Projects/PortfolioSite/test/uploaders/image_file_uploader_test.rb
33 end
34
35 # The whole point of this is to upload a file.
36 def test_upload_of_file
37 uploader = ImageFileUploader.new
=> 38 uploader.store!(@file)
39 # Ensure the uploaded file is correct.
40 assert_equal Digest::SHA2.file(@file).hexdigest, Digest::SHA2.file("#{STORE_PATH}/#{FILENAME}").hexdigest
41 end
42
(rdb:1) p uploader.store!(@file)
[:store_versions!]
(rdb:1)
The code
Class being tested
class ImageFileUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
version :thumbnail do
process resize_to_fill: [100,100]
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
The test itself
require 'minitest/autorun'
require 'minitest/pride'
require 'minitest/debugger' if ENV['DEBUG']
require 'rmagick'
require 'carrierwave'
require_relative '../../app/uploaders/image_file_uploader'
class ImageFileUploaderTest < MiniTest::Unit::TestCase
# Before any tests run, set up parameters.
FILENAME = 'test_photo_1.jpg'
STORE_DIR = 'tmp/uploads/store'
CACHE_DIR = 'tmp/uploads/cache'
STORE_PATH = File.join __dir__, '..', '..', STORE_DIR
CACHE_PATH = File.join __dir__, '..', '..', CACHE_DIR
# Override the store and cache dirs so we’re not reliant on Rails.
class ::ImageFileUploader
storage :file
store_dir STORE_PATH
cache_dir CACHE_PATH
end
# Before each test runs, set up a file to test with.
def setup
@file = File.new "#{__dir__}/../test_files/#{FILENAME}"
end
# After each test runs, clear the results directory so it doesn't influence other tests.
def teardown
FileUtils.rm_rf STORE_PATH
FileUtils.rm_rf CACHE_PATH
end
# The whole point of this is to upload a file.
def test_upload_of_file
uploader = ImageFileUploader.new
uploader.store!(@file)
# Ensure the uploaded file is correct.
assert_equal Digest::SHA2.file(@file).hexdigest, Digest::SHA2.file("#{STORE_PATH}/#{FILENAME}").hexdigest
end
end
Simple Rake task
require 'rake/testtask'
Rake::TestTask.new('dev:test') do |t|
t.test_files = FileList['test/uploaders/*_test.rb']
end
Rails initializer (N.B. I think the test is isolated from this...)
CarrierWave.configure do |config|
config.storage = :file
# Override the directory where uploaded files will be stored.
config.store_dir = -> do
if model.nil?
"uploads/other/#{Time.now.strftime("%F")}/#{Time.now.strftime("%H-%M-%S")}"
else
# This is a sensible default for uploaders that are meant to be mounted:
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
# Override the directory where temp files will be stored.
config.cache_dir = -> do
# This is a better default because it prevents temp files from becoming public and is more consistent with the Rails directory structure.
Rails.root.join('tmp/uploads')
end
end
Thanks!