¿Cómo utilizo Factory Girl para generar un clip adjunto?


119

Tengo una persona modelo que tiene muchas imágenes, donde las imágenes tienen un campo adjunto de clip de papel llamado datos, una versión abreviada que se muestra a continuación:

class Person
  has_many :images
  ...
end

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

Se requiere que la persona tenga al menos una imagen adjunta.

Cuando uso FactoryGirl, tengo un código similar al siguiente:

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

(Nota: también probé el código comentado anteriormente) La mayoría de las veces cuando ejecuto funciones de pepino, aparece un error similar al siguiente:

No existe tal archivo o directorio - /tmp/stream,9887,0.png (Errno :: ENOENT)

...

A veces, las pruebas se ejecutan con éxito.

¿Alguien puede decirme cuál es el problema que tengo aquí o cómo usan FactoryGirl y Paperclip juntos para lograr algo como lo que estoy tratando de lograr?

Estoy usando Rails 3.


2
¡Vota a favor la pregunta solo por usar Keyzer Soze como nombre de prueba!
Breno

Cuando hago esto ... las fotos se generan y se colocan en la carpeta pública / del sistema cada vez que ejecuto el conjunto de pruebas. Las fotos no se destruyen una vez que la suite de pruebas termina de ejecutarse. ¿Alguien más nota esto?
Jwan622

Respuestas:


86

Puede usar fixture_file_upload

include ActionDispatch::TestProcess en su ayudante de prueba, aquí hay una fábrica de ejemplo:

include ActionDispatch::TestProcess

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

En el ejemplo anterior, spec/photos/test.pngdebe existir en el directorio raíz de su aplicación antes de ejecutar sus pruebas.

Tenga en cuenta que FactoryBotes un nombre nuevo para FactoryGirl.


2
Esta respuesta es totalmente correcta, pero puede ser más claro decir que la inclusión de TestProcess debe incluirse con Factory y no simplemente en su spec_helper.
Andrew Hubbs

2
Gracias por la aclaración, Andrew. También puede tener que colocar "incluir ActionDispatch :: TestProcess" antes del bloque FactoryGirl.define (que no es lo que sucede en esta esencia: gist.github.com/313121 ).
Sam

3
Además, { }son obligatorios. Se rompe sin él
bigpotato

3
Aclaración adicional: include ActionDispatch::TestProcessdebe insertarse en la parte superior del archivo de fábrica, fuera del FactoryGirl.define do...endbloque.
Frank Koehl

49

Nueva sintaxis de FG y no es necesario incluir

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

o mejor aún,

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

2
Me gusta, pero tenga en cuenta que rails 4 elimina app / assets / images / rails.png, por lo que deberá tener en cuenta ese cambio :)
stephenmurdoch

38

Desmond Bowe de Pivotal Labs sugiere evitar fixture_file_upload debido a problemas de pérdida de memoria. En su lugar, debe configurar los campos del clip directamente en su fábrica:

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

Funciona para mi. También lo suficientemente simple como para no requerir un archivo existente en la carpeta de especificaciones / pruebas.
bibstha

2
Además de evitar pérdidas de memoria, de esta forma las pruebas serán más rápidas.
evedovelli

La publicación de blog mencionada se movió a pivotal.io/blog
Karsten S.

Desafortunadamente, esto no funciona con la validación de archivos adjuntos activada content_type. Para eso necesita un objeto de archivo válido.
Karsten S.



4

Intente usar ActionController :: TestUploadedFile. Puede simplemente establecer la propiedad del archivo en una instancia de TestUploadedFile y el clip debe encargarse del resto. Por ejemplo

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

Las respuestas anteriores en algunos casos pueden ayudar, y la que realmente ayudó en una de mis situaciones, pero al usar un Carrierwave, la solución anterior de esta pregunta no funcionó esta vez.

PRIMER ENFOQUE:

Para mí, agregando un after :createproblema resuelto para mí de esta manera:

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

La configuración del archivo de video en línea como video_file { File.new("#{Rails.root}/spec/fixtures/sample.mp4") }no funcionó y estaba informando errores.

SEGUNDO ENFOQUE:

Defina una fábrica como esta (cambie personal_filea su nombre de archivo adjunto):

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

Y agregue estas líneas al config/environemnts/test.rb:

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

-1

¿Qué estás probando exactamente? ¿Ese clip adjuntará correctamente el archivo? Eso realmente parece una prueba que debe manejar el clip, no su aplicación.

Has probado

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

Usamos Machinist en lugar de factory_girl y acabamos de usar cosas como

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

Sin embargo, en realidad no estamos probando mucho cuando hacemos esto, normalmente solo queremos tener un Imageobjeto válido .


Tengo modelos que requieren una asociación válida con un modelo habilitado para Paperclip, con un adjunto válido.
Eric
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.