2010-12-14 10 views
8

Nell'utilizzo della mia applicazione, mi sono imbattuto in una condizione di competizione in un codice che utilizza un NSOperationQueue per eseguire attività in modo asincrono dopo eventi attivati ​​dall'utente. So come risolvere le condizioni della gara, poiché si tratta di uno stupido errore di progettazione che non approfondirò, ma mi piacerebbe provare l'errore con un caso di test (in modo che non ritorni durante l'ottimizzazione/refactoring lungo la linea). Questo mi ha perplesso. Come si fa a testare qualcosa che è multi-thread, specialmente quando lo scopo del test è generare una condizione di competizione?Codice basato su thread di test unitario? Forzare una condizione di gara

Qualcuno ha qualche link a materiale di riferimento a cui posso riferirsi quando si tratta di trattare thread e test di unità? Sono particolarmente interessato alla generazione di condizioni di gara.

+0

Suppongo che si possa prendere in giro qualsiasi struttura di dati condivisa e all'interno dei propri oggetti mock è possibile eseguire qualsiasi sincronizzazione necessaria per eseguire thread diversi nell'ordine "errato". –

risposta

4

È necessario accertarsi che la sequenza di eventi che causa la condizione di competizione si verifichi effettivamente durante il test. Per questo, è necessario influenzare l'interleaving del filo all'interno del test case.

È possibile ottenere ciò con la sincronizzazione aggiuntiva (condizionale) o, (più semplice e meno affidabile) i timer aggiuntivi. Metti alcune chiamate sleep() nelle sezioni critiche per assicurarti che corrano abbastanza a lungo perché l'altro thread arrivi allo stato indesiderato. Quando hai funzionato, sostituisci le chiamate a riposo con la sincronizzazione esplicita (ad esempio, blocca un thread finché l'altro non riconosce effettivamente di essere arrivato).

Quindi rendere tutto condizionale su un flag globale impostato dal test case.

+3

Onestamente non penso che l'accoppiamento del codice di produzione effettivo a questo particolare test sia una buona idea. Significa che devi stare attento a non alterare quell'accoppiamento ogni volta che si rifatta il codice, che sconfigge il punto di avere questo test in primo luogo. –

+0

No, la fragilità wrt. il refactoring supporta effettivamente questo approccio di test. Quando ti rifatti, dovrai ripensare alle condizioni della gara. Quindi, potresti scoprire che il refactoring ne ha introdotti di nuovi, o che quelli a cui prima era vulnerabile non potevano più accadere. –

+0

Semplicemente non vedo come questo "costringa" chiunque a refactoring a ripensare le potenziali condizioni di gara, o che farlo sia effettivamente utile. Chiaramente, pensare alle condizioni di gara non ha funzionato la prima volta. Chiunque esegua il refactoring del codice in modo significativo potrebbe dover buttare fuori completamente il codice di test esistente e scriverne di nuovi, oppure rendere il codice di test inutile. Ad ogni modo, sconfigge lo scopo di avere il codice di prova. Meglio sarebbe avere un codice di test che non inquini il codice di base principale, ma invece segnala la build come se fosse rotta. –