Libreria per falsi errori intermittenti in base alla politica definita dal tester?

2

Sto cercando una libreria che posso usare per aiutare a deridere un componente del programma che funziona solo in modo intermittente - di solito, funziona bene, ma a volte fallisce.

Ad esempio, supponiamo di dover leggere i dati da un file e il mio programma deve evitare di bloccarsi o bloccarsi quando una lettura non riesce a causa di un arresto anomalo della testa del disco. Mi piacerebbe modellarlo avendo una funzione di lettore di dati simulato che restituisce dati falsi il 90% delle volte, ma blocca o restituisce spazzatura in caso contrario. Oppure, se sto sottoponendo a prove di stress il mio programma completo, potrei attivare il codice di debug nel mio vero modulo di lettore di dati per fare in modo che restituisca dati reali il 90% delle volte e si blocchi altrimenti.

Ora, ovviamente, in questo particolare esempio potrei semplicemente programmare il mio simulatore manualmente per testare una routine random() . Tuttavia, stavo cercando un sistema che consenta l'implementazione di qualsiasi politica di errore che desidero, tra cui:

  • Fallisce casualmente il 10% delle volte
  • Riuscire 10 volte, fallire 4 volte, ripetere
  • Fallisce in modo semi-casuale, in modo tale che un errore tende a essere seguito da una serie di altri fallimenti
  • Qualsiasi criterio che il tester desideri definire

Inoltre, mi piacerebbe essere in grado di modificare la politica di errore in fase di esecuzione, utilizzando le manopole o gli switch esterni che possono essere rimossi (insieme al resto della libreria) prima di spedire il codice. (Se il componente è caricato da un'infrastruttura per le dipendenze, potremmo fornire la simulazione come un'implementazione nella versione di prova e trattenerla dalla build spedita.)

In pig-Java, immaginerei un'interfaccia FailureFaker in questo modo:

interface FailureFaker {
    /**
        Return true if and only if the mocked operation succeeded.
        Implementors should override this method with versions consistent
        with their failure policy.
     */
    public boolean attempt();
}

E ogni criterio di errore sarebbe una classe che implementa FailureFaker ; per esempio ci sarebbe un PatternFailureFaker che avrebbe avuto successo N volte, poi fallire M volte, poi ripetere, e un AlwaysFailFailureFaker che userei temporaneamente quando ho bisogno di simulare, ad esempio, qualcuno che rimuove il mio disco esterno i miei dati era su. La politica potrebbe quindi essere utilizzata (e modificata) nel mio codice oggetto simulato in questo modo:

class MyMockComponent {
    FailureFaker faker;

    public void doSomething() {
        if (faker.attempt()) {
            // ...
        } else {
            throw new RuntimeException();
        }
    }

    void setFailurePolicy (FailureFaker policy) {
        this.faker = policy;
    }
}

Ora, questo sembra essere qualcosa che farebbe parte di una biblioteca derisoria, quindi non sarei sorpreso se fosse stato fatto prima. (In realtà, ho avuto l'idea da Scrittura di codice solido di Steve Maguire, dove ha discute questa idea esatta alle pagine 228-231, dicendo che tali strutture erano comuni nel codice Microsoft di quell'era degli anni '90.) Tuttavia, ho solo familiarità con EasyMock e jMockit per Java, e nessuno dei due AFAIK ha questa funzione, o qualcosa del genere simile con diversa sintassi.

Quindi, la domanda: esistono librerie come quelle sopra descritte? Se lo fanno, dove li hai trovati utili? Se non li hai trovati utili, perché no?

    
posta Michael Ratanapintha 03.03.2011 - 06:52
fonte

1 risposta

2

Corri il rischio di introdurre il codice di test nel codice di produzione

Non conosco alcuna libreria che fornisca questa funzione esatta, probabilmente perché è qualcosa che opera a un livello più alto di astrazione di quello che fornisce. Cioè, normalmente useresti, diciamo, jMockit per fornire queste risposte durante la fase di test.

sicuramente non vuoi avere speciali "test only" nel tuo codice di produzione.

Ricorda che l'obiettivo del codice di test è verificare che i percorsi corretti siano selezionati per determinate condizioni. A tal fine, i framework di simulazione che hai menzionato forniscono un insieme ripetibile di condizioni di test che garantiscono un errore quando lo si desidera e consentono di verificare che il programma reagisca correttamente ad esso.

Quindi, come procedi nello stress test con un ambiente instabile?

Prima di iniziare lo stress test, sei già sicuro che la tua applicazione si comporterà correttamente, ma potrebbero esserci problemi di carico o relativi ai thread che non hai previsto.

In tal caso, esegui l'applicazione in un contenitore che supporta l'accesso al percorso di classe di test (ad esempio Jetty) e fornisce una configurazione di test (ad es. Spring) che inietta le versioni mock di errore casuale delle tue classi all'avvio. L'applicazione viene quindi eseguita su una piattaforma di errore configurabile e puoi martellarla con i test di stress di tua scelta.

Se è necessario perfezionare i guasti, è sufficiente regolare la configurazione Spring per inserire meno o più classi di errori simulati, o modificare i mock come richiesto.

Ricorda che i framework mocking (in particolare jMockit) sono molto più lenti di un'implementazione fittizia realizzata a mano di un'interfaccia. Nell'interesse di mantenere un ambiente rappresentativo per gli stress test, è probabilmente necessario evitare l'approccio al framework.

Una volta che i test sono finiti e hai aggiornato i tuoi test per intrappolare tutti quei fastidi aggiuntivi, puoi lasciare le pedine di stress test che si trovano nel classpath di prova sicuro sapendo che nessun codice di test è passato in produzione.

    
risposta data 03.03.2011 - 12:57
fonte

Leggi altre domande sui tag