TDD / un test che rappresenta l'intero scenario? o dovrei dividerlo? [duplicare]

3

Mentre praticavo il TDD, mi sono imbattuto in questa specifica:

Un utente deve essere creato con la password hash, essere persistente e restituire un token di attivazione.

Il mio primo test di unità (con l'obiettivo di iniziare a testare questo scenario) dovrebbe comprendere tutte le esigenze? :

shouldPersistTheNewlyCreatedUserWithAHasedPasswordAndReturnACorrespondingActivationToken

O meglio, suddividendo le sue parti principali in diversi test più piccoli e testando in modo incrementale:

shouldCreateAUser
shouldReturnAUserActivationToken
shouldReturnAnActivationTokenBasedOnNewlyCreatedUserEmail
shouldPersistTheNewlyCreatedUser
shouldHashTheUserPersistBeforePersistingIt

Per dirla in poche parole, dovrei rielaborare lo stesso test fino a quando non passa un intero scenario? O dovrei procedere in modo incrementale specificando funzionalità aggiuntive in altri piccoli test.

IMHO, il vantaggio della prima soluzione è che la spec sta definendo in un punto, non c'è bisogno di raccogliere alcuni pezzi di funzionalità per capire il tutto. D'altra parte, il numero di asserzioni e aspettative potrebbe essere enorme, quindi il codice del test sarebbe meno leggibile.

    
posta Mik378 23.07.2013 - 14:30
fonte

1 risposta

10

tl; dr: Seconda opzione. Dovresti dividerlo in diversi test più piccoli, poiché è quello che dovresti fare con TDD (Red-Green-Refactor).

Inizi a scrivere i test più semplici per iniziare con l'implementazione più semplice e costruisci la tua strada verso uno scenario completo. La semantica con test unitari è totalmente diversa con test di scenario / funzionali / di accettazione. Gli sviluppatori tendono a confonderli tutti come gli stessi, ma sono semanticamente diversi e soddisfano scopi diversi.

TDD è costruito sul concetto in cui un test ha la granularità di un'unità. Di solito questa unità si trova in un metodo in una classe. L'intero punto con TDD è progettare il codice per essere testabile. Se inizi con uno scenario intero come un'unità e non i metodi stessi, ti ritroverai con un codice che potrebbe fare troppo.

Ci sono diversi modi per andare con il tuo scenario. Inizierei approssimativamente provando quanto segue:

  1. In primo luogo scrivi un UserService che può creare un nuovo utente con un solo test createUserShouldReturnUser .
  2. Quindi scrivi un'interfaccia IActivationTokenFactory che crea token di attivazione. In UserService Continuerò con un test che usa la fabbrica di token come oggetto fittizio. Il test è createUserShouldRequestActivationToken che richiede qualsiasi token di attivazione dall'oggetto fittizio e lo inserisce sull'oggetto utente che viene restituito.
  3. Procedo a scrivere un% co_de concreto che implementa ActivationTokenFactory . Il test è per assicurarsi che produca token "legittimi".
  4. e così via ... Posso immaginare un qualche tipo di oggetto IActivationTokenFactory e anche un qualche tipo di livello di persistenza.

Risciacquare, ripetere finché non ho uno scenario completo e un refactoring lungo la strada. Scriverò ora il test dello scenario che esercita tutto il codice, e assicurarmi di avere anche alcuni percorsi infelici da testare (con eccezioni di persistenza fallite e quant'altro).

È più facile implementare qualcosa se dividi e vinci ... che è ciò che dovresti fare con TDD. Una volta che hai colpito un ostacolo, è meglio avere questi piccoli test unitari per le regressioni se decidi di rifattorizzare qualcosa.

    
risposta data 23.07.2013 - 14:42
fonte

Leggi altre domande sui tag