Testing carrierwave file uploads with RSpec and FactoryGirl
Bài viết được dịch từ blog: https://til.codes/testing-carrierwave-file-uploads-with-rspec-and-factorygirl/ Trong bài viết này tác giả chỉ muốn tập trung vào việc sử dụng Carriewavve trong testing mà cụ thể là Rspec. Vì vậy nếu các bạn muốn biết cách cài đặt hoặc cấu hình carrierwave cho project ...
Bài viết được dịch từ blog: https://til.codes/testing-carrierwave-file-uploads-with-rspec-and-factorygirl/
Trong bài viết này tác giả chỉ muốn tập trung vào việc sử dụng Carriewavve trong testing mà cụ thể là Rspec. Vì vậy nếu các bạn muốn biết cách cài đặt hoặc cấu hình carrierwave cho project của mình thì các bạn nên tham khảo trong wiki của carrierwave tại đây
Giả sử mọi thứ đã được cài đặt đầy đủ cho project của bạn, chúng ta có một model Attachment sử dụng Carrierwave uploader(FileUploader) như dười đây:
# app/models/attachment.rb class Attachment < ActiveRecord::Base mount_uploader :file, FileUploader end
Để bắt đầu sử dụng trong testing, chúng ta cần tạo ra các bản ghi Attachment trong testing. Vì vậy chúng ta cần cập nhật factory của Attachment như sau:.
# spec/factories/attachments.rb FactoryGirl.define do factory :attachment do photo Rack::Test::UploadedFile.new(File.open(File.join(Rails.root, '/spec/fixtures/myfiles/myfile.jpg'))) end end
Trong đoạn code trên chúng ta đã đính kèm file trong thuw mục /spec/fixtures/myfiles/ folder vào trường photo. Có một chú ý là đoạn code trên chỉ có tác dụng đính kèm một file vào trường photo khi bạn build một object mới. Nếu bạn sử dụng phương thức create và muốn tạo một bản ghi tồn tại thực sự trong DB thì ta cần cập nhật đường dẫn file vào cột photo như sau:
FactoryGirl.define do factory :attachment do after :create do |b| b.update_column(:photo, "foo/bar/baz.png") end end end
Với tất cả các cài đặt ở trên thì ta đã đủ để sử dụng factory của Attachment trong Rspec như tất cả các model bình thường để testing. Tuy nhiên, sau đây tác giả sẽ trình bày thêm cách tối ưu để thời gian chạy test là nhanh nhất
- Cài đặt kiểu storage là file đối với môi trường test. 2.Loại bỏ quá trình xử lý file với môi trường test.
- Phân tách thư mục lưu file cho môi trường test khác các môi trường khác.
- Xóa file đã upload sua mỗi request.
Cài đặt Carrierwave để sử dụng local storage and disable quá trình xử lý file test env
Để làm được các công việc trên, chúng ta sẽ thêm cấu hình của Carrierwave trong thư mục initializer như sau:
# config/initializers/carrierwave.rb if Rails.env.test? || Rails.env.cucumber? CarrierWave.configure do |config| config.storage = :file config.enable_processing = false end end
Phân tách thư mục chứa file của môi trường test khác với các môi trường khác.
Tiếp theo, chúng ta nên chia thư mục chứa file upload của môi trường test riêng biệt với các môi trường khác (production, development....). Chúng ta có thể sửa các phương thức cache_dir và store_dir cho tất cả các Carrierwave models hoặc ghi đè trong file config của initializers như dưới đây:
# config/initializers/carrierwave.rb CarrierWave::Uploader::Base.descendants.each do |klass| next if klass.anonymous? klass.class_eval do def cache_dir "#{Rails.root}/spec/support/uploads/tmp" end def store_dir "#{Rails.root}/spec/support/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end end
Xóa file sua mỗi request.
Thêm đoạn code sau vào file spec_helper.rb để chắc chắn rằng file sẽ được xóa sau mỗi test:
# spec_helper.rb RSpec.configure do |config| config.after(:each) do if Rails.env.test? || Rails.env.cucumber? FileUtils.rm_rf(Dir["#{Rails.root}/spec/support/uploads"]) end end end
Cài đặt asset_host
Ta nên cài đặt asset_host cho carrierwave trong file # config/initializers/carrierwave.rb như sau:
CarrierWave.configure do |config| config.asset_host = ActionController::Base.asset_host end
Đến đây, ta đã hoàn thành việc cấu hình sử dungh carrierwave trong testing. Nội dung cuối cùng của file config/initializers/carrierwave.rb sau khi chỉnh sửa là:
if Rails.env.test? || Rails.env.cucumber? CarrierWave.configure do |config| config.storage = :file config.enable_processing = false end # make sure uploader is auto-loaded FileUploader CarrierWave::Uploader::Base.descendants.each do |klass| next if klass.anonymous? klass.class_eval do def cache_dir "#{Rails.root}/spec/support/uploads/tmp" end def store_dir "#{Rails.root}/spec/support/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end end end CarrierWave.configure do |config| config.asset_host = ActionController::Base.asset_host end