La guida per principianti al test delle unità creazione di un plug-in testabile

Nella prima parte di questa serie, abbiamo preso uno sguardo ad alto livello sulle metodologie di test e abbiamo fornito alcuni casi sul perché è vantaggioso per noi iniziare a fare nei nostri progetti WordPress. Abbiamo anche impiegato del tempo per impostare PHPUnit e i test di WordPress per iniziare a creare il nostro primo plug-in testabile.

In questo articolo definitivo, definiremo una metodologia per i test unitari, inizieremo ad incorporarla nel nostro lavoro e adotterà un plug-in completamente funzionale (anche se semplice) che ha anche una piccola serie di test per garantire che funzioni esattamente come previsto.


Una metodologia di test unitario

Quando si tratta di test, ci sono generalmente due modi per farlo:

  • Scrivi i tuoi test, quindi scrivi il codice per far passare i test
  • Scrivi il tuo codice, quindi scrivi i test che superano

Nella mia esperienza, il primo approccio è sempre migliore. Certo, questo è praticamente impossibile da fare nel contesto di un'applicazione che esiste già, ma se stai iniziando da zero - che cosa siamo - è un approccio migliore ed ecco perché: una volta che hai scritto un'applicazione, sapere come funziona Come tale, può essere estremamente difficile scrivere test che estendano l'applicazione quando si conosce intrinsecamente come dovrebbe funzionare.

A tal fine, trovo che sia meglio scrivere i test primo. In questo modo, i tuoi test non solo includono il modo in cui è il programma ipotetico lavorare, ma diventa anche una forma di documentazione che mostra quale funzionalità è destinata e alla fine si tradurrà in un fallimento quando la funzionalità non è performante come dovrebbe.

Con questo in mente, stiamo andando a costruire con questa semplice metodologia:

  • Scrivi un test ed eseguilo. Ovviamente fallirà.
  • Scrivi il codice che tenta di far passare il test.
  • Se il test passa, passiamo alla funzione successiva; altrimenti, ripetiamo il processo fino a quando non passa.

Infine, come aggiornamento, il nostro plug-in darà un messaggio di benvenuto specializzato al visitatore in base a se ha fatto clic sul sito da Google o Twitter. Lo scriveremo anche in questo modo che sarà più facile espandersi con servizi aggiuntivi, nel caso volessi farlo in futuro.


Costruire un plug-in testabile

A questo punto, è ora di iniziare a scrivere del codice; tuttavia, a differenza della maggior parte dei progetti, non stiamo ancora saltando nel codice specifico di WordPress. Invece, annulleremo la nostra classe di test unitari. Se hai strutturato la directory del tuo plug-in basandoti su ciò che abbiamo condiviso nel primo post o su come lo abbiamo configurato su GitHub, dovresti avere un hello_reader_tests.php file situato nel tuo test / wordpress-test directory. Non è necessario seguire quell'organizzazione, naturalmente, ma ciò contribuirà al progredire del progetto.

Esaminiamo la classe di test dell'unità:

require_once ('... / ... /plugin.php'); la classe Hello_Reader_Tests estende WP_UnitTestCase  // end class

Ora, prova ad eseguire il test usando dal terminale usando l'unità PHP. Supponendo che tu stia eseguendo un'unità PHP dall'installazione MAMP locale, dovresti essere in grado di inserire:

$ /Applications/MAMP/bin/php/php5.3.6/bin/phpunit ./hello_reader_tests.php

A questo punto, dovresti vedere un errore:

Quello è buono! Significa che PHPUnit è installato e funzionante e che il tuo framework di test WordPress è pronto per essere utilizzato. Il test è fallito semplicemente perché non abbiamo effettivamente scritto alcun test. Iniziamo a farlo.

Il nostro primo test

Innanzitutto, scriviamo un test per assicurarci che il nostro plug-in sia inizializzato, istanziato e pronto per il test. Ricordiamo in precedenza nel primo articolo che abbiamo memorizzato un riferimento all'istanza di Hello Reader nel PHP $ GLOBALS array. Questo è il modo in cui accediamo a quell'istanza utilizzando il framework di test. Quindi aggiorna il nostro test unitario in questo modo:

Si noti che per motivi di spazio, tralascio i commenti sul codice, ma il plugin e i test completamente commentati saranno disponibili su GitHub.

require_once ('... / ... /plugin.php'); la classe Hello_Reader_Tests estende WP_UnitTestCase plugin $ privato; function setUp () parent :: setUp (); $ this-> plugin = $ GLOBALS ['ciao-lettore'];  // end setup function testPluginInitialization () $ this-> assertFalse (null == $ this-> plugin);  // end testPluginInitialization // end class

In alto, abbiamo impostato un riferimento all'istanza del plug-in in modo che possiamo accedervi durante i nostri test unitari. Stiamo usando il impostare metodo per prendere il riferimento al plugin da $ GLOBALS. Nota, tuttavia, che abbiamo introdotto un'altra funzione chiamata testPluginInitialization. Questa funzione verifica che il riferimento che abbiamo impostato nel file impostare il metodo non è nullo.

Se riesegui i test, ora dovresti ottenere un test che passa e il tuo terminale dovrebbe assomigliare a questo:

C'è un take-away importante qui: Nota che la singola funzione che abbiamo fornito sopra ha uno scopo chiaro: verificare che il plugin sia stato inizializzato correttamente. Il nome della sua funzione è chiaro e contiene una singola affermazione. Questo è un ottimo modo per modellare i nostri test rimanenti principalmente perché rende facile trovare bug quando appaiono. Pensaci in questo modo: se includi una serie di affermazioni di asser differenti in una singola funzione, sarà difficile determinare quale affermazione di affermazione stia fallendo.

La prima funzione

Ora che ci siamo introdotti su come scrivere test unitari, eseguire test unitari e valutare come passano o come falliscono, iniziamo ad implementare funzionalità per il plugin. Prima di tutto, avremo bisogno di impostare un filtro per il contenuto poiché aggiungeremo il testo all'inizio del contenuto. Seguendo la metodologia che abbiamo definito in precedenza in questo articolo, scriviamo prima il test.

Questo particolare test andrà a vedere se abbiamo aggiunto un set specifico di testo alla prima parte del post:

function testAddWelcomeMessage () $ this-> assertEquals ('TEST CONTENT', $ this-> plugin-> add_welcome_message ('Questo è esempio di contenuto del post. Questo simula il ritorno di WordPress durante la visualizzazione di un post di blog.'), 'add_welcome_message ( ) aggiunge il messaggio di benvenuto al contenuto del post. ');  // end testAddWelcomeMessage

Se esegui il test esattamente così com'è, non fallirà nemmeno - invece, PHPUnit restituirà un errore fatale perché il metodo non è definito nel plugin. Quindi aggiungiamolo ora. Aggiorna il plugin per assomigliare a questo:

class Hello_Reader function __construct () add_filter ('the_content', array (& $ this, 'add_welcome_message'));  // funzione pubblica di costruzione finale add_welcome_message ($ content)  // end add_welcome_message // end class

Ora prova a eseguire il test. Il test non bombarderà, ma in realtà dovresti vedere un errore insieme a un chiaro messaggio sul motivo per cui il test è fallito:

1) Hello_Reader_Tests :: testAddWelcomeMessage add_welcome_message () aggiunge il messaggio di benvenuto al contenuto del post. Non è stato possibile affermare che NULL corrisponde al "CONTENUTO DI PROVA" previsto

Quindi, in linea con la nostra metodologia, vogliamo far passare questo test. Per fare ciò, dobbiamo assicurarci che il contenuto del post contenga la stringa di testo - in questo caso, 'CONTENUTO DI PROVA', per farlo passare. Quindi proviamo questo. Aggiorna la funzione corrispondente nel plugin per aggiungere la stringa prima del contenuto:

funzione pubblica add_welcome_message ($ content) return 'TEST CONTENT'. $ Content;  // end add_welcome_message

E ancora, eseguiamo nuovamente il test solo per vedere che fallisce. Se noti il ​​nostro test, questo è perché guarda ai nostri contenuti è uguale a il 'CONTENUTO DI PROVA'stringa. Invece, dobbiamo assicurarci che la stringa inizi sul contenuto. Ciò significa che dobbiamo aggiornare il nostro test. Fortunatamente, PHPUnit ha una funzione assertContains. Quindi aggiorna il nostro codice per usarlo:

function testAddWelcomeMessage () $ this-> assertContains ('TEST CONTENT', $ this-> plugin-> add_welcome_message ('Questo è esempio di contenuto del post. Questo simula il ritorno di WordPress durante la visualizzazione di un post di blog.'), 'add_welcome_message ( ) aggiunge il messaggio di benvenuto al contenuto del post. ');  // end testAddWelcomeMessage

Ancora una volta, riesegui il test e dovresti vedere che il test ora passa. Eccezionale! Ora dobbiamo scrivere messaggi personalizzati per le persone che provengono da Twitter e persone che provengono da Google.

Accogliere i nostri visitatori di Twitter

Ci sono un certo numero di modi diversi che possiamo verificare per vedere come un utente è arrivato a una determinata pagina. A volte possiamo controllare i valori nel $ _GET array, a volte possiamo interrogare il $ _SERVER array, oa volte possiamo controllare la sessione di un utente. Per gli scopi di questo esempio, cercheremo "twitter.com" nel file $ _SERVER [ 'HTTP_REQUEST']. Dico questo solo così che voi ragazzi potete seguire quello che stiamo facendo nel codice.

Quindi, in generale, il add_welcome_message dovrebbe verificare se la richiesta proviene da Twitter e quindi personalizzare il messaggio in modo appropriato. Poiché siamo impegnati a testare ogni funzionalità, possiamo scrivere una funzione in grado di valutare se la richiesta proviene da Twitter. Quindi scriviamo un nuovo test:

Nel plugin:

funzione pubblica is_from_twitter ()  // end is_from_twitter

Nel test:

function testIsComingFromTwitter () $ _SERVER ['HTTP_REFERER'] = 'http://twitter.com'; $ this-> assertTrue ($ this-> plugin-> is_from_twitter (), 'is_from_twitter () restituirà true quando il sito di riferimento è Twitter.');  // end testIsComingFromTwitter

Ovviamente stiamo spoofing HTTP_REFERER valore, ma va bene per gli scopi di questo esempio. Il punto rimane ancora: esegui il test, fallirà, quindi avremo bisogno di implementare la funzione nel plugin per farlo passare:

funzione pubblica is_from_twitter () return strpos ($ _SERVER ['HTTP_REFERER'], 'twitter.com')> 0;  // end is_from_twitter

Il riesecuzione del test dovrebbe ora comportare un test di passaggio. Ma aspetta - dobbiamo essere completi. Assicuriamoci di eseguire un test per verificare che questa funzione non riesca quando è il referrer non da Twitter.

function testIsNotComingFromTwitter () // Spoofing di HTTP_REFERER ai fini di questo test e del post del blog associato $ _SERVER ['HTTP_REFERER'] = 'http://facebook.com'; $ this-> assertFalse ($ this-> plugin-> is_from_twitter (), 'is_from_twitter () restituirà true quando il sito di riferimento è Twitter.');  // end testIsNotComingFromTwitter

Si noti che abbiamo aggiornato il HTTP_REFERER e siamo cambiati assertTrue a assertFalse. Consentire tutto il resto è corretto, eseguire i test e dovrebbero passare.

Ripetendo lo stesso per Google

Fornire un messaggio personalizzato per Google richiederà la stessa cosa che abbiamo fatto per Twitter, ovvero lo spoofing HTTP_REFERER e quindi restituisce true o false per la funzione helper. Quindi, per evitare di sembrare ridondante, terrò questa sezione il più concisa possibile. Gli stessi passi devono essere seguiti come per Twitter.

Per prima cosa, eliminiamo la funzione di supporto nel plugin:

funzione pubblica is_from_google ()  // end is_from_google

Quindi interrompiamo il test:

function testIsComingFromGoogle () $ _SERVER ['HTTP_REFERER'] = 'http://google.com'; $ this-> assertTrue ($ this-> plugin-> is_from_google (), 'is_from_google () restituirà true quando il sito di riferimento è Google.');  // end testIsComingFromGoogle

Eseguendo il test così com'è ora si verificherà un errore. Quindi, implementiamo il is_from_google () funzione:

funzione pubblica is_from_google () return strpos ($ _SERVER ['HTTP_REFERER'], 'google.com')> 0;  // end is_from_twitter

E ora, il test dovrebbe passare. Ma, ancora, dobbiamo essere completi, quindi scriviamo il test di errore per supporre che la funzione non restituirà true quando gli utenti provengono da qualche altra parte:

function testIsNotComingFromGoogle () // Spoofing di HTTP_REFERER ai fini di questo test e del post del blog associato $ _SERVER ['HTTP_REFERER'] = 'http://facebook.com'; $ this-> assertFalse ($ this-> plugin-> is_from_google (), 'is_from_google () restituirà true quando il sito di riferimento è Google.');  // end testIsNotComingFromGoogle

Finalmente, esegui i tuoi test. Permettere tutto il resto è corretto, dovresti avere sei test di passaggio.

Tirando tutto insieme

A questo punto, abbiamo tutto ciò che serve per iniziare a mostrare messaggi di benvenuto personalizzati ai nostri utenti. L'unica cosa è che abbiamo bisogno di rifattorizzare il nostro test iniziale che sta verificando "TEST CONTENT". Ora, dovremo introdurre test per i seguenti casi:

  • Quando l'utente proviene da Twitter, diremo "Benvenuto da Twitter!"
  • Quando l'utente proviene da Google, diremo "Benvenuto da Google!"
  • Quando l'utente viene da qualsiasi altra parte, non anteporremo nulla.

Quindi rimuoviamo il test che abbiamo creato in precedenza testAddWelcomeMessage al posto di aggiungere tre nuovi test.

Innanzitutto, aggiungeremo un test che controlla il messaggio di benvenuto di Twitter.

Nel plugin, ridurremo il add_welcome_message a questo:

funzione pubblica add_welcome_message ($ content) return $ content;  // end add_welcome_message

E aggiungeremo il test di Twitter, in primo luogo:

function testDisplayTwitterWelcome () // Spoof di HTTP_REFERER per Twitter $ _SERVER ['HTTP_REFERER'] = 'http://twitter.com'; $ this-> assertContains ('Benvenuto da Twitter!', $ this-> plugin-> add_welcome_message ('Questo è esempio di contenuto del post. Questo simula il ritorno di WordPress durante la visualizzazione di un post del blog.'), 'add_welcome_message () accoda messaggio al contenuto del post. ');  // end testDisplayTwitterWelcome

A questo punto, questo è vecchio cappello, giusto? Eseguilo, il test fallirà. Implementare il add_welcome_message per assomigliare a questo:

funzione pubblica add_welcome_message ($ content) if ($ this-> is_from_twitter ()) $ content = 'Benvenuto da Twitter!' . $ Content;  // end if return $ content;  // end add_welcome_message

Eseguilo di nuovo, e passerà. Il prossimo è il test di Google:

function testDisplayGoogleWelcome () // Spoof di HTTP_REFERER per Google $ _SERVER ['HTTP_REFERER'] = 'http://google.com'; $ this-> assertContains ('Benvenuto da Google!', $ this-> plugin-> add_welcome_message ('Questo è esempio di contenuto del post. Questo simula il ritorno di WordPress durante la visualizzazione di un post del blog.'), 'add_welcome_message () accoda messaggio al contenuto del post. ');  // end testDisplayGoogleWelcome

Esegui il test, fallo fallire, quindi aggiorna il add_welcome_message nel plugin per contenere un controllo usando la funzione helper che abbiamo scritto in precedenza:

funzione pubblica add_welcome_message ($ content) if ($ this-> is_from_twitter ()) $ content = 'Benvenuto da Twitter!' . $ Content;  else if ($ this-> is_from_google ()) $ content = 'Benvenuto da Google!' . $ Content;  // end if return $ content;  // end add_welcome_message

A questo punto, dovresti avere un plugin pienamente funzionale che ha sette test unitari che passano!


Conclusione

Come si può vedere, il test delle unità introduce un ulteriore livello di sviluppo, ma può ripagare in modo significativo in un codice gestibile, ben organizzato e verificabile. Man mano che la tua applicazione cresce, esegui continuamente test per verificare che i tuoi progetti funzionino come previsto può essere un problema. Naturalmente, questo è solo un piccolo esempio di come funziona il test delle unità. L'applicazione di queste pratiche può ripagare in progetti molto più grandi e / o complicati.

Infine, puoi trovare questo plug-in, i test di WordPress e i test dell'unità Hello Reader completamente commentati su GitHub.