2012-03-08 13 views
11

Ho appena aggiunto convalide per un'immagine carrierwave a un modello e ora i test vengono eseguiti molto lentamente. Come posso accelerare questo processo? Mi sembra che ci debba essere un modo migliore.Test davvero lento con upload di file


ho corso senza convalide e usato per essere in grado di eseguire attraverso i miei test RSpec in circa 140 secondi, ma dato che ora convalidare presenza di :display_pic ho dovuto aggiungere upload di file vero e proprio al mio fabbrica del progetto. Questo ha aumentato a 240 secondi! 140 era già dalla parte pesante, questo è solo pazzesco.

This is how the carrierwave github page recommends setting up 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 

ho preso una test.jpg sopra solo un file di testo vuoto, quindi è essenzialmente come piccolo un file come possibile.

Ho anche seguito la raccomandazione carrierwave al test di setup:

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

risposta

6

con la convalida accadendo ora sempre che un'istanza viene creato il display_pic attributi si accede e il codice all'interno delle parentesi sarà eseguito

{ File.open(File.join(Rails.root, 'spec', 'support', 'projects', 'display_pics', 'test.jpg')) } 

(si viene eseguito pigramente). Questo sta causando la differenza nel tempo.

Un'opzione per evitare questo è quello di impostare to_create per la definizione fabbrica di quello che io non consiglio:

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 
+2

Preferirei non bypassare le convalide. In paperclip puoi riempire il campo dell'immagine con una stringa, speravo in qualcosa del genere. –

+0

Grazie per la risposta, capisco che è logico che ci vorrà più tempo per caricare, il tempo di caricamento è comunque troppo per i miei scopi di test, sperando in qualche modo di ridurlo al minimo. –

+0

Questa è la soluzione migliore che ho visto fino ad ora, e funziona, grazie –

9

Sono i caricamenti memorizzati localmente o hanno intenzione di un servizio cloud come S3? Se è quest'ultimo, probabilmente è ciò che sta uccidendo le prestazioni del test.

Per i test, è sempre buona pratica prendere in giro eventuali dipendenze esterne. Se questo è il tuo problema, dovresti usare uno strumento per deridere la connessione. Penso che il fog gem abbia un supporto integrato per questo.

Aggiornamento: Regarding the answer by Jefferson Girao, Ho usato un trucco per evitare l'apertura di un file di test e, invece, l'uso di StringIO per simulare i file di test per scopi di fabbrica. Questo funziona meglio perché evita l'accesso al disco:

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 
+0

Sì, grazie, questo è già stato fatto 'config.storage =: linea file' nelle forze del blocco di configurazione onda portante che, nella produzione è impostato ad appannarsi –

+0

Interessante. Allora sono fuori di ipotesi. Scusate. –

+0

Haha, anche io ... –

1

Probabilmente avete considerato questo già, ma è il 100 sec rallentamento relativo ad un singolo caricamento di file? Se è un aggregato su tutti i test, ci deve essere un modo per strutturarli in modo da avere un singolo test (o alcuni) che convalidano la presenza del file, e il resto del tempo lo si prende in giro.

+0

Suggeriresti qualcosa di diverso da Jefferson Girao o sei d'accordo? –

1

Ho appena riscontrato questo problema, potrebbe essere utile risolverlo memorizzando il file in memoria anziché lasciare che la fabbrica legga l'immagine dal disco ogni singolo test. Sto usando qualcosa come il seguente.

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 

credo di avere risparmiato tempo circa il 10% sul mio suite di test, ma la mia suite di test è variabile tranquilla, quindi non posso essere assolutamente sicuro. In ogni caso, è solo una cosa da considerare se qualcuno tocca questo problema.

Non mi piace molto la soluzione che richiede di non convalidare il modello.Immagino che questo sia simile alla risposta StringIO di Wolfram Arnold, anche se penso che in questo modo sia un po 'più facile da capire.

3

Con ispirazione da @jeffersongirao e @Wolfram Arnold:

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 

Due cose chiave qui:

  1. setter di upload di CarrierWave può dare un senso a tutta una serie di cose. Lo fanno avvolgendo ciò che ottengono in un CarrierWave::SanitizedFile. Una delle cose che può prendere è un hash, come qui.

  2. CarrierWave::SanitizedFile si preoccupa se il file è vuoto. Ho passato troppo tempo a chiedermi perché non avrebbe accettato il mio StringIO.new. Ha bisogno che ci sia qualcosa lì dentro, ma non gli importa cosa. Gli ho dato un koala.