Rails:在模型规范中测试文件上传验证(神社 gem)
Rails: Testing file upload validation (Shrine gem) at model spec
以下代码在 Rails 4.2 应用程序的模型规范内测试图像验证,其中 RSpec 3.5 和 Shrine gem 用于文件上传。
我的问题是:
- 您能想出改进以下测试的方法或更好的方法来测试这些验证吗?
- 如何提高文件大小验证测试的速度?如果可能的话,我想测试它而不必实际上传 >10mb 的文件。
文件上传设置的其他方面在控制器和功能规范中进行了测试,与此问题无关。
RSpec.describe ShareImage, :type => :model do
describe "#image", :focus do
let(:image_file) do
# Could not get fixture_file_upload to work, but that's irrelevant
Rack::Test::UploadedFile.new(File.join(
ActionController::TestCase.fixture_path, 'files', filename))
end
let(:share_image) { FactoryGirl.build(:share_image, image: image_file) }
before(:each) { share_image.valid? }
context "with a valid image file" do
let(:filename) { 'image-valid.jpg' }
it "attaches the image to this record" do
expect(share_image.image.metadata["filename"]).to eq filename
end
end
context "with JPG extension and 'text/plain' media type" do
let(:filename) { 'image-with-text-media-type.jpg' }
it "is invalid" do
expect(share_image.errors[:image].to_s).to include("invalid file type")
end
end
# TODO: Refactor the following test (it takes ~50 seconds to run)
context "with a >10mb image file" do
let(:filename) { 'image-11mb.jpg' }
it "is invalid" do
expect(share_image.errors[:image].to_s).to include("too large")
end
end
end
end
不是通过 Rack::Test::UploadedFile
路由上传,而是直接使用固定装置或工厂或直接在测试中创建附件元数据记录。最终结果应该是您拥有引用您的文件的附件元数据(上传文件时构建的内容),而无需通过上传代码 运行 它。我不确定使用 Shrine 执行此操作的具体细节,但该技术适用于 Paperclip 等库。在 Shrine 中,这看起来意味着直接构建一个引用您的文件的 Shrine::UploadedFile
记录。
我建议您分别测试元数据提取和验证。您需要使用真实的元数据提取进行测试 IOs,但对于验证测试,您可以为缓存文件分配所需的元数据,该元数据不一定实际存在。
RSpec.describe ImageUploader do
def uploaded_file(metadata = {})
Shrine.uploaded_file(
"id" => "123",
"storage" => "cache",
"metadata" => {"mime_type" => "image/jpeg", "size" => 100}.merge(metadata)
)
end
let(:share_image) do
FactoryGirl.build(:share_image, image: uploaded_file(metadata).to_json)
end
let(:metadata) { Hash.new }
describe "validations" do
before(:each) { share_image.valid? }
context "when image is correct" do
it "passes" do
expect(share_image.errors).to be_empty
end
end
context "when extension is correct but MIME types isn't" do
let(:metadata) { Hash["filename" => "image.jpg", mime_type => "text/plain"] }
it "fails" do
expect(share_image.errors[:image].to_s).to include("isn't of allowed type")
end
end
context "when file is larger than 10MB" do
let(:metadata) { Hash["size" => 11 * 1024 * 1024] }
it "fails" do
expect(share_image.errors[:image].to_s).to include("too large")
end
end
end
end
以下代码在 Rails 4.2 应用程序的模型规范内测试图像验证,其中 RSpec 3.5 和 Shrine gem 用于文件上传。
我的问题是:
- 您能想出改进以下测试的方法或更好的方法来测试这些验证吗?
- 如何提高文件大小验证测试的速度?如果可能的话,我想测试它而不必实际上传 >10mb 的文件。
文件上传设置的其他方面在控制器和功能规范中进行了测试,与此问题无关。
RSpec.describe ShareImage, :type => :model do
describe "#image", :focus do
let(:image_file) do
# Could not get fixture_file_upload to work, but that's irrelevant
Rack::Test::UploadedFile.new(File.join(
ActionController::TestCase.fixture_path, 'files', filename))
end
let(:share_image) { FactoryGirl.build(:share_image, image: image_file) }
before(:each) { share_image.valid? }
context "with a valid image file" do
let(:filename) { 'image-valid.jpg' }
it "attaches the image to this record" do
expect(share_image.image.metadata["filename"]).to eq filename
end
end
context "with JPG extension and 'text/plain' media type" do
let(:filename) { 'image-with-text-media-type.jpg' }
it "is invalid" do
expect(share_image.errors[:image].to_s).to include("invalid file type")
end
end
# TODO: Refactor the following test (it takes ~50 seconds to run)
context "with a >10mb image file" do
let(:filename) { 'image-11mb.jpg' }
it "is invalid" do
expect(share_image.errors[:image].to_s).to include("too large")
end
end
end
end
不是通过 Rack::Test::UploadedFile
路由上传,而是直接使用固定装置或工厂或直接在测试中创建附件元数据记录。最终结果应该是您拥有引用您的文件的附件元数据(上传文件时构建的内容),而无需通过上传代码 运行 它。我不确定使用 Shrine 执行此操作的具体细节,但该技术适用于 Paperclip 等库。在 Shrine 中,这看起来意味着直接构建一个引用您的文件的 Shrine::UploadedFile
记录。
我建议您分别测试元数据提取和验证。您需要使用真实的元数据提取进行测试 IOs,但对于验证测试,您可以为缓存文件分配所需的元数据,该元数据不一定实际存在。
RSpec.describe ImageUploader do
def uploaded_file(metadata = {})
Shrine.uploaded_file(
"id" => "123",
"storage" => "cache",
"metadata" => {"mime_type" => "image/jpeg", "size" => 100}.merge(metadata)
)
end
let(:share_image) do
FactoryGirl.build(:share_image, image: uploaded_file(metadata).to_json)
end
let(:metadata) { Hash.new }
describe "validations" do
before(:each) { share_image.valid? }
context "when image is correct" do
it "passes" do
expect(share_image.errors).to be_empty
end
end
context "when extension is correct but MIME types isn't" do
let(:metadata) { Hash["filename" => "image.jpg", mime_type => "text/plain"] }
it "fails" do
expect(share_image.errors[:image].to_s).to include("isn't of allowed type")
end
end
context "when file is larger than 10MB" do
let(:metadata) { Hash["size" => 11 * 1024 * 1024] }
it "fails" do
expect(share_image.errors[:image].to_s).to include("too large")
end
end
end
end