Ho testato la mia unità in classe, ora come faccio a iniziare con un test di integrazione?

19

Ho scritto una classe che gestisce i destinatari su una lista MailChimp, chiamata MailChimpRecipient. Utilizza la classe MCAPI, che è un wrapper API di terze parti.

link http://apidocs.mailchimp.com/api/downloads/

Ho passato l'oggetto MCAPI al costruttore dell'oggetto MailChimpRecipient, quindi ho scritto test unitari usando PHPUnit per testare tutta la logica della mia classe (non sto testando la classe MCAPI). Ho il 100% di copertura del codice e tutti i test passano. Questo viene fatto simulando e stubando l'oggetto MCAPI.

Il mio prossimo passo è stato scrivere un test di integrazione, anche usando PHPUnit, dove avrei costruito il dispositivo MailChimpRecipient utilizzando un vero oggetto MCAPI, configurato per usare una vera lista MailChimp.

Ho scritto quello che penso sia un test di integrazione, che fondamentalmente esegue nuovamente i test dell'interfaccia pubblica dell'oggetto, come:

public function testAddedRecipientCanBeFound()
{
    $emailAddress = '[email protected]';
    $forename = 'Fred';
    $surname = 'Smith';

    // First, delete the email address if it is already on the list
    $oldRecipient = $this->createRecipient();
    if($oldRecipient->find($emailAddress))
    {
        $oldRecipient->delete();
    }
    unset($oldRecipient);

    // Add the recipient using the test data
    $newRecipient = $this->createRecipient();
    $newRecipient->setForename($forename);
    $newRecipient->setSurname($surname);
    $newRecipient->setEmailAddress($emailAddress);
    $newRecipient->add();
    unset($newRecipient);

    // Assert that the recipient can be found using the same email address
    $this->assertTrue($this->_recipient->find($emailAddress));
}

Il test di "integrazione" non verifica nessuno dei componenti interni della classe, ma fa in modo che, dato un vero oggetto MCAPI, si comporti come pubblicizzato.

È corretto? È questo il modo migliore per eseguire un test di interazione? Dopo tutto, gli interni sono stati testati con un test unitario. Ho ragione nel pensare che il test di integrazione sia lì per testare che funzioni davvero, secondo il modo in cui viene pubblicizzato il suo comportamento?

Per fare un ulteriore passo avanti, la classe MailChimpRecipient implementa un'interfaccia, che sarà implementata anche da altre classi. L'idea è di usare una fabbrica per passare diversi tipi di oggetti destinatari della mailing list al mio codice, che fanno tutti la stessa cosa, anche se si usano diversi provider di mailing list. Dal momento che i miei test di integrazione testano l'interfaccia, che ne dici di usarla per tutte le classi che implementano l'interfaccia? Quindi, in futuro, se progetto una nuova classe da utilizzare in modo intercambiabile, posso eseguire lo stesso test di integrazione prima di inserirla in un progetto.

Suona ragionevole? I test unitari testano le parti interne di un oggetto, i test di integrazione assicurano che si comporti come pubblicizzato?

    
posta Lewis Bassett 04.01.2012 - 12:12
fonte

1 risposta

17

Quando collaudi il tuo codice dovresti prestare attenzione a tre aree:

  • Test dello scenario
  • Test funzionali
  • Test delle unità

Normalmente la quantità di test che hai in ogni categoria dovrebbe avere la forma di una piramide, ovvero test di unità molto in basso, alcuni test funzionali nel mezzo e solo alcuni test di scenario.

Con un test unitario prendi in giro tutto ciò che la classe sotto test usa e testalo in puro isolamento (ecco perché è importante assicurarsi che all'interno della classe si recuperino tutte le dipendenze attraverso l'iniezione in modo che possano essere sostituite in prova ).

Con i test delle unità testate tutte le possibilità, quindi non solo il "percorso felice" ma anche tutte le condizioni di errore.

Se sei completamente sicuro che tutte le tue unità lavorano in isolamento, scrivi un paio di test (test funzionali) per assicurarti che le unità funzionino anche quando sono combinate. Quindi scrivi un test di scenario, che verifica il cablaggio tra tutti i moduli funzionali.

Ad esempio, supponi di provare una macchina.

Potresti assemblare l'intera macchina e come pilota controllare tutte le possibili condizioni, ma sarebbe davvero difficile.

Invece dovresti testare una piccola parte del motore con tutte le possibilità (unit test)

Quindi testerai l'intero motore (separato dalla macchina) che sarebbe un test funzionale.

Come ultimo test, inserisci la tua chiave, avvia la macchina e guidala nel parcheggio. Se funziona, allora sai che tutte le parti (batteria, carburante, motore, ..) sono collegate e dal momento che le hai provate in isolamento puoi essere certo che l'intera macchina funzioni correttamente.

Quindi nel tuo caso hai testato tutte le condizioni di errore e il percorso felice del tuo test unitario e sai che devi solo eseguire un test end-to-end con i "componenti reali" per verificare se il cablaggio è corretto.

Alcuni altri punti,

  • Evita la logica condizionale nel test dell'unità. Se devi pulire, l'utilizzo di una sorta di stato globale e i test possono improvvisamente influenzarsi a vicenda.
  • Non specificare alcun dato che non è rilevante per il test. Se cambiasse nome o cognome, il test fallirebbe? Probabilmente non perché è l'indirizzo e-mail che è importante ma perché lo menzioni esplicitamente nel tuo test, non posso esserne sicuro. Prova a guardare il Pattern Builder per creare i dati di test e rendi esplicito ciò che è veramente importante.
risposta data 04.01.2012 - 13:02
fonte

Leggi altre domande sui tag