Bagaimana Saya Menggunakan Factory Girl Untuk Menghasilkan Lampiran Penjepit Kertas?

119

Saya memiliki model Person yang memiliki banyak Gambar, di mana gambar memiliki bidang lampiran Penjepit Kertas yang disebut data, versi singkatnya ditampilkan di bawah ini:

class Person
  has_many :images
  ...
end

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

Orang harus memiliki setidaknya satu Gambar yang dilampirkan.

Saat menggunakan FactoryGirl, saya memiliki kode yang mirip dengan berikut ini:

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

(NB Saya juga mencoba kode yang dikomentari di atas juga mencoba) Sebagian besar waktu ketika saya menjalankan fitur mentimun, saya mendapatkan kesalahan seperti berikut:

Tidak ada file atau direktori seperti itu - /tmp/stream,9887,0.png (Errno :: ENOENT)

...

Terkadang tes berjalan dengan sukses.

Adakah yang bisa memberi tahu saya apa masalah yang saya alami di sini atau bagaimana mereka menggunakan FactoryGirl dan Paperclip bersama-sama untuk mencapai sesuatu seperti yang saya coba capai?

Saya menggunakan Rails 3.

Laz
sumber
2
Berikan suara untuk pertanyaan hanya untuk menggunakan Keyzer Soze saat Anda menguji nama!
Breno
Ketika saya melakukan ini ... foto dibuat dan ditempatkan di folder publik / sistem setiap kali saya menjalankan rangkaian pengujian. Foto-foto tidak akan rusak setelah rangkaian pengujian selesai dijalankan. Apakah ada orang lain yang memperhatikan ini?
Jwan622

Jawaban:

86

Anda dapat menggunakan fixture_file_upload

include ActionDispatch::TestProcess di test helper Anda, berikut adalah contoh pabrik:

include ActionDispatch::TestProcess

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

Dalam contoh di atas, spec/photos/test.png harus ada di direktori root aplikasi Anda sebelum menjalankan pengujian.

Perhatikan, itu FactoryBotadalah nama baru untuk FactoryGirl.

DanS
sumber
2
Jawaban ini sepenuhnya benar tetapi mungkin lebih jelas untuk mengatakan bahwa TestProcess termasuk perlu disertakan dengan Pabrik dan tidak hanya di spec_helper Anda.
Andrew Hubbs
2
Terima kasih atas klarifikasinya, Andrew. Anda mungkin juga harus menempatkan "include ActionDispatch :: TestProcess" sebelum blok FactoryGirl.define (yang tidak terjadi dalam inti ini: gist.github.com/313121 ).
Sam
3
Juga, { }wajib diisi. Rusak tanpanya
kentang besar
3
Klarifikasi lebih lanjut: yang include ActionDispatch::TestProcessharus dimasukkan di bagian paling atas dari file pabrik, di luar itu FactoryGirl.define do...endblok.
Frank Koehl
49

Sintaks FG yang lebih baru dan tidak perlu menyertakan

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

atau, lebih baik lagi,

factory :user do
  avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") } 
end
Neal
sumber
2
Saya menyukainya, tetapi perlu diingat bahwa rails 4 menghapus app / assets / images / rails.png, jadi Anda harus memperhitungkan perubahan itu :)
stephenmurdoch
38

Desmond Bowe di Pivotal Labs menyarankan untuk menghindari fixture_file_upload karena masalah kebocoran memori. Sebaliknya, Anda harus menyetel bidang penjepit kertas langsung di pabrik Anda:

factory :attachment do
  supporting_documentation_file_name { 'test.pdf' }
  supporting_documentation_content_type { 'application/pdf' }
  supporting_documentation_file_size { 1024 }
  # ...
end
Rick Quantz
sumber
Bekerja untuk saya. Juga cukup sederhana untuk tidak memerlukan file yang ada di folder spec / test.
bibstha
2
Selain menghindari kebocoran memori, pengujian dengan cara ini akan lebih cepat.
evedovelli
Entri blog yang disebutkan dipindahkan ke pivotal.io/blog
Karsten S.
Sayangnya, ini tidak berfungsi dengan validasi lampiran aktif content_type. Untuk itu Anda membutuhkan objek file yang valid.
Karsten S.
25

Saya telah menggunakan kode dalam inti di bawah ini:

Rel 2

http://gist.github.com/162881

Rel 3

https://gist.github.com/313121

deb
sumber
1
Hanya bertanya-tanya hal yang sama dan ini bekerja dengan baik. Terima kasih. Saya memasukkannya ke dalam sebuah penginisialisasi.
Todd
1
Sesuatu yang perlu diperhatikan: Inti di atas menggunakan sintaks FactoryGirl yang lebih lama. Jawaban DanS menggunakan sintaks baru.
Andrew Hubbs
12
file { File.new(Rails.root.join('spec', 'fixtures', 'filename.png')) }
Matthew Deiters
sumber
Ini adalah solusi fungsional paling sederhana.
superluminary
4

Coba gunakan ActionController :: TestUploadedFile. Anda cukup menyetel properti file ke instance TestUploadedFile dan paperclip akan menangani sisanya. Sebagai contoh

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

Jawaban di atas dalam beberapa kasus dapat membantu, dan yang benar-benar membantu dalam salah satu situasi saya, tetapi saat menggunakan gelombang pembawa, solusi sebelumnya dari pertanyaan ini tidak berhasil kali ini.

PENDEKATAN PERTAMA:

Bagi saya menambahkan after :creatememecahkan masalah untuk saya seperti ini:

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

Mengatur file video sebaris seperti video_file { File.new("#{Rails.root}/spec/fixtures/sample.mp4") } tidak berhasil dan melaporkan kesalahan.

PENDEKATAN KEDUA:

Tentukan pabrik seperti ini (ubah personal_fileke nama lampiran Anda):

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

Dan tambahkan baris ini ke config/environemnts/test.rb:

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

Apa yang sebenarnya Anda uji? Penjepit kertas itu akan berhasil melampirkan file? Itu benar-benar tampak seperti ujian yang harus ditangani penjepit kertas, bukan aplikasi Anda.

Sudahkah kamu mencoba

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

Kami menggunakan Machinist daripada factory_girl dan baru saja menggunakan hal-hal seperti

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

Padahal, kami tidak benar-benar menguji banyak ketika kami melakukan ini, kami biasanya hanya ingin memiliki Imageobjek yang valid .

theIV
sumber
Saya memiliki model yang memerlukan asosiasi yang valid dengan model yang mendukung Penjepit Kertas, dengan lampiran yang valid.
Eric