2009-09-02 13 views
21

Ho un test di unità chiamato TestMakeAValidCall(). Mette alla prova la mia app del telefono facendo una chiamata valida.Test unità - È una cattiva condizione che il test dell'unità venga chiamato per altri test di unità

Sto per scrivere un altro test chiamato TestShowCallMessage() che deve avere una chiamata valida per il test. È una cattiva forma chiamare semplicemente TestMakeAValidCall() in quel test?

Per riferimento questo è il mio test TestMakeAValidCall().

[TestMethod] 
    public void TestMakeAValidCall() 
    { 
     //Arrange 
     phone.InCall = false; 
     phone.CurrentNumber = ""; 
     // Stub the call to the database 
     data.Expect(x => x.GetWhiteListData()). 
      Return(FillTestObjects.GetSingleEntryWhiteList()); 
     // Get some bogus data 
     string phoneNumber = FillTestObjects.GetSingleEntryWhiteList(). 
      First().PhoneNumber; 
     // Stub th call to MakeCall() so that it looks as if a call was made. 
     phone.Expect(x => x.MakeCall(phoneNumber)). 
      WhenCalled(invocation => 
         { 
          phone.CurrentNumber = phoneNumber; 
          phone.InCall = true; 
         }); 

     //Act 
     // Select the phone number 
     deviceControlForm.SelectedNumber = phoneNumber; 
     // Press the call button to make a call. 
     deviceMediator.CallButtonPressed(); 

     //Assert 
     Assert.IsTrue(phone.InCall); 
     Assert.IsTrue(phone.CurrentNumber == phoneNumber); 
    } 
+0

Grazie per tutte le grandi risposte. Ho rifattorizzato il codice duplicato in una chiamata separata. Ho scelto la risposta con il maggior numero di voti. – Vaccano

risposta

51

Riformare l'installazione su un altro metodo e chiamare tale metodo da entrambi i test. I test non dovrebbero chiamare altri test.

+3

Non testare un altro test con il test –

+0

Qualcuno potrebbe discutere su come sarebbe in questo caso il refactoring? –

+1

@Nakata: difficile mostrare il codice esatto per questo esempio senza sapere come sono strutturate le dipendenze, ma questo elenco mostra lo schema che utilizzo per inserire il codice di configurazione in un contesto di test e richiamarlo da lì in più test. https://gist.github.com/tvanfosson/1ca6dd3bb0b796de65b0 – tvanfosson

6

Penso che sia una cattiva idea. Vuoi che il tuo test unitario test di una cosa e solo una cosa. Invece di creare una chiamata attraverso l'altro test, prendi in giro una chiamata e passala come argomento.

11

IMHO, si dovrebbe fare uno dei seguenti modi:

  • Creare un metodo che restituisce una chiamata valida, e usarlo separatamente per entrambi i test (non uno chiama l'altro)
  • Mock la chiamata valida per ShowCallMessageTest
4

Un test di unità deve testare una unità/funzione del codice per definizione. Chiamare altri test di unità fa provare più di una unità. L'ho suddiviso in test individuali.

2

Sì, i test di unità devono essere separati e devono mirare a testare solo una cosa (o almeno un piccolo numero di cose strettamente correlate). Come un aspettative a parte, le chiamate a data.Expect e phone.Expect nel metodo di prova stanno creando piuttosto che le chiamate stub, che possono rendere i test fragile se si refactoring ...

+0

Grazie per la correzione sulla mia terminologia. Ho aggiornato i commenti nel mio codice sorgente. – Vaccano

6

per offrire un punto di contatore:

Sono fermamente convinto che il test dell'unità ben progettato debba essere dipendente l'uno dall'altro!

Ovviamente, ciò ha senso solo se il framework di testing è a conoscenza di queste dipendenze in modo tale da poter interrompere l'esecuzione del test dipendente quando una dipendenza non riesce. Ancora meglio, un tale framework può passare l'apparecchiatura dal test al test, in modo tale da poter costruire su un dispositivo in espansione ed estensione invece di ricostruirlo da zero per ogni singolo test. Naturalmente, il caching è fatto per fare attenzione, non vengono introdotti effetti collaterali quando più di un test dipende dallo stesso esempio.

Abbiamo implementato questa idea nel JExample extension for JUnit. Non esiste ancora una porta C#, anche se ci sono porte per Ruby e Smalltalk e ... lo most recent release of PHPUnit picked up both our ideas: dependencies and fixture reuse.

PS: folks are also using it for Groovy.

+0

Punto interessante, se fatto correttamente, potrebbe ridurre molto la duplicazione. –

1

Un'unità contro modulo .... pensiamo anche che i test dovrebbero dipendere anche da metodi riutilizzabili e dovrebbero testare a livello di api l'integrazione di test delle classi. Molti testano solo una singola classe ma molti bug sono a quell'integrazione tra il livello di classe. Usiamo anche verifydesign per garantire che l'API non dipenda dall'implementazione. Ciò consente di rifattorizzare l'intero componente/modulo senza toccare un test (e l'abbiamo analizzato una volta e ha funzionato benissimo).Ovviamente, qualsiasi modifica architettonica ti costringe a rifattorizzare i test, ma almeno le modifiche di progettazione nel modulo non fanno sì che il refact test funzioni (a meno che tu non modifichi il comportamento della API, implicitamente come se si attivassero più eventi di quelli che avevi usato in precedenza) " sarebbe "essere un cambiamento api comunque).