使用文件上传测试真的很慢

时间:2012-03-08 09:16:22

标签: ruby-on-rails rspec carrierwave factory-bot

我刚刚将一个载波图像的验证添加到模型中,现在测试运行速度非常慢。我怎样才能加快这个过程?我觉得必须有更好的方法。


我一直在运行而没有经过验证,过去能够在大约140秒内完成我的rspec测试,但是因为我现在验证了:display_pic的存在,我必须将真实的文件上传添加到我的项目中厂。这已经增加到240秒! 140已经处于沉重的一面,这真是太疯狂了。

This is how the carrierwave github page recommends setting up Factory Girl:

FactoryGirl.define do
  factory :project do
    display_pic { File.open(File.join(Rails.root, 'spec', 'support', 'projects', 'display_pics', 'test.jpg')) }
  end
end

我将上面的test.jpg作为一个空的文本文件,因此它本质上尽可能小。

我也遵循了载波建议来设置测试:

CarrierWave.configure do |config|
  config.storage = :file
  config.enable_processing = false
end

5 个答案:

答案 0 :(得分:9)

您的上传是存储在本地还是转到像S3这样的云端服务?如果是后者,这可能会破坏你的测试表现。

对于测试,模拟任何外部依赖项总是好习惯。如果这是您的问题,您应该使用工具来模拟连接。我认为fog gem内置了对此的支持。

更新:Regarding the answer by Jefferson Girao,我使用了一个技巧来避免打开测试文件,而是使用StringIO来模拟测试文件以用于工厂目的。这样做效果更好,因为它避免了磁盘访问:

def test_file_stream(filename = 'test.jpg', mime_type='image/jpg', content = '')
  StringIO.new(content).tap do |s|
    s.content_type = mime_type
    s.original_filename = filename
  end
end

答案 1 :(得分:6)

现在验证一直在创建实例,访问属性display_pic,括号内的代码

{ File.open(File.join(Rails.root, 'spec', 'support', 'projects', 'display_pics', 'test.jpg')) } 

将被执行(它被懒惰地执行)。这导致时间上的差异。

避免这种情况的一个选项是为工厂定义设置to_create我不建议:

FactoryGirl.define do
  factory :project do
    display_pic { File.open(File.join(Rails.root, 'spec', 'support', 'projects', 'display_pics', 'test.jpg')) }

    to_create do |instance|
      instance.save!(:validate => false)
    end 
  end
end

答案 2 :(得分:3)

灵感来自@jeffersongirao@Wolfram Arnold

FactoryGirl.define do
  sequence(:image) do |n|
    {
      tempfile: StringIO.new('{・㉨・}'),
      filename: "#{n}.jpeg",
      content_type: 'image/jpeg'
    }
  end

  factory :user do
    avatar { generate(:image) }
  end
end

这里有两个关键的事情:

  1. CarrierWave的上传设定器可以理解一大堆事物。他们通过将他们获得的内容包装在CarrierWave::SanitizedFile中来实现。其中一件事就是哈希,就像这里一样。

  2. CarrierWave::SanitizedFile关心文件是否为空。我花了太长时间想知道为什么它不接受我的StringIO.new。它需要那里有东西,但它并不关心什么。我给了它一只考拉。

答案 3 :(得分:1)

您可能已经考虑过这一点,但是与文件上传相关的100秒减速?如果它是所有测试的聚合,那么必须有一种方法来构造它们,以便您有一个验证文件存在的单个测试(或几个),其余的时间只是模拟它。

答案 4 :(得分:1)

我刚刚遇到这个问题,它可能有助于通过将文件存储在内存中来解决它,而不是让工厂每次测试都从磁盘读取映像。我正在使用以下内容。

DUMMY_IMAGE = File.open(File.join(Rails.root, 'spec', 'support', 'projects', 'display_pics', 'test.jpg'))
FactoryGirl.define do
  factory :project do
    display_pic DUMMY_IMAGE
  end
end

我认为我在测试套件上节省了大约10%的时间,但我的测试套件是安静的变量,所以我不能完全确定。无论如何,如果有人遇到这个问题,只需考虑一些事情。

我真的不喜欢要求您不验证模型的解决方案。我想这与Wolfram Arnold的StringIO答案相似,尽管我认为这种方式有点容易理解。