2010-11-15 14 views
7

Ci sono troppi asserimenti in questo test?Ci sono troppi asserti in questo test unitario?

[Fact] 
public void Send_sends_an_email_message() { 
    using (var server = new MockSmtpServer()) { 
     server.Start(); 
     using (var client = new EmailClient("localhost")) { 
      string from = "[email protected]"; 
      IEnumerable<string> to = new[] { "[email protected]" }; 
      string subject = "Test"; 
      string body = "Test."; 
      client.Send(from, to, subject, body); 
      var session = server.Sessions.FirstOrDefault(); 
      Assert.NotNull(session); 
      var message = session.Messages.FirstOrDefault(); 
      Assert.NotNull(message); 
      Assert.NotNull(message.From); 
      Assert.Equal(message.From.Address, "[email protected]"); 
      Assert.NotNull(message.To); 
      var recipient = message.To.FirstOrDefault(); 
      Assert.NotNull(recipient); 
      Assert.Equal(recipient.Address, "[email protected]"); 
      Assert.Equal(message.Subject, "Test"); 
      Assert.Equal(message.Body, "Test."); 
     } 
    } 
} 

Non penso che questo codice richieda alcuna spiegazione, ma se lo fa fammi sapere.

+0

Solo una cosa da dire. Leggi questo libro: http://www.amazon.com/Art-Unit-Testing-Examples-Net/dp/1933988274. Sarai un altro sviluppatore dopo averlo letto. – Steven

+0

@Steven: lo leggerò; grazie. – Arlen

risposta

6

Cerco di mantenere i miei UnitTests abbastanza piccoli e di testare una cosa alla volta. Quindi probabilmente effettuerò test di parti distinte in test separati, ad es.

  • sendWillSendAnEmail,
  • fromContainsSenderAddress,
  • toContainsRecipientAddress,
  • mailBodyContainsMailMessage,
  • mailContainsSubject
+0

Ma non si finisce con un sacco di codice ripetuto o un sacco di codice infrastruttura-y per impostare questi vari test? Ne vale davvero la pena? – Arlen

+1

@Arlen: La mia unità verifica la presenza di un po 'di codice ripetuto, ma lo mantiene al minimo utilizzando i metodi di fabbrica per l'impostazione di prova e i metodi di asserzione personalizzati. Il trucco è minimizzare la duplicazione del codice per garantire la manutenibilità, ma anche garantire la leggibilità. Questa è l'arte del collaudo unitario :-) – Steven

+1

@Arlen Di solito installo ciò che è necessario nel metodo di installazione, quindi è disponibile in qualsiasi test o scrivi un helper per impostare lo stato - qualunque sia il codice meno. Funziona abbastanza bene e con pochissima duplicazione del codice per me. Non hai aggiunto un tag della lingua alla tua domanda, quindi dovrei notare che sto usando PHPUnit. PHPUnit è un framework xUnit quindi suppongo che lo stesso dovrebbe essere possibile con il tuo framework. – Gordon

1

In generale, più asserzioni, meglio è. Un errore comune nei test unitari non è abbastanza esplicito.

Il test è molto esplicito e leggibile. Mi piacciono particolarmente le affermazioni su null. È una buona pratica perché rende l'interpretazione di un test fallito estremamente semplice.

L'unico modo in cui si possono avere troppe asserzioni è se si asserisce la stessa cosa più di una volta, cosa che non si sta facendo.

4

non vedo alcun problema particolare con il vostro afferma, ma se si vuole ripulire il codice, si potrebbe cambiare

var session = server.Sessions.FirstOrDefault(); 
Assert.NotNull(session); 

in

var session = server.Sessions.First(); 

First() un'eccezione comunque, in modo da semplicemente cambiando il tuo codice ottieni il vantaggio che l'asserzione ti avrebbe portato senza tanto codice. Ci sono altri posti in cui puoi fare cambiamenti simili.

Ma come regola generale, non dare nulla per scontato in unit test - e questo significa un sacco di asserzioni!

2

Dipende dagli standard a cui si sta aderendo, ma in genere direi di sì, nel test ci sono state troppe affermazioni.

Molte persone sostengono che un singolo test dovrebbe avere un'unica affermazione; Penso che possa essere un po 'eccessivo, ma credo certamente che sia appropriato avere un test unitario per un singolo "pezzo" di funzionalità; sei dappertutto con le tue affermazioni. Il test è troppo grande; suddividerlo in diversi test.

0

Penso che la domanda è, fanno le assert() d valori cambiano in modo indipendente? Se cambiano in modo indipendente, devono essere testati in diversi test che variano le condizioni relative a ciascuna affermazione.

Se tuttavia si dispone di un singolo codep che genera un'e-mail con tutti quei campi, è opportuno testare tutte le cose in un test.

Ora il test è piuttosto difficile da leggere. Potresti voler avvolgere quegli asserti in un metodo di supporto descrittivo. Non mi preoccuperei di questo finché non trovo che lo stesso metodo di supporto potrebbe essere utile da qualche altra parte.

6

Penso che sia troppo grande.

Quando si dispone di una serie di test più piccoli, è possibile ottenere la "localizzazione dei difetti": è sufficiente eseguire tutti i test per vedere esattamente dove si trova un problema. Con il maggior numero di affermazioni che hai attualmente (e non asserire messaggi), probabilmente dovresti avviare un debugger per scoprirlo. Ricorda che probabilmente finirai per avere centinaia se non migliaia di test, e se un gruppo di loro non funziona, non devi fare il debug di ognuno per capire perché.

Inoltre, qualsiasi affermazione che fallisce all'inizio del test significa che le asserzioni successive non vengono eseguite. Quando sono separati in singoli test, ogni assert viene controllato. Questo è una sorta di compromesso; molti di questi sono probabilmente correlati e falliranno allo stesso tempo, quindi avrai cinque test rossi invece di uno. Ma io lavoro dal presupposto che maggiori informazioni sono migliori, quindi preferirei avere quei cinque test e sapere che tutti e cinque gli asseriti falliscono.

0

Le tue numerose affermazioni assert sono un indicatore di quanta logica hai nei test unitari. Dovrai mantenere i tuoi test unitari come un normale codice. È meglio dedicare del tempo alla programmazione difensiva e alla programmazione per contratto piuttosto che alle prove unitarie del codice.

0

Forse è possibile creare una nuova classe di e-mail che accetta tutti quei parametri nel suo costruttore predefinito.

E quindi è possibile generare un'eccezione nel caso in cui l'utente passi un parametro non valido.

E nel tuo test di unità

Send_sends_an_email_message

è possibile aggiungere l'sostiene che controlla uguaglianze solo che invece di controllare contro NULL.

Forse puoi creare 2 email in un test e fare l'uguaglianza per entrambe le istanze.

1

Sì, hai troppe affermazioni nel tuo codice! Inoltre, la dichiarazione di affermazione dovrebbe essere solo una per metodo di prova. L'uso di molti asseriti può essere l'odore del codice che stai testando più di una cosa. Inoltre, c'è la possibilità che qualcuno possa aggiungere nuove asserzioni al test invece di scriverne un altro. E come puoi capire in che modo il tuo altro afferma completato quando il primo fallisce?

Forse potresti trovato interessante questo post: https://timetocode.wordpress.com/2016/06/01/zen-of-unit-testing/