Intro
Jag har utforskat enhetstestning och testa täckning för JavaScript som jag arbetar på en ny SharePoint-app för SharePoint online i Office 365 svit. De uppenbara forskning vägar ledde mig till Qunit.js och direkt efter att, till Blanket.js.
QUnit Låt mig ställa in enhetstester och gruppera dem i moduler. En modul är bara ett enkelt sätt att organisera relaterade tester. (Jag vet inte om jag använder det som avsett, men det fungerar för mig hittills med liten uppsättning tester som jag hittills har definierat).
Blanket.js integreras med Qunit och det kommer Visa mig de faktiska rader JavaScript som var – och ännu viktigare-inte faktiskt avrättades under kör testerna. Detta är "täckning"-rader som avrättades omfattas av testet medan andra inte är.
Mellan att ställa in bra testfall och Visa täckning, Vi kan minska risken att vår kod har dolda defekter. Goda tider.
Qunit
Förutsatt att du har din Visual Studio projektet skapa, börja med att ladda ner JavaScript paketet från http://qunitjs.com. Lägga till JavaScript och motsvarande CSS i din lösning. Mine ser ut såhär:
Figur 1
Som ni kan se, Jag var med 1.13.0 på tiden skrev jag detta blogginlägg. Glöm inte att hämta och lägga till CSS-filen.
Som ur vägen, Nästa steg är att skapa något slags test sele och referera de Qunit bitarna. Jag testar en massa funktioner i en skriptfil som kallas "QuizUtil.js" så jag skapade en HTML-sida som kallas "QuizUtil_test.html" som visas:
Här är koden:
<!DOCTYPE HTML> <HTML xmlns= "http-://www.w3.org/ 1999/xhtml"> <huvud> <titel>QuizUtil test med Qunit</titel> <länk rel= "stylesheet" href="../CSS/qunit-1.13.0.CSS" /> <skript typ= text/javascript"" src="QuizUtil.js" data-cover></skript> <script typ ="text/javascript" src ="qunit-1.13.0.js"></skript> <script typ ="text/javascript" src ="blanket.min.js"></skript> <skript> modul("getIDFromLookup"); Testa("QuizUtil getIDFromLookupField", funktionen () { var goodValue = "1;#Paul Galvin"; lika(getIDFromLookupField(goodValue) + 1, 2), "ID för [" + goodValue + "] + 1 bör vara 2"; lika(getIDFromLookupField(undefined), undefined, "Odefinierad indataargumentet bör återvända odefinierat resultatet."); lika(getIDFromLookupField(""), undefined, "Tom indataargumentet ska returnera ett odefinierat värde."); lika(getIDFromLookupField("gobbledigood3-thq;dkvn ada;skfja sdjfbvubvqrubqer0873407t534piutheqw;vn"), undefined,"Ska alltid returnera ett resultat Cabriolet till ett heltal"); lika(getIDFromLookupField("2;#någon annan person"), "2", "Kontrollera [2;#någon annan person]."); lika(getIDFromLookupField("9834524;#lång värde"), "9834524", "Stort värde test."); notEqual(getIDFromLookupField("5;#någon", 6), 6, "Testa en notEqual (5 är inte lika med 6 för detta prov: [5;#någon]"); }); modul("htmlEscape"); Testa("QuizUtil htmlEscape()", funktionen () { lika(htmlEscape("<"), "<", "Fly en mindre än-operator ('<')"); lika(htmlEscape("<div class = "someclass">Lite text</div>"), "<div class ="someclass">Lite text</div>", "Mer komplex test sträng."); }); modul("getDateAsCaml"); Testa("QuizUtil getDateAsCaml()", funktionen () { lika(getDateAsCaml(nya Datum("12/31/2013")), "2013-12-31T:00:00:00", "Testa hårdkodade datum: [12/31/2013]"); lika(getDateAsCaml(nya Datum("01/05/2014")), "2014-01-05T:00:00:00", "Testa hårdkodade datum: [01/05/2014]"); lika(getDateAsCaml(nya Datum("01/31/2014")), "2014-01-31T:00:00:00", "Testa hårdkodade datum: [01/31/2014]"); lika(getTodayAsCaml(), getDateAsCaml(nya Datum()), "getTodayAsCaml() ska vara lika getDateAsCaml(nytt datum())"); lika(getDateAsCaml("nonsens värde"), undefined, "Försöka få datum för ett nonsens värde."); lika(getDateAsCaml(undefined), undefined, "Försöka få datum för den [undefined] datum."); }); modul("getParameterByName"); Testa("QuizUtil getParameterByName (från frågesträngen)", funktionen () { lika(getParameterByName(undefined), undefined, "Försöka få odefinierad parameter bör återvända odefinierat."); lika(getParameterByName("finns inte"), undefined, "Försöka få parametervärde när vi vet att parametern inte finns."); }); modul("Cookies"); Testa("QuizUtil olika cookie funktioner.", funktionen () { lika(setCookie("test", "1", -1), getCookieValue("test"), "Få en cookie som jag ska fungera."); lika(setCookie("anycookie", "1", -1), sant, "Ange en giltig matlagning ska returnera 'true'."); lika(setCookie("crazy cookie-namn !@#$%"%\^&*(()?/><.,", "1", -1), sant, "Ställa in en dålig cookie-namn ska returnera"falska"."); lika(setCookie(undefined, "1", -1), undefined, "Passerar odefinierat som namnet på cookie."); lika(getCookieValue("finns inte"), "", "Cookie finns inte testet."); }); </skript> </huvud> <organ> <div ID= "qunit"></div> <div ID= "qunit-fixtur"></div> </organ> </HTML>
Det finns flera saker som händer här:
- Referera till min kod (QuizUtil.js)
- Referenser Qunity.js
- Definiera några moduler (getIDFromLookup, Cookies, och andra)
- Att placera en <div> vars ID är "qunit".
Sedan, Jag dra bara upp denna sida och du får något sådant:
Figur 3
Om du tittar överst, har du några alternativ, varav två är intressant:
- Dölj klarat tester: Ganska uppenbart. Kan hjälpa ögat bara se problemområden och inte en massa skräp.
- Modul: (släpp ner): Detta kommer att filtrera testerna till just dessa grupper av tester som du vill.
När det gäller testerna själva-några kommentarer:
- Det säger sig självt att du måste skriva din kod så att det är testbara i första hand. Med hjälp av verktyget kan hjälpa till att upprätthålla den disciplinen. Till exempel, Jag hade en funktion som kallas "getTodayAsCaml()”. Detta är inte mycket testbara eftersom det tar ingen indataargumentet och testa det för jämställdhet, Vi skulle behöva ständigt uppdatera Provningsmetod för att återspegla det aktuella datumet. Jag refactored det genom att lägga till en indataparameter för data sedan passerar det aktuella datumet när jag vill ha dagens datum i CAML-format.
- Ramen Qunit dokumenterar sina egna tester och det verkar ganska robust. Det kan göra enkla saker som att testa för jämställdhet och har även stöd för ajax stil samtal (både "riktiga" eller hånade med din favorit knäcka).
- Gå igenom processen också tvingar dig att tänka igenom kant fall – vad händer med "odefinierade" eller null överförs till en funktion. Det gör att det är död enkel att testa dessa scenarier ut. Bra grejer.
Täckning med Blanket.js
Blanket.js kompletterar Qunit genom att spåra de faktiska kodrader som kör under köra dina tester. Det integrerar rätt in i Qunit så även om det är en helt separat app, Det leker fint-det ser verkligen ut som det är en smidig app.
Detta är blanket.js i aktion:
Figur 5
(Du måste faktiskt Klicka på kryssrutan "Aktivera täckning" överst [se figur 3] att möjliggöra detta.)
Markerade rader i figur 5 har inte utförts av någon av mina tester, så jag behöver att utforma ett test som orsakar dem att köra om jag vill ha full täckning.
Få blanket.js fungerar på följande sätt:
- Ladda ner från http://blanketjs.org/.
- Lägg till det i projektet
- Uppdatera din sele testsida (QuizUtil_test.html i mitt fall) enligt följande:
- Referens koden
- Dekorera din <skript> referens gillar detta:
<skript typ= text/javascript"" src="QuizUtil.js" data-cover></skript>
Blanket.js plockar upp attributet "data-cover" och gör sin magi. Det krokar i Qunit, uppdateringar av UI för att lägga till alternativet "Aktivera täckning" och voila!
Sammanfattning (TL; DR)
Använda Qunit för att skriva din testfall.
- Ladda ner den
- Lägg till det i projektet
- Skriva en testsida sele
- Skapa dina tester
- Refactor några av din kod vara testbara
- Vara kreativ! Tror galen, omöjligt scenarier och testa dem ändå.
Använd blanket.js för att säkerställa täckning
- Kontrollera att Qunit fungerar
- Hämta blanket.js och lägga till ditt projekt
- Lägga till din sele testsida:
- Lägg till en hänvisning till blanket.js
- Lägga till en "data-cover" attribut till din <skript> tag
- Köra din Qunit tester.
Jag aldrig gjorde något av detta innan och hade några elementära saker som arbetar i en handfull timmar.
Glad testning!
</slutet>
Följ mig på Twitter vid http://www.twitter.com/pagalvin