TDD con tipi statici predefiniti

3

Mi piace lavorare in lingue con tipi statici, perché mi piace usare i tipi come strumento per progettare un'API prima di iniziare a codificarlo.

Mi piace anche TDD, perché mi aiuta a concentrarmi sul lavoro a piccoli passi per assicurarmi di ottenere risultati coerenti.

Ma quando combino i due approcci, ho spesso questo problema: progetto il tipo di API, ma prima di scrivere test unitari per parte della funzionalità, trovo che devo implementarlo perché altrimenti il compilatore si lamenta dei metodi essere digitato in modo errato. Ad esempio, in un progetto Java, ho la seguente classe:

 public class TransformedModelObserver<O,S>
 {
       private O sourceModel;
       private Function<O,S> transform;
       // note: a ChangeNotification<S> is a class that can only be constructed with a non-null instance of S
       private Consumer<ChangeNotification<S>> receiver;

       // ....

       /** Should call the receiver if and only if the source model change
        *  is visible in the transformed model.
        */
       public void notifySourceModelChanged ()
       {

       }
 }

Posso semplificare il test usando una funzione di identità per la trasformazione, che consentirebbe un primo passo facile, ma il compilatore si lamenta se non lo chiamo comunque. Quindi, come potrei lavorare per implementare questo metodo in piccoli passi guidati da test in questo scenario?

    
posta Periata Breatta 02.01.2017 - 12:14
fonte

3 risposte

1

Supponendo che notifySourceModelChanged venga chiamato solo se sourceModel è effettivamente cambiato (quindi, nessun filtro del modello invariato prima della trasformazione necessaria), quindi posso vedere questi piccoli passi per implementare la funzione.

  1. Verifica che un modello modificato (con una trasformazione che non nasconde alcuna modifica) notifica sempre receiver : chiama receiver con un S appena creato.
  2. Verifica che il modello passato a receiver corrisponda a sourceModel dopo la trasformazione: sostituisci S appena creato con uno ottenuto da transform . Testcase utilizza una trasformazione dell'identità per una facile verifica.
  3. Verifica che receiver non venga notificato se la trasformazione nasconde la modifica.

Come puoi vedere, aggiro la differenza di tipo tra O e S rompendo la corrispondenza tra i modelli nei primi (pochi?) testcase (s).

    
risposta data 02.01.2017 - 12:52
fonte
3

Ho spesso adottare un approccio simile durante lo sviluppo di .Net, che fornisce un NotImplementedException . Lo butto da qualsiasi metodo che TDD non mi abbia ancora forzato a implementare. Ciò mantiene i miei test in errore dopo averlo ottenuto compilazione . Non sono sicuro che Java fornisca una classe di eccezioni simile, ma certamente non sarebbe difficile crearne una.

Solo una nota su come adottare questo approccio allo sviluppo: fai attenzione a non lasciare che il tuo design preconcetto abbia la precedenza su ciò che i tuoi test & codice ti sta dicendo. Se ritieni di dover combattere l'API predeterminata, modificala di conseguenza. Il principale vantaggio del tuo approccio è che riesci a pensare al tuo design più che a un design frontale o TDD. Non perdere questo vantaggio perché sei testardo.

    
risposta data 02.01.2017 - 14:58
fonte
-2

Non iniziare con i tipi. Inizia con il test. Scrivi anche prima l'Assert, se ritieni che ti consenta di ritardare l'implementazione un po 'più a lungo.

Il compilatore si lamenterà solo alla fase Act, quando inizi a utilizzare il Sistema sotto test e non esiste ancora. Quindi la maggior parte degli IDE ti consente di creare stub di classe e metodo su una semplice scorciatoia da tastiera.

Nella maggior parte dei casi dovresti essere in grado di soddisfare il compilatore con una semplice UnsupportedException o restituire null nello stub del metodo generato. Quindi esegui un test di compilazione completo prima di iniziare qualsiasi implementazione reale del tuo metodo.

    
risposta data 02.01.2017 - 15:58
fonte

Leggi altre domande sui tag