Nybörjarens guide till enhetstestning Bygg en testbar plugin

I den första delen av denna serie tog vi en hög nivå på testmetoder och gav några fall till varför det är fördelaktigt för oss att börja göra i våra WordPress-projekt. Vi tog också tid att installera PHPUnit och WordPress-testen för att börja bygga vårt första testbara plugin.

I den här sista artikeln ska vi definiera en metod för enhetstestning, börja integrera den i vårt arbete och gå bort med ett fullt fungerande (om än enkelt) plugin som också har en liten uppsättning test för att säkerställa att den fungerar exakt som förväntat.


Enhetsprovningsmetodik

När det gäller testning finns det i allmänhet två sätt att göra det:

  • Skriv dina test, skriv sedan kod för att göra dina tester passerade
  • Skriv din kod och skriv sedan tester som passerar

Enligt min erfarenhet är det första tillvägagångssättet alltid bättre. Beviljas, det här är praktiskt taget omöjligt att göra inom ramen för en ansökan som redan finns, men om du börjar från grunden - som vi är - är det ett bättre tillvägagångssätt och det är därför: När du har skrivit en ansökan vet hur det fungerar. Som sådant kan det vara extremt svårt att skriva test som sträcker applikationen när man själv vet hur den ska fungera.

För det ändamålet tycker jag att det är bättre att skriva testen först. På så sätt inkluderar dina test inte bara hur programmet är förment att fungera, men det blir också en form av dokumentation som visar vilken funktionalitet som är avsedd och kommer slutligen att ge ett misslyckande när funktionaliteten inte fungerar som den borde.

Med det i åtanke kommer vi att bygga med den här enkla metoden:

  • Skriv ett test och kör det. Det kommer naturligtvis att misslyckas.
  • Skriv kod som försöker få testet att passera.
  • Om testet passerar går vi vidare till nästa funktion; Annars upprepar vi processen tills den passerar.

Slutligen, som en uppdatering, kommer vårt plugin att ge ett specialiserat välkomstmeddelande till besökaren baserat på om de har klickat på webbplatsen från antingen Google eller Twitter. Vi skriver också detta på ett sådant sätt att det blir enklare att expandera med ytterligare tjänster, om du vill göra det i framtiden.


Bygga en testbar plugin

Vid den här tiden är det dags att börja skriva några koden; Men, till skillnad från de flesta projekt, kommer vi inte att hoppa till WordPress-specifik kod ännu. Istället kommer vi att stubba ut vår enhetstestklass. Om du har strukturerat din plugin-katalog baserat på vad vi delade i det första inlägget eller hur vi har konfigurerat det på GitHub, borde du ha en hello_reader_tests.php fil som finns i din tester / wordpress-tester katalogen. Du behöver naturligtvis inte följa den organisationen, men det kommer att hjälpa till när vi går vidare genom projektet.

Låt oss stubba ut enhetstestklassen:

require_once ('... / ... /plugin.php'); klass Hello_Reader_Tests utökar WP_UnitTestCase  // end class

Försök nu att köra testet med hjälp av terminalen med hjälp av PHP-enheten. Om du antar att du kör PHP-enhet från din lokala MAMP-installation, ska du kunna skriva in:

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

Vid denna tidpunkt bör du se ett misslyckande:

Det är bra! Det betyder att PHPUnit installeras och körs och att ditt WordPress Testing-ramverk är klart att gå. Testet misslyckades helt enkelt för att vi inte har skrivit några test. Låt oss börja göra det.

Vårt första test

Låt oss först skriva ett test för att se till att vårt plugin är initialiserat, installerat och redo för testning. Minns tidigare i den första artikeln att vi lagrade en referens till förekomsten av Hello Reader i PHP $ GLOBALS array. Så här får vi tillgång till det exemplet med testramen. Så låt oss uppdatera vårt test för att se så här ut:

Observera att jag, för rymdens skull, lämnar ut kodkommentarer, men det fullständigt kommenterade plugin-programmet och testen kommer att finnas tillgängliga på GitHub.

require_once ('... / ... /plugin.php'); klass Hello_Reader_Tests utökar WP_UnitTestCase privat $ plugin; funktion setUp () förälder :: setUp (); $ this-> plugin = $ GLOBALS ['hejläsare'];  // end setup funktion testPluginInitialization () $ this-> assertFalse (null == $ this-> plugin);  // slut testPluginInitialization // end class

Ovanstående har vi satt upp en referens till instansen av plugin så att vi kan komma åt den genom våra enhetstester. Vi använder inrätta Metod för att fånga referensen till plugin från $ GLOBALS. Observera dock att vi har introducerat en annan funktion som heter testPluginInitialization. Den här funktionen verifierar att referensen vi har inställt i inrätta Metoden är inte null.

Om du omprövar testen ska du nu få ett godkännande och din terminal ska se ut så här:

Det finns en viktig takeaway här: Observera att den enda funktionen som vi har angivit ovan har ett tydligt syfte: för att verifiera att plugin har initierats korrekt. Dess funktionsnamn är tydligt och innehåller ett enda uttalande. Det här är ett utmärkt sätt att modellera våra återstående test, främst för att det är lätt att hitta fel när de visas. Tänk på det på så sätt: Om du inkluderar ett antal olika påståenden i en enda funktion, kommer det att bli svårt att avgöra vilket påstående som uttalas misslyckas.

Den första funktionen

Nu när vi har introducerats för hur man skriver enhetstester, kör enhetstester, och utvärdera hur de passerar eller hur de misslyckas, låt oss börja implementera funktionalitet för plugin. Först måste vi installera ett filter för innehållet eftersom vi kommer att lägga till text till början av innehållet. I enlighet med den metod som vi definierade tidigare i den här artikeln, låt oss skriva vårt test först.

Det här specifika testet kommer att se om vi har bifogat en viss uppsättning text till den första delen av posten:

funktionstestAddWelcomeMessage () $ this-> assertEquals ('TEST CONTENT', $ this-> plugin-> add_welcome_message ('Detta är exempel efter innehåll. Detta simulerar att WordPress skulle återvända när man tittar på ett blogginlägg.'), 'add_welcome_message ) bifogar välkomstmeddelande till inläggets innehåll. ');  // slut testAddWelcomeMessage

Om du kör testet exakt som det kommer det inte ens att misslyckas - istället kommer PHPUnit att returnera ett dödligt fel eftersom metoden inte är definierad i plugin. Så låt oss lägga till det nu. Uppdatera plugin så här:

klass Hello_Reader funktion __construct () add_filter ('the_content', array (& $ this, 'add_welcome_message'));  // slutkonstruktörens offentliga funktion add_welcome_message ($ content)  // end add_welcome_message // slutklass

Försök nu att köra testet. Testet kommer inte att bomba, men du borde faktiskt se ett misslyckande tillsammans med ett tydligt meddelande om varför testet misslyckades:

1) Hello_Reader_Tests :: testAddWelcomeMessage add_welcome_message () bifogar välkomstmeddelande till inläggets innehåll. Misslyckades hävdar att noll matchar förväntat "TEST INNEHÅLL"

Så, i överensstämmelse med vår metodik, vill vi göra det här provet. För att göra det måste vi se till att inläggets innehåll innehåller textsträngen - i det här fallet "TEST INNEHÅLL', för att få det att passera. Så låt oss försöka detta. Uppdatera motsvarande funktion i plugin för att lägga till strängen innan innehållet:

offentlig funktion add_welcome_message ($ content) returnera "TEST CONTENT". content $;  // end add_welcome_message

Och igen, vi bara ompröva testet för att se att det misslyckas. Om du märker vårt test beror det på att det ser ut att se vårt innehåll är lika med "TEST INNEHÅLL"strängen. Istället måste vi se till att strängen börjar på innehållet. Det innebär att vi måste uppdatera vårt test. Lyckligtvis har PHPUnit en assertContains-funktion. Så låt oss uppdatera vår kod för att använda den:

funktionstestAddWelcomeMessage () $ this-> assertContains ('TEST CONTENT', $ this-> plugin-> add_welcome_message ('Detta är exempel efter innehåll. Detta simulerar att WordPress skulle återvända när man tittar på ett blogginlägg.'), 'add_welcome_message ) bifogar välkomstmeddelande till inläggets innehåll. ');  // slut testAddWelcomeMessage

Återigen, ompröva testet och du bör se att testet nu passerar. Grymt bra! Nu måste vi skriva anpassade meddelanden för personer som kommer från Twitter och personer som kommer från Google.

Välkomna våra Twitter besökare

Det finns ett antal olika sätt att vi kan kontrollera hur en användare har kommit fram till en viss sida. Ibland kan vi kontrollera värdena i $ _GET array, ibland kan vi ifrågasätta $ _SERVER array, eller ibland kan vi kontrollera en användares session. I det här exemplet ska vi leta efter "twitter.com" som finns i $ _SERVER [ 'HTTP_REQUEST']. Jag säger detta bara så att ni kan följa med vad vi gör i koden.

Så allmänt sett, add_welcome_message bör kontrollera om begäran har kommit från Twitter och skräddarsy sedan meddelandet på lämpligt sätt. Eftersom vi arbetar med att testa varje funktion, kan vi skriva en funktion som kan utvärdera om begäran kommer från Twitter. Så låt oss skriva ett nytt test:

I plugin:

allmän funktion is_from_twitter ()  // end is_from_twitter

I testet:

funktionstestIsComingFromTwitter () $ _SERVER ['HTTP_REFERER'] = 'http://twitter.com'; $ this-> assertTrue ($ this-> plugin-> is_from_twitter (), 'is_from_twitter () kommer att returneras sant när referensplatsen är Twitter.');  // end testIsComingFromTwitter

Vi är uppenbarligen spoofing the HTTP_REFERER värde, men det är okej för det här exemplet. Poängen kvarstår: kör testet, det kommer att misslyckas, så vi måste implementera funktionen i pluginet för att få det att passera:

allmän funktion is_from_twitter () return strpos ($ _SERVER ['HTTP_REFERER'], 'twitter.com')> 0;  // slut är_from_twitter

Ompröva testet borde nu resultera i ett provningsprov. Men vänta - vi måste vara kompletta. Låt oss se till att vi kör ett test för att verifiera att den här funktionen misslyckas när hänvisningen är inte från Twitter.

funktionstestIsNotComingFromTwitter () // Spoofing HTTP_REFERER för detta test och följeslag bloggblogg $ _SERVER ['HTTP_REFERER'] = 'http://facebook.com'; $ this-> assertFalse ($ this-> plugin-> is_from_twitter (), 'is_from_twitter () kommer att returneras sant när referensplatsen är Twitter.');  // slut testIsNotComingFromTwitter

Observera att vi har uppdaterat HTTP_REFERER och vi har ändrats assertTrue till assertFalse. Att tillåta allt annat är korrekt, kör testen och de ska passera.

Upprepa detsamma för Google

Att tillhandahålla ett anpassat meddelande till Google kräver samma sak som vi gjorde för Twitter, det vill säga spionera HTTP_REFERER och returnera sedan sant eller falskt för hjälparfunktionen. För att undvika att det blir överflödigt håller jag det här avsnittet så kortfattat som möjligt. Samma steg måste följas som för Twitter.

Först stubbar vi hjälpfunktionen i plugin:

allmän funktion is_from_google ()  // end is_from_google

Sedan stubbar vi ut testet:

funktionstestIsComingFromGoogle () $ _SERVER ['HTTP_REFERER'] = 'http://google.com'; $ this-> assertTrue ($ this-> plugin-> is_from_google (), 'is_from_google () kommer att returneras sant när referensplatsen är Google.');  // slut testIsComingFromGoogle

Att köra testet som det är just nu kommer att leda till ett misslyckande. Så, låt oss genomföra is_from_google () fungera:

allmän funktion is_from_google () return strpos ($ _SERVER ['HTTP_REFERER'], 'google.com')> 0;  // slut är_from_twitter

Och nu ska testet passera. Men igen måste vi vara kompletta så låt oss skriva felprovet för att anta att funktionen inte kommer att återvända sant när användare kommer ifrån någon annanstans:

funktion testIsNotComingFromGoogle () // Spoofing HTTP_REFERER för detta test och följeslag blogg blogg $ _SERVER ['HTTP_REFERER'] = 'http://facebook.com'; $ this-> assertFalse ($ this-> plugin-> is_from_google (), 'is_from_google () kommer att returneras sant när referensplatsen är Google.');  // slut testIsNotComingFromGoogle

Slutligen kör dina test. Att tillåta allt annat är korrekt, du borde ha sex provtagningar.

Dra allt ihop

Vid den här tiden har vi allt vi behöver för att börja visa vanliga välkomstmeddelanden till våra användare. Det enda är att vi måste refactor vårt första test som letar efter "TEST CONTENT." Nu måste vi introducera test för följande fall:

  • När användaren kommer från Twitter, säger vi "Välkommen från Twitter!"
  • När användaren kommer från Google, säger vi "Välkommen från Google!"
  • När användaren kommer från någon annanstans kommer vi inte att förbereda något.

Så låt oss ta bort det test vi skapade tidigare testAddWelcomeMessage i stället för att lägga till tre nya test.

Först lägger vi till ett test som kontrollerar Twitter välkomstmeddelandet.

I plugin reducerar vi add_welcome_message till detta:

offentlig funktion add_welcome_message ($ content) return $ content;  // end add_welcome_message

Och vi lägger till Twitter-testet, först:

funktionstestDisplayTwitterWelcome () // Spoof HTTP_REFERER för Twitter $ _SERVER ['HTTP_REFERER'] = 'http://twitter.com'; $ this-> assertContains ('Välkommen från Twitter!', $ this-> plugin-> add_welcome_message ('Detta är exempel efter innehåll. Detta simulerar att WordPress skulle återvända när man tittar på ett blogginlägg.'), 'add_welcome_message meddelande till inläggets innehåll. ');  // avsluta testDisplayTwitterWelcome

Vid denna tidpunkt är detta gammal hatt, eller hur? Kör det, testet kommer att misslyckas. Implementera add_welcome_message att se så här ut:

public function add_welcome_message ($ content) om ($ this-> is_from_twitter ()) $ content = 'Välkommen från Twitter!' . content $;  // slut om retur $ innehåll  // end add_welcome_message

Kör det igen, och det kommer att passera. Nästa upp är Google-testet:

funktionstestDisplayGoogleWelcome () // Spoof HTTP_REFERER för Google $ _SERVER ['HTTP_REFERER'] = 'http://google.com'; $ this-> assertContains ('Välkommen från Google!', $ this-> plugin-> add_welcome_message ('Detta är exemplet efter innehåll. Detta simulerar att WordPress skulle återvända när du tittar på ett blogginlägg.'), 'add_welcome_message meddelande till inläggets innehåll. ');  // avsluta testDisplayGoogleWelcome

Kör testet, misslyckas, uppdatera sedan add_welcome_message i plugin för att innehålla en check med hjälp av hjälparfunktionen som vi skrev tidigare:

public function add_welcome_message ($ content) om ($ this-> is_from_twitter ()) $ content = 'Välkommen från Twitter!' . content $;  annars om ($ this-> is_from_google ()) $ content = 'Välkommen från Google!' . content $;  // slut om retur $ innehåll  // end add_welcome_message

Vid denna punkt borde du ha ett fullt fungerande plugin som har sju godkända enhetstester!


Slutsats

Som du kan se, introducerar enhetstestning en ytterligare utvecklingsnivå men kan betala betydligt i underhållsbar, välorganiserad och testbar kod. När din ansökan växer, fortsätter testen kontinuerligt för att verifiera att dina projekt fungerar som förväntat, vilket kan ge dig sinnesro. Det här är naturligtvis bara ett litet exempel på hur enhetstestning fungerar. Att tillämpa dessa metoder kan löna sig i mycket större och / eller komplicerade projekt.

Slutligen kan du hitta det här pluginet, WordPress-testen och Hello Reader-enhetstesterna fullt kommenterade GitHub.