Come posso iniziare a utilizzare TDD per codificare alcune semplici funzionalità?

9

Fondamentalmente ho il succo del TDD. Sono venduto che è utile e ho un ragionevole comando del framework MSTEST. Tuttavia, fino ad oggi non sono stato in grado di usarlo come metodo di sviluppo primario. Principalmente, lo uso come surrogato per scrivere app per console come test driver (il mio approccio tradizionale).

La cosa più utile per me è il modo in cui assorbe il ruolo dei test di regressione.

Non ho ancora creato nulla che isolasse specificamente i vari comportamenti testabili, che è un'altra grande parte del quadro che conosco.

Quindi questa domanda è di chiedere dei suggerimenti su quali potrebbero essere i primi test che potrei scrivere per il seguente compito di sviluppo: voglio produrre un codice che incapsuli l'esecuzione del compito alla maniera del produttore / consumatore.

Mi sono fermato e ho deciso di scrivere questa domanda dopo aver scritto questo codice (chiedendomi se potrei effettivamente usare TDD per davvero questa volta)

Codice:

interface ITask
{
    Guid TaskId { get; }
    bool IsComplete { get; }
    bool IsFailed { get; }
    bool IsRunning { get; }
}

interface ITaskContainer
{
    Guid AddTask(ICommand action);
}

interface ICommand
{
    string CommandName { get; }
    Dictionary<string, object> Parameters { get; }
    void Execute();
}
    
posta Aaron Anodide 11.04.2012 - 23:23
fonte

1 risposta

10

A partire da questo concetto:
1) Inizia con il comportamento che desideri. Scrivi un test per questo. Vedi fallire il test.
2) Scrivi abbastanza codice per far passare il test. Vedi tutti i test pass.
3) Cerca codice ridondante / sciatto - > refactoring. Vedi i test ancora passati. Vai a 1

Quindi al # 1, diciamo che vuoi creare un nuovo comando (mi sto concentrando su come funzionerebbe il comando, quindi portami con me). (Inoltre, sarò un po 'pragmatico piuttosto che estremo TDD)

Il nuovo comando si chiama MakeMyLunch, quindi devi prima creare un test per istanziarlo e ottenere il nome del comando:

@Test
public void instantiateMakeMyLunch() {
   ICommand command = new MakeMyLunchCommand();
   assertEquals("makeMyLunch",command.getCommandName());
}

Questo fallisce, costringendoti a creare la nuova classe di comando e fargli restituire il suo nome (il purista direbbe che si tratta di due round di TDD, non di 1). Così si crea la classe e si ha implementare l'interfaccia ICommand, incluso restituire il nome del comando. L'esecuzione di tutti i test ora mostra tutti i passaggi, quindi procedi a cercare le opportunità di refactoring. Probabilmente nessuno.

Quindi la prossima volta che vuoi implementare execute. Quindi devi chiedere: come faccio a sapere che "MakeMyLunch" ha "preparato il mio pranzo" con successo. Cosa cambia nel sistema a causa di questa operazione? Posso testare per questo?

Supponiamo che sia facile testare per:

@Test
public void checkThatMakeMyLunchIsSuccessful() {
   ICommand command = new MakeMyLunchCommand();
   command.execute();
   assertTrue( Lunch.isReady() );
}

Altre volte, questo è più difficile, e ciò che si vuole veramente fare è testare le responsabilità del soggetto sotto test (MakeMyLunchCommand). Forse la responsabilità di MakeMyLunchCommand è di interagire con il frigorifero e il microonde. Quindi per testarlo puoi usare un finto frigorifero e finto microonde. [due esempi di framework di simulazione sono Mockito e nMock o guarda qui .]

In questo caso dovresti fare qualcosa come il seguente pseudo codice:

@Test
public void checkThatMakeMyLunchIsSuccessful() {
   Fridge mockFridge = mock(Fridge);
   Microwave mockMicrowave = mock(Microwave);
   ICommand command = new MakeMyLunchCommand( mockFridge, mockMicrowave );
   command.execute();
   mockFramework.assertCalled( mockFridge.removeFood );
   mockFramework.assertCalled( microwave.turnon );
}

Il purista dice che prova la responsabilità della tua classe - le sue interazioni con altre classi (il comando ha aperto il frigorifero e accende il forno a microonde?)

Il pragmatico dice di testare un gruppo di classi e testare il risultato (il pranzo è pronto?).

Trova il giusto equilibrio che funzioni per il tuo sistema.

(Nota: considera che forse sei arrivato alla struttura dell'interfaccia troppo presto. Forse puoi lasciarlo evolvere mentre scrivi i test e le implementazioni dell'unità, e nel passaggio 3 "noti" l'opportunità dell'interfaccia comune).

    
risposta data 11.04.2012 - 23:50
fonte

Leggi altre domande sui tag