Unit testing time-bound code

7

Attualmente sto lavorando a un'applicazione che esegue molte operazioni con limiti di tempo. Cioè, basato su long now = System.currentTimeMillis(); , e combinato con uno schedulatore, calcolerà i periodi di tempo che parametrizzano l'esecuzione di alcune operazioni. per esempio:.

public void execute(...) { // executed by an scheduler each x minutes
    final int now = (int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
    final int alignedTime = now - now % getFrequency() ;
    final int startTime = alignedTime - 2 * getFrequency(); 
    final int endTimeSecs = alignedTime - getFrequency(); 
    uploadData(target, startTime, endTimeSecs);
}

La maggior parte delle parti dell'applicazione sono testate in unità indipendentemente dal tempo (in questo caso, uploadData ha un test unitario naturale), ma mi chiedevo quali sono le migliori pratiche per testare parti legate al tempo che si basano su System.currentTimeMillis() ?

    
posta maasg 09.07.2012 - 16:40
fonte

3 risposte

11

Si DEFINITIVAMENTE si dovrebbe organizzare per mock-out l'orologio di sistema. Ho lavorato in C ++, e o faccio in modo che l'oggetto prenda un oggetto 'interfaccia orologio', oppure io uso un'interfaccia interna o un puntatore di funzione all'interno della classe che poi sostituisco quando faccio il codice di test.

In realtà ho avuto esperienza con NON prendendo in giro l'orologio di sistema e credimi quando te lo dico - non finisce mai bene.

In realtà ci sono diversi problemi con i test delle unità che fanno affidamento sull'orologio del sistema reale. La prima è che è semplicemente difficile da fare (finisci per afferrare il tempo, poi fai cose, poi riprendi l'orologio per verificare), ma è anche noioso perché i tempi di test diventano limitati in tempo reale (se stai provando qualcosa questo è 30 secondi, quindi è più di 30 secondi per eseguire il test).

Il problema più importante, però, è che rende i tuoi test MOLTO BRICI.

I test inizieranno a fallire in modo casuale a causa di problemi di caricamento del server. Falliranno a caso, e invierai il tempo a controllare gli errori più e più volte.

Non ne vale la pena: usa un'interfaccia per l'orologio di sistema e prendi in giro il codice di prova.

    
risposta data 09.07.2012 - 17:18
fonte
12

Invece di chiamare System.currentTimeMillis() direttamente, lo avvolgerei nella tua classe e inserirli dinamicamente nel tuo codice. Ciò che ti dà è la capacità di deridere l'oggetto wrapper per restituire un tempo fisso nel contesto dei test. Ciò significa che il tuo codice di test non chiamerà mai System.currentTimeMillis() , ma preferirà avere un tempo prefissato per lavorare con quello che puoi prevedere.

    
risposta data 09.07.2012 - 16:44
fonte
6

Non utilizzare System.currentTimeMillis (), ma programmare tutto usando il tempo su un'interfaccia che restituisce il tempo. Durante i test unitari, prendi in giro l'interfaccia, altrimenti non puoi semplicemente testare nulla usando il tempo in modo affidabile. Questo ha anche il vantaggio che se decidi che currentTimeMillis non è abbastanza preciso, puoi sostituirlo con un altro metodo in un singolo punto e tutto ora utilizzerà quell'altro metodo.

    
risposta data 09.07.2012 - 16:44
fonte

Leggi altre domande sui tag