TDD: come vengono svuotati i test obsoleti?

5

Stavo leggendo alcune domande su TDD e ho trovato il mio.

Capisco che TDD sia un modo per sviluppare o catturare le specifiche / i requisiti interni dettagliati per il codice nel corso della stesura di quel codice.

Procediamo passo dopo passo e aggiungiamo proposizioni falsificabili al corpo della specifica sotto forma di test. Mostriamo che questi sono falsi e poi scriviamo il codice per renderli veri. Quindi refactoring mantenendoli veri.

Il problema è, come facciamo a sapere che tutti i test esistenti sono restanti falsificabili (per quanto riguarda la loro funzione originale)?

Durante l'aggiunta di alcuni nuovi elementi al codice tramite questo processo, supponiamo che alcuni test possano facilmente diventare obsoleti nel seguente senso: quei test sono stati inizialmente associati ad alcuni cambiamenti specifici, e se tale cambiamento è ora ripristinato nel attuale base, forse passano ancora. Qualunque cosa li stia facendo passare ora non è quella caratteristica originale che li ha capovolti dal non riuscire a passare.

Quei test / specifiche sembrano immondizie che aggiungono massa alla base delle specifiche senza alcuna sostanza. Oppure c'è ancora un valore in un test che non diventa falso se viene ripristinato il codice originale che lo ha reso vero, e non è ovvio quale cambiamento di codice altro nella base attuale lo renderebbe falso ?

C'è qualche processo TDD per identificare questi test? E poi vengono rimossi o riscritti o cosa?

O, in alternativa, questo è completamente impedito in qualche modo?

    
posta Kaz 29.07.2017 - 00:59
fonte

5 risposte

4

Una delle due cose è sbagliata qui.

In realtà non hai seguito TDD

Se segui TDD, scrivi un test in errore, quindi scrivi il codice per passare il test. Se rimuovi il codice che lo fa passare, allora il tuo test dovrebbe essere rotto. Forse non hai effettivamente seguito TDD e quindi hai costruito un test auto-passeggero.

I tuoi test verificano la mancanza di un problema piuttosto che il successo

I test unitari non dovrebbero essere progettati per testare i problemi. Dovrebbero essere progettati come una dichiarazione di fatto, che deve essere confermata. Ad esempio:

@Test
public void tableIsSortedAlphabetically() {
    Table t = new Table();
    t.addRow("Hello");
    t.addRow("World");
    t.addRow("Apple");
    assertEquals("Apple", t.getRow(0));
}

Nota come questo è formulato. Stiamo testando che qualcosa è ordinato in un modo particolare. Se il test è progettato in questo modo e viene implementato correttamente, non è possibile rimuovere il codice che ordina una tabella in ordine alfabetico senza che questo test fallisca.

Ecco un test che passerebbe comunque se il codice sotto test fosse stato rimosso.

@Test
public void userCanBeCreated() {
    User user = new User();
    user.setFirstName("Johnny");
    user.setLastName("Appleseed");

    try {
        user.save();
    }
    catch (Exception e) {
        fail(e);
    }
}

Se l'implementazione di user.save() è stata modificata per non fare nulla, questo test passerebbe comunque perché il test in realtà non verifica se il comportamento è corretto, ma semplicemente verifica che non abbia esito negativo.

    
risposta data 29.07.2017 - 02:55
fonte
3

The problem is, how do we know that all the existing tests are staying falsifiable (with regard to their original feature)?

Una risposta è effettuare i test immutable

Lo schema di base di TDD è questo: si implementa un test, lo si vede fallire, si aggiorna il codice di produzione, lo si vede passare. Finché il test rimane invariato da questo punto, puoi essere certo che l'attuale implementazione continua a soddisfare tale limite.

Those tests/specifications seem like garbage which adds bulk to the specification base without any substance. Or is there still value in a test which doesn't go false if the original code change which made it true is reverted

Sì, perché il test stesso è ancora la documentazione delle specifiche. Normalmente un buon test non impone una specifica implementazione - se così fosse, il refactoring non funzionerebbe. Invece, il test limita l'insieme di possibili implementazioni a quelle che producono un risultato specifico.

Is there some TDD process to identify these tests?

Non proprio. Esistono alcuni protocolli che puoi applicare per provare a identificare i test che non limitano più nulla: test della mutazione, per esempio.

And are they then removed or rewritten or what?

Se la specifica è cambiata, puoi ritirare un test. Se la specifica è invariata, ma hai perso la fiducia nel test, quindi introduci un nuovo test, stabilisci fiducia in esso e poi ritira il vecchio.

    
risposta data 29.07.2017 - 13:21
fonte
1

I test sono mirati al comportamento. Non righe di codice.

La copertura del codice è buona, ma se riesco a ottenere ciò che voglio senza codice mi sembra buona.

Ciò che mi disturba è l'idea che il test non sia falsificabile. Non dovresti fare il test se non fosse una volta falso. Ma se si aggiunge una linea di codice che fa passare il test 2 e fa anche passare il test 1 che viene passato solo a causa dell'altro codice, allora è il momento di cancellare quell'altro codice, ora inutile. Ma anche senza cancellarlo, il test è ancora falsificabile. Devi solo rompere una linea diversa da codice per farlo.

Un test potrebbe sapere quale metodo chiama durante il test ma non sa dove è codificato il comportamento che il metodo mostra. Quindi, come potrei insistere sul fatto che c'è un problema con un test che diventa falso quando dovrebbe, cioè quando il comportamento si interrompe, solo perché il codice di comportamento è cambiato?

Ora tutto ciò che è stato detto, se non puoi guardare il test e il codice e capire dove è codificato il comportamento sotto test hai problemi più grandi.

Questo non significa che i test non debbano mai morire. Dovresti cambiare anche i tuoi test.

is this entirely prevented somehow?

Esamina periodicamente i tuoi test. Dovresti farlo comunque. Ne vedi uno che non sei sicuro di come possa essere falsificato, ferma tutto e vai a rompere qualcosa per renderlo falso. Questo è come testare il test.

    
risposta data 29.07.2017 - 05:08
fonte
0

Non dovresti pensare a test come test di linee di codice specifiche . Piuttosto, un test verifica che un aspetto di un requisito sia soddisfatto dal sistema o sottosistema in un modo o nell'altro.

Un test non sarà obsoleto a condizione che il requisito sia presente, anche se il codice che in origine soddisfa il requisito è completamente riscritto o sostituito.

Finché un test tocca effettivamente il sistema, ha il potenziale di diventare rosso, se qualcuno apporta una modifica al codice. Voglio dire, se qualcuno ha cancellato tutto il codice, sicuramente tutti i test fallirebbero.

    
risposta data 29.07.2017 - 13:52
fonte
0

Uno dei vantaggi di TDD è che sei costretto a scrivere codice contro le astrazioni. Quindi quando riconosci alcune logiche che possono essere spostate all'esterno dell'unità corrente dietro l'astrazione e passate nell'unità come dipendenza. Finisci con un mucchio di astrazioni da cui dipende la tua unità.

Con le astrazioni non hai bisogno di cambiare l'implementazione, ma solo implementarne una nuova. Nei casi in cui è possibile riconoscere classi non referenziate da nessuno, la maggior parte dell'IDE fornisce questa funzionalità e rimuoverle con test corrispondenti.

    
risposta data 31.07.2017 - 20:49
fonte

Leggi altre domande sui tag