Як я можу використовувати заводську дівчину для створення вкладки для скріпки?


119

У мене модель Person, яка має багато зображень, де на зображеннях є поле вкладення Paperclip, яке називається data, скорочена версія відображається нижче:

class Person
  has_many :images
  ...
end

class Image
  has_attached_file :data
  belongs_to :person
  ...
end

Особа повинна мати принаймні одне зображення, прикріплене до неї.

Під час використання FactoryGirl у мене код схожий на таке:

Factory.define :image do |a|
  a.data { File.new(File.join(Rails.root, 'features', 'support', 'file.png')) }
  a.association :person
end

Factory.define :person do |p|
  p.first_name 'Keyzer'
  p.last_name 'Soze'
  p.after_create do |person|
    person.assets = [Factory.build(:image, :person => person)]
  end
  # p.images {|images| [images.association(:image)]}
end

(Примітка. Я також спробував код, прокоментований вище, також був випробуваний) Більшість випадків, коли я запускаю функції огірків, я отримую помилку, схожу на таке:

Немає такого файлу чи каталогу - /tmp/stream,9887,0.png (Errno :: ENOENT)

...

Іноді тести проходять успішно.

Хто-небудь може сказати мені, у чому проблема у мене тут чи як вони використовують FactoryGirl та Paperclip разом, щоб досягти чогось подібного до того, що я намагаюся досягти?

Я використовую Rails 3.


2
Голосуйте за питання лише за використання Keyzer Soze в якості тестового імені!
Брено

Коли я це роблю ... фотографії генеруються та розміщуються у загальнодоступній / системній папці кожного разу, коли я запускаю тестовий набір. Фотографії не руйнуються після запуску тестового набору. Хтось ще помічає це?
Jwan622

Відповіді:


86

Ви можете використовувати fixture_file_upload

include ActionDispatch::TestProcess у вашому помічнику для тесту, ось приклад заводу:

include ActionDispatch::TestProcess

FactoryBot.define do
  factory :user do
    avatar { fixture_file_upload(Rails.root.join('spec', 'photos', 'test.png'), 'image/png') }
  end
end

У наведеному вище прикладі spec/photos/test.pngперед запуском тестів потрібно існувати у кореневій директорії вашої програми.

Зауважте, FactoryBotце нове ім'я для FactoryGirl.


2
Ця відповідь цілком вірна, але, можливо, буде більш зрозуміло сказати, що TestProcess включає в себе необхідність включати Фабрику, а не просто у ваш spec_helper.
Ендрю Хаббс

2
Дякую за роз’яснення, Ендрю. Можливо, вам також доведеться розмістити "включити ActionDispatch :: TestProcess" перед блоком FactoryGirl.define (що не відбувається в цьому суті: gist.github.com/313121 ).
Сем

3
Також { }необхідні. Без нього пробивається
bigpotato

3
Подальше уточнення: include ActionDispatch::TestProcessмає бути вставлено в самому початку файлу фабрики, поза в FactoryGirl.define do...endблоці.
Френк Кель

49

Новіший синтаксис FG і не включає необхідних

factory :user do
  avatar { File.new(Rails.root.join('app', 'assets', 'images', 'rails.png')) }
end

або, ще краще,

factory :user do
  avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") } 
end

2
Мені це подобається, але майте на увазі, що rails 4 видаляє додаток / активи / образи / rails.png, тому вам потрібно буде врахувати цю зміну :)
stephenmurdoch

38

Десмонд Боу в Pivotal Labs пропонує уникати файлового завантаження через проблеми з витоком пам'яті. Натомість слід встановити поля скріпками безпосередньо на заводі:

factory :attachment do
  supporting_documentation_file_name { 'test.pdf' }
  supporting_documentation_content_type { 'application/pdf' }
  supporting_documentation_file_size { 1024 }
  # ...
end

Працює для мене. Також досить простий, щоб не вимагати наявного файлу в папці spec / test.
bibstha

2
Крім уникнення витоків пам'яті, таким чином тести будуть швидшими.
evedovelli

Згадана публікація в блозі переїхала на pivotal.io/blog
Карстен С.

На жаль, це не працює з підтвердженням додатку content_type. Для цього вам потрібний дійсний файл-об’єкт.
Карстен С.

25

Я використовував код у суті нижче:

Рейки 2

http://gist.github.com/162881

Рейки 3

https://gist.github.com/313121


1
Просто цікаво одне і те ж, і це прекрасно працює. Дякую. Я помістив його в ініціалізатор.
Тодд

1
Що слід зазначити: Суть вище використовує старіший синтаксис FactoryGirl. Відповідь DanS використовує новий синтаксис.
Ендрю Хаббс


4

Спробуйте використовувати ActionController :: TestUploadedFile. Ви можете просто встановити властивість файлу на екземпляр TestUploadedFile, а решта повинна подбати про інше. Наприклад

valid_file = File.new(File.join(Rails.root, 'features', 'support', 'file.png'))  
p.images { 
   [
     ActionController::TestUploadedFile.new(valid_file, Mime::Type.new('application/png'))
   ] 
}

0

Наведені вище відповіді в деяких випадках можуть допомогти, і той, хто насправді допоміг в одній із моїх ситуацій, але коли я використовував Carrierwave, попереднє рішення цього питання цього разу не вийшло.

ПЕРШИЙ ПІДХІД:

Для мене додав after :createвирішену для мене проблему так:

after :create do |b|
  b.update_column(:video_file, File.join(Rails.root, 'spec', 'fixtures', 'sample.mp4'))
end

Налаштування вбудованого відеофайлу, як-от video_file { File.new("#{Rails.root}/spec/fixtures/sample.mp4") }, не вийшло, і він повідомляв про помилки.

ДРУГИЙ ПІДХІД:

Визначте такий завод (змініть personal_fileсвоє ім’я вкладення):

FactoryGirl.define do
  factory :contact do
    personal_file { File.new("#{Rails.root}/spec/fixtures/personal_files/my_test_file.csv") }
    personal_file_content_type 'text/csv'

  end
end

І додайте ці рядки до config/environemnts/test.rb:

config.paperclip_defaults = {
  url: "#{Rails.root}/spec/fixtures/:attachment/:filename",
  use_timestamp: false
}

-1

Що саме ви тестуєте? Ця скріпка успішно прикріпить файл? Це насправді здається тестом, з яким повинна працювати обробка скріпки, а не ваша програма.

Ти намагався

a.data { File.join(Rails.root, 'features', 'support', 'file.png') }

Ми використовуємо Machinist замість factory_girl і просто використовували такі речі

Image.blueprint do
  image { RAILS_ROOT + 'spec/fixtures/images/001.jpg' }
end

Хоча ми насправді не дуже тестуємо, коли це робимо, ми зазвичай просто хочемо мати дійсний Imageоб’єкт.


У мене є моделі, для яких потрібна дійсна асоціація з моделлю, що підтримує Paperclip, сама з дійсним вкладенням.
Ерік
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.