Come progettare un test unitario per salvaguardare la dipendenza dallo stato interno

0

Sto facendo TDD. Diciamo che mi aspetto un metodo m di qualche classe C per chiamare qualche funzione f (per mantenere le cose veramente semplici).

Come progetterei un unit test che verrebbe a prendere e quindi fallire, se m dovesse essere implementato come:

m(func f)
{
  // let's say some_internal_counter starts at 0 when object initialised.
  if (some_internal_counter < 10)
  {
    f();
    some_internal_counter++;
  }
}

Un test unitario come il seguente non solo passerà, ma determinerà anche una copertura del 100% del codice:

C c = new C(); // C.some_internal_counter at 0, but the one writing this test doesn't know (or shouldn't know) this.
func f = SomeMockFunc();
c.m(f);
Expect(f).ToBeCalled();

Ma non è stato salvaguardato dal dipendere da uno stato interno (non autorizzato). Quindi il programma si aprirà verso prod (dato che tutto è verde) e non funzionerà quando m viene chiamato più di 10 volte.

    
posta Ash 10.04.2018 - 01:20
fonte

3 risposte

7

Edsger W. Dijkstra :

Testing shows the presence, not the absence of bugs.

Se vuoi dimostrare l'assenza di bug, devi passare alla verifica formale piuttosto che ai test. Ma come diceva Donald Knuth:

Beware of bugs in the above code; I have only proved it correct, not tried it.

Più seriamente, TDD non ti proteggerà mai da programmatori attivamente malintenzionati o fuorviati. Se stai facendo un reflex rosso-verde TDD, allora dovrebbe essere chiaro da una rapida recensione che questo codice non è la cosa più semplice che potrebbe far passare il test. Da quel punto puoi capire cosa il requisito aggiuntivo è (se esiste) e implementare un test corrispondente. Trovare codice non necessario (e quindi spesso buggato) può essere un effetto collaterale molto potente del TDD.

    
risposta data 10.04.2018 - 02:07
fonte
1

Il test unitario è generalmente un test della scatola bianca. Scrivi e leggi il codice e le prove insieme e pensi alla loro qualità insieme. Non si può mai scrivere un test che impedisca il passaggio di codice sufficientemente patologico e offra agli utenti un brutto momento.

Se stai facendo tdd come descritto da Bob Martin, non avresti mai scritto la funzione come mostrato. Martin sostiene solo la scrittura del codice minimo necessario per superare i test. L'implementazione di m è molto più complessa di quanto richiesto per superare i test.

D'altra parte se non stai facendo tdd ma stai scrivendo il test unitario dopo il codice dovresti guardare il codice e fare uno sforzo per testare i vari modi in cui può essere eseguito. Ogni volta che vedi una condizione if nel codice, preferisci scrivere un test per il ramo falso e uno per il ramo vero.

    
risposta data 10.04.2018 - 02:15
fonte
-2

safeguarded against being dependent on some (unauthorised) internal state

I test unitari non sono per questo. Usa il cervello, gli occhi e le dita e rimuovi le variabili che tracciano lo stato.

    
risposta data 21.04.2018 - 20:45
fonte

Leggi altre domande sui tag