La metodologia TDD può essere applicata dall'alto in basso?


13

Non sono chiaro come TDD, la metodologia, gestisca il caso seguente. Supponiamo che io voglia implementare l'algoritmo di fusione, in Python. Comincio scrivendo

assert mergesort([]) === []

e il test fallisce con

NameError: il nome 'mergesort' non è definito

Aggiungo quindi

def mergesort(a):
    return []

e il mio test ha superato. Quindi aggiungo

assert mergesort[5] == 5

e il mio test fallisce con

AssertionError

con cui faccio passare

def mergesort(a):
    if not a:
        return []
    else:
        return a

Successivamente, aggiungo

assert mergesort([10, 30, 20]) == [10, 20, 30]

e ora devo provare a fare questo passaggio. "Conosco" l'algoritmo di fusione e quindi scrivo:

def mergesort(a):
    if not a:
        return []
    else:
        left, right = a[:len(a)//2], a[len(a)//2:]
        return merge(mergesort(left)), mergesort(right))

E questo fallisce

NameError: il nome 'merge' non è definito

Ora ecco la domanda. Come posso scappare e iniziare a implementare mergeusando TDD? Sembra che non posso perché ho questo "appeso" non completato, test fallito mergesort, che non passerà fino al mergetermine! Se questo test si blocca, non potrò mai davvero fare TDD perché non sarò "verde" durante la costruzione delle iterazioni TDD merge.

Mi sembra di essere bloccato con i seguenti tre brutti scenari e vorrei sapere (1) quale di questi preferisce la comunità TDD o (2) c'è un altro approccio che mi manca? Ho visto diverse procedure guidate sullo Zio Bob TDD e non ricordo di aver mai visto un caso come questo prima d'ora!

Ecco i 3 casi:

  1. Implementare l'unione in una directory diversa con una suite di test diversa.
  2. Non preoccuparti di essere ecologico quando sviluppi la funzione di aiuto, tieni traccia manualmente dei test che vuoi davvero superare.
  3. Commenta (GASP!) O elimina le linee in mergesortquella chiamata merge; poi dopo aver iniziato mergea lavorare, rimetterli dentro.

Mi sembrano tutti sciocchi (o sto guardando questo male?). Qualcuno conosce l'approccio preferito?


2
Parte dell'obiettivo di TDD è aiutarti a creare un progetto software. Parte di quel processo di progettazione è scoprire ciò che è necessario per produrre il risultato desiderato. Nel caso in cui mergesort, poiché è già un algoritmo molto ben definito, questo processo di scoperta non è necessario e diventa quindi una questione di mappatura di ciò che già sai essere il progetto a una serie di test unitari. Presumibilmente, il test di livello superiore afferma che il metodo in esame accetta una raccolta non ordinata e ne restituisce una ordinata ...
Robert Harvey,

1
... I successivi test unitari approfondiranno gradualmente la meccanica reale di a mergesort. Se stai cercando il modo "giusto" per farlo, non ce n'è uno, se non quello di essere accurati sulla mappatura mergesortdell'algoritmo su una serie di test unitari; cioè dovrebbero riflettere ciò mergesortche fa realmente.
Robert Harvey,

4
Il design non cresce da soli test unitari; se ti aspetti che un mergesortprogetto emerga naturalmente dal rifrattore rosso-verde, ciò non accadrà se non guidi il processo in base alle tue conoscenze esistenti mergesort.
Robert Harvey,


1
In TDD mergedeve essere inventato solo sul palco "refactoring". Se vedi che il mergemetodo può essere introdotto per superare il test, mergesortfai prima passare i test senza mergemetodo. Quindi riformattare l'implementazione introducendo il mergemetodo.
Fabio,

Risposte:


13

Ecco alcuni modi alternativi per esaminare le tue opzioni. Ma prima, le regole di TDD, di zio Bob con enfasi da parte mia:

  1. Non è consentito scrivere alcun codice di produzione a meno che non si debba effettuare un test unit unit fallito.
  2. Non è consentito scrivere più unit test di quanto sia sufficiente per fallire; e gli errori di compilazione sono errori.
  3. Non è consentito scrivere più codice di produzione di quanto sia sufficiente per superare un test unitario non riuscito.

Quindi, un modo per leggere la regola numero 3 è che hai bisogno della mergefunzione per superare il test, quindi puoi implementarlo, ma solo nella sua forma più semplice.

Oppure, in alternativa, si inizia scrivendo l'operazione di unione in linea e quindi si esegue il refactoring in una funzione dopo aver eseguito il test.

Un'altra interpretazione è che stai scrivendo mergesort, sai che avrai bisogno di mergeun'operazione (cioè, non è YAGNI, che è ciò che la regola "sufficiente" tenta di ridurre). Pertanto, è necessario iniziare con i test per l'unione e solo successivamente procedere con i test per l'ordinamento generale.


Queste sono osservazioni davvero positive. Avevo pensato in precedenza al factoring e al factoring, ma come mergeè sorprendentemente disordinato, per quanto riguarda il caso (oltre che utile come standalone) l'idea di farlo come una funzione separata aveva più senso. Tuttavia, lo stile di farlo in linea nella sua forma di base e poi includerlo sul palco del cappello blu sembra davvero essere giusto e molto quello che stavo cercando.
Ray Toal,

@RayToal - In realtà mi sposto verso l'approccio di testare completamente l' mergeoperazione prima di fare l'ordinamento (oltre a test separati partitiondell'operazione). Penso che il design emergente dei benefici dichiarati derivi dal lavorare lentamente verso un obiettivo noto. Nel caso di mergesort, non penso che l'obiettivo sia l'ordinamento in generale (perché poi finirai con l'ordinamento a bolle). Conosci le operazioni di base, quindi lavori verso quelle operazioni; l'ordinamento è principalmente un ripensamento.
kdgregory,

1
C'è una quarta opzione. Passa la mergefunzione mergesorte prendi in giro il suo comportamento. Quindi tornare indietro e implementare mergeprima il test. I delegati sono fantastici ™.
RubberDuck,

@RubberDuck Deridere una parte integrante del dominio principale potrebbe causare alcuni problemi, in particolare quando si esegue il programma e la funzione derisa e unita differisce nei minimi dettagli. Un approccio del genere dovrebbe essere lasciato per i casi in cui si lavora con risorse esterne come da dove proviene l'elenco da ordinare.
Cllamach,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.