2015-08-06 11 views
6

(pubblicato già allo https://www.ruby-forum.com/topic/6876320, ma crosspost qui, perché non ho ricevuto una risposta finora).Ruby: Minitest, unità di test e variabili di istanza

Una domanda sulla parallelizzazione test in Minitest eo Test :: Unit/(vale a dire l'uso corretto del parallelize_me!):

Si supponga che ho alcuni metodi di supporto, che sono necessari per diverse prove. Dalla mia comprensione, non ho potuto fare qualcosa di simile a un tale metodo (esempio semplificato):

def prep(m,n) 
@pid = m 
@state = n 
end 

def process 
if @stat > 5 && @pid != 0 
    ... 
else 
    ... 
end 
end 

penso che non posso fare questo in Minitest e test di unità, perché se io chiamo di preparazione e di processo da molte delle mie funzioni di test, i test non possono più essere parallelizzati - quelle funzioni di test impostano tutte e leggono la stessa variabile di istanza. Destra?

Ora, la mia domanda è, se la seguente approccio sarebbe sicuro per parallelizzazione: Faccio tutte queste variabili di istanza mutabili un hash, che ho inizializzarla nella configurazione come questa:

def setup 
    @pid ||= {} 
    @state ||= {} 
end 

miei "metodi helper "ricevere una chiave (ad esempio, il nome del metodo di prova) e utilizzarlo per accedere al 'proprio' elemento di un hash:

def prep(key,m,n) 
@pid[key] = m 
@state[key] = n 
end 

def process 
if @stat[key] > 5 && @pid[key] != 0 
    ... 
else 
    ... 
end 
end 

e 'un po' brutto, ma: si tratta di un approccio affidabile? Questo modo di accedere a un hash thread-safe? Come posso farlo meglio?

risposta

1

Almeno in Minitest si può tranquillamente fare, per esempio,

setup do 
    @form = Form.new 
end 

senza @form confondersi tra i test in parallelo, in modo da questo approccio dovrebbe essere al sicuro troppo:

def setup 
    @stat = m 
    @pid = n 
end 

il che significa che il tuo approccio originale dovrebbe essere al sicuro.

================

UPDATE

considerare quanto segue sostanza con un pezzo di codice che definiscono 100 diverse prove di accesso @random che è impostato in setuphttps://gist.github.com/bbozo/2a64e1f53d29747ca559

si noterà che la roba impostato in setup non è condivisa tra i test, che viene eseguito prima di ogni prova, praticamente ogni prova è incapsulato in modo filo di sicurezza non è un problema.

+0

Come funziona il mio approccio originale?'setup' è chiamato giusto prima di ogni caso di test, e le variabili di istanza (@stat ...) sono condivise tra i casi di test. Se i casi vengono eseguiti in parallelo (in più thread), abbiamo delle condizioni di competizione sulle variabili di istanza. – user1934428

+0

@ user1934428, si spera che il mio aggiornamento aiuti :) – bbozo

+0

Lo fa davvero! Tuttavia, il codice gist che hai scritto, in realtà non prova il caso. Nella maggior parte dei casi, l'output è solo una sequenza di setup/test/setup/test/..., quindi anche se la variabile fosse condivisa tra i test, si otterrebbe l'output. I due casi, in cui l'output è setup/setup/test/test, potrebbero, forse, un artefatto del buffer di output. Mi sono preso la libertà di modificare un po 'il tuo codice per escludere questi casi e il codice modificato dimostra davvero la tua affermazione. – user1934428

0

Il tuo approccio con gli hash ha senso, e funzionerà per distinguere tra i thread. Il problema sta nel Global Interpreter Lock.

A meno che i metodi di supporto non siano legati all'IO (effettuare richieste HTTP, richieste socket, gestire file locali), non si vedrà un miglioramento della velocità perché Ruby sarà praticamente (per semplificare le cose) eseguire il codice sequenzialmente su più thread , senza un ordine di esecuzione garantito.

Buona fortuna!

Problemi correlati