come costante di test unitario che definisce un dettaglio di implementazione?

3

Come faccio a testare un'unità una costante che definisce un dettaglio di implementazione? e dovrei?

Per esempio diciamo che ho la seguente classe:

class A 
{
   private Cache _cache;
   const int timeToLiveInCache = 30; // 30 seconds of TTL

   A()
   {
      _cache = new Cache(timeToLiveInCache);
   }
}

Nel mio test di unità, come posso verificare che il mio TTL sia effettivamente 30 secondi?

La classe Cache è stata testata e so che qualunque input TTL I funzionerà come previsto, ma voglio un test unitario per assicurarmi che la classe A usi effettivamente un TTL di 30 secondi. È anche una buona idea testare l'unità?

    
posta lezebulon 13.01.2016 - 22:57
fonte

2 risposte

2

I test unitari devono avere accesso a questa costante, per verificare che le voci della cache non vengano rimosse prima della scadenza del loro tempo di vita. Il valore reale dato è irrilevante, penserei.

Pertanto: rendi questa costante pubblica e documentala. Dopotutto, il tempo di vivere non è un segreto ma si traduce in conseguenze osservabili dall'esterno. Se lo desideri, puoi anche notare che il valore specifico di questa costante non è specificato e soggetto a modifiche. Ciò evita la duplicazione del valore costante nel codice e nei test. Se avessi duplicato tali informazioni, i tuoi test sarebbero più fragili.

Test errato:

mockTime = 0;
cache.put(value);
assert cache.contains(value);

mockTime += 30;

assert !cache.contains(value);

Test migliore:

mockTime = 0;
cache.put(value);
assert cache.contains(value);

mockTime += cache.TIME_TO_LIVE;

assert !cache.contains(value);
    
risposta data 13.01.2016 - 23:24
fonte
1

Prova a lavorare a un livello superiore: quale caso d'uso a cui si preoccupa l'azienda non funzionerà se TTL non è 30 secondi?

Più in generale:

Non scrivere test unitari per cose che non possono fallire; infastidisce il maiale.

Scrivere test che verifichino un'implementazione specifica di solito è una cattiva idea. Quando in un secondo momento avrai un modo migliore per implementare ciò che ti serve, tutti questi test verranno gettati via (o no), forse qualcuno dovrà esaminarli per cercare di capire se ci sono affari valore lasciato nascosto in loro - più sprechi!).

Il che non vuol dire che non sia bello avere un blocco e un placcaggio quando sei giù nelle trincee cercando di far funzionare qualcosa la prima volta. Ad esempio, quando stai facendo un picco di alcune funzionalità, i test specifici dell'implementazione possono essere di conforto, poiché consentono di identificare più rapidamente che cosa è andato storto, piuttosto che semplicemente quale requisito ha stato mancato.

Ad esempio, non dovresti scrivere un test per verificare getRandomNumber () Questo è solo squilibrato. Invece, scrivi test che assicurano che qualsiasi implementazione che supera i test sia accettabile per il business.

Considera l'ordinamento, ad esempio. A meno che ciò che si sta effettivamente spedendo sia il Ordinamento di bolle su scala Web migliore al mondo , non ci si preoccupa dei dettagli di implementazione sotto il cofano. Ciò che ti interessa è se un gruppo di casi d'uso patologici o meno produca risultati accettabili. Ti interessa sapere se alcuni casi di dati patologici fanno diventare instabile il tuo comparatore, e così via.

Detto questo, certi tipi di cose sono un vero dolore da provare. Caches sarebbe uno di loro; una cache è fondamentalmente un compromesso memoria / computazione, di solito fatto per migliorare uno SLA, piuttosto che fornire garanzie di correttezza aggiuntive. Quindi un test unitario duraturo per questo potrebbe sembrare

given(User.hasBeenIdleFor(MINUTES(29)))
.when(User.loadsPage())
.expect(Probability(Page.loadsWithin(MILLISECONDS(1)))>Probability.NINES(3));

e poi provi a capire come implementare quel test per soddisfare

Probability.testExecutesWithin(SECONDS(1)) > Probability.NINES(2);

Whee - momenti divertenti.

    
risposta data 13.01.2016 - 23:38
fonte

Leggi altre domande sui tag