Bir Ataç Eklentisi Oluşturmak İçin Fabrikalı Kız Nasıl Kullanılır?


119

Resimlerin veri adı verilen, kısaltılmış bir versiyonu aşağıda gösterilen bir Ataç ek alanına sahip olduğu birçok Görüntüye sahip model Person var:

class Person
  has_many :images
  ...
end

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

Kişinin kendisine eklenmiş en az bir Görsel olması gerekir.

FactoryGirl'i kullanırken aşağıdakine benzer bir kodum var:

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

(Not: Yukarıda açıklanan kodu da denedim, denendi) Salatalık özelliklerini çalıştırdığımda çoğu zaman aşağıdakine benzer bir hata alıyorum:

Böyle bir dosya veya dizin yok - /tmp/stream,9887,0.png (Errno :: ENOENT)

...

Bazen testler başarıyla çalışır.

Burada yaşadığım sorunun ne olduğunu veya benim başarmaya çalıştığım şey gibi bir şeyi başarmak için FactoryGirl ve Paperclip'i nasıl birlikte kullandıklarını kimse bana söyleyebilir mi?

Rails 3 kullanıyorum.


2
Adınızı test ederken sadece Keyzer Söze'yi kullandığınız için soruya oy verin!
Breno

Bunu yaptığımda ... test paketini her çalıştırdığımda fotoğraflar oluşturuluyor ve genel / sistem klasörüne yerleştiriliyor. Test paketi çalıştıktan sonra fotoğraflar yok edilmez. Bunu fark eden başka biri var mı?
Jwan622

Yanıtlar:


86

Fixture_file_upload kullanabilirsiniz

include ActionDispatch::TestProcess test yardımcınızda, işte örnek bir fabrika:

include ActionDispatch::TestProcess

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

Yukarıdaki örnekte, spec/photos/test.pngtestlerinizi çalıştırmadan önce uygulamanızın kök dizininde bulunması gerekir.

Bunun FactoryBotyeni bir ad olduğunu unutmayın FactoryGirl.


2
Bu cevap tamamen doğrudur, ancak Test Sürecinin sadece spec_helper'ınıza değil, Fabrikaya dahil edilmesi gerektiğini söylemek daha açık olabilir.
Andrew Hubbs

2
Açıklama için teşekkürler Andrew. Ayrıca FactoryGirl.define bloğunun önüne "include ActionDispatch :: TestProcess" yerleştirmeniz gerekebilir (bu ana başlıkta olan bu değildir: gist.github.com/313121 ).
Sam

3
Ayrıca { }gereklidir. Onsuz kırılıyor
bigpotato

3
Daha fazla açıklama: include ActionDispatch::TestProcessfabrika dosyasının en üstüne , bloğun dışına yerleştirilmelidir FactoryGirl.define do...end.
Frank Koehl

49

Daha yeni FG sözdizimi ve eklemeye gerek yok

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

veya daha iyisi,

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

2
Hoşuma gitti, ancak rails 4'ün app / assets / images / rails.png dosyasını kaldırdığını unutmayın, bu nedenle bu değişikliği hesaba
katmanız gerekecek

38

Pivotal Labs'deki Desmond Bowe , bellek sızıntısı sorunları nedeniyle fixture_file_upload'dan kaçınılmasını öneriyor . Bunun yerine, ataç alanlarını doğrudan fabrikanızda ayarlamalısınız:

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

Benim için çalışıyor. Ayrıca, özellik / test klasöründe mevcut bir dosya gerektirmeyecek kadar basit.
bibstha

2
Bellek sızıntılarını önlemenin yanı sıra, bu şekilde testler daha hızlı olacaktır.
evedovelli

Bahsedilen blog yazısı pivotal.io/blog adresine
Karsten S.

Ne yazık ki bu, ek doğrulama açıkken çalışmaz content_type. Bunun için geçerli bir dosya nesnesine ihtiyacınız var.
Karsten S.



4

ActionController :: TestUploadedFile kullanmayı deneyin. File özelliğini bir TestUploadedFile örneğine ayarlayabilirsiniz ve gerisini ataç halledecektir. Örneğin

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

Bazı durumlarda yukarıdaki cevaplar yardımcı olabilir ve bu cevap benim durumlarımdan birinde gerçekten yardımcı oldu, ancak bir Carrierwave kullanırken, bu sorunun önceki çözümü bu sefer işe yaramadı.

İLK YAKLAŞIM:

Benim after :createiçin bir sorun benim için şu şekilde çözüldü:

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

Satır içi video dosyasını ayarlamak video_file { File.new("#{Rails.root}/spec/fixtures/sample.mp4") }işe yaramadı ve hata bildiriyordu.

İKİNCİ YAKLAŞIM:

Bunun gibi bir fabrika tanımlayın ( personal_fileek adınızı değiştirin ):

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

Ve bu satırları şuna ekleyin config/environemnts/test.rb:

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

-1

Tam olarak neyi test ediyorsunuz? Bu ataç, dosyayı başarıyla ekleyecek mi? Bu gerçekten sizin uygulamanızın değil, ataçların üstesinden gelmesi gereken bir test gibi görünüyor.

Denedin mi

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

Factory_girl yerine Machinist kullanıyoruz ve sadece

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

Bununla birlikte, bunu yaptığımızda pek test etmiyor olsak da, tipik olarak sadece geçerli bir Imagenesneye sahip olmak isteriz .


Ataç özellikli bir modelle, kendisi de geçerli bir eke sahip geçerli bir ilişki gerektiren modellerim var.
Eric
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.