Очень медленное тестирование с загрузкой файлов - PullRequest
11 голосов
/ 08 марта 2012

Я только добавил валидации для изображения несущей волны в модель, и теперь тесты работают очень медленно. Как я могу ускорить этот процесс? Я чувствую, что должен быть лучший способ.


Я работал без проверок и имел обыкновение проходить через мои тесты rspec в течение примерно 140 секунд, но с тех пор, как я теперь проверяю наличие :display_pic, мне пришлось добавлять реальные загрузки файлов на мою фабрику проектов. Это увеличило его до 240 секунд! 140 уже был на тяжелой стороне, это просто безумие.

Вот как страница github на сайте carrierwave рекомендует настроить 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 при настройке тестирования:

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

Ответы [ 5 ]

9 голосов
/ 11 марта 2012

Ваши загрузки хранятся локально или они отправляются в облачный сервис, такой как S3? Если последнее, это, вероятно, то, что убивает вашу производительность теста.

Для тестов всегда рекомендуется макетировать любые внешние зависимости. Если это ваша проблема, вы должны использовать инструмент для проверки соединения. Я думаю, что fog gem поставляется со встроенной поддержкой для этого.

Обновление: Что касается ответа Джефферсона Жирао , я использовал трюк, чтобы не открывать тестовый файл, и вместо этого использовал 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
6 голосов
/ 15 марта 2012

Теперь, когда проверка выполняется, всегда создается экземпляр, к которому осуществляется доступ к атрибуту 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
3 голосов
/ 27 ноября 2013

С вдохновением от @ jeffersongirao и @ Вольфрам Арнольд :

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.Там должно быть что-то, но не важно, что.Я дал ему коалу.

1 голос
/ 17 января 2013

Я только что столкнулся с этой проблемой, она может помочь решить ее, сохранив файл в памяти, а не позволяя фабрике считывать образ с диска при каждом тесте. Я использую что-то вроде следующего.

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% времени на моем наборе тестов, но мой набор тестов является переменной переменной, поэтому я не могу быть абсолютно уверен. Во всяком случае, просто кое-что рассмотреть, если кто-нибудь ударит эту проблему.

Мне не очень нравится решение, которое требует от вас не проверять модель. Я думаю, что это похоже на ответ StringIO Вольфрама Арнольда, хотя я думаю, что этот способ немного легче понять.

1 голос
/ 17 марта 2012

Вы, наверное, уже рассмотрели это, но связано ли замедление на 100 секунд с одиночной загрузкой файла? Если это совокупность по всем тестам, должен быть способ структурировать их так, чтобы у вас был один (или несколько) тест, который проверяет наличие файла, а в остальное время вы просто его макетируете.

...