I min presentation på Valtech Tech-day presenterade jag olika tekniker för att få snabba tester med Node.js. En av teknikerna är att profilera sina tester på samma sätt som sin produktionskod. Att profilera en applikation (eller tester) innebär att du får se var din applikation spenderar CPU-tid. Om det finns tydliga flaskhalsar i din kod kommer du se dem som platser där en stor del av CPU-tiden spenderas. Det är precis den koden som lönar sig att optimera mest.
Varför är det viktigt med snabba tester?
Det finns flera anledningar. En långsam testsvit leder till en ovilja att köra testerna. Istället för att köra dem själv så börjar du förlita dig på att byggservern ska köra testerna istället, med fler trasiga byggen som följd. Ännu skadligare blir en långsam testsvit om den får dig att tveka inför att skriva nya tester. Eftersom du inte vill göra testerna ännu långsammare, genom att lägga till fler, blir din kod mindre och mindre vältestad. Med en riktigt snabb testsvit kör du testerna oftare och tvekar inte för att lägga till nya. Och så blir det ju mycket roligare att utveckla när du slipper vänta!
Nodetime är gratis om du bara använder den för en applikation i taget vilket är det normala under utveckling. Det vanliga sättet att profilera en applikation med Nodetime är att installera dessnpm-modul, inkludera modulen överst i din kod, lasta din server med Apache Bench,Locust, JMeter eller liknande och så trycka på profileringsknappen i Nodetimes webbgränssnitt. Efter några sekunder dyker profileringsdatan upp på skärmen och du kan klicka dig runt för att se om din kod behöver optimeras.
En enkel lösning är att köra något test (helst ett långsamt!) många gånger i rad. Använder du Mocha för att köra dina test behöver du bara göra en loop kring test-definitionen för att köra godtyckligt många kopior av ett testfall.
Att profilera tester är lite annorlunda
Du måste till exempel se till att Node.js-processen inte stängs av innan Nodetime skickat profilerings-datan till molnet. Och du måste köra testerna kontinuerligt under profileringen för att få bra mätvärden. Om testerna tar kortare tid att köra än tiden du mäter kommer det inte vara lika tydligt vilken kod du bör optimera.
|
1
2
3
|
it('runs slowly', function (done) { ...}) |
kan köras 100 gånger genom att köras i en loop
|
1
2
3
4
5
|
for (var i = 0; i < 100; i++) { it('runs slowly', function (done) { ... })} |
Nu kan du starta dina tester (glöm inte att Nodetime-modulen måste installeras och aktiveras) och profilera under tiden som testerna körs.
Något som kan försvåra profileringen ytterligare är test-biblioteket Nock. Nock är en förträfflig HTTP-mocknings-modul som jag varmt rekommenderar men som kan förhindra Nodetime från att alls ladda upp sin data. Även om du ställer in Nock för att tillåta riktiga HTTP-anrop så misslyckas Nodetime med sin uppladdning. Jag har misslyckats med att komma fram till varför, men det är inte helt förvånande med tanke på att nock byter ut de underliggande http och https modulerna i Node.js för att göra sitt jobb.
Som tur är kan du tjuvkika på profileringsdatan ändå. Liksom alla andra Node.js moduler kan du läsa källkoden till nodetime och dessutom göra ändringar i den. Genom att ändra källkoden kan du skriva profileringsdatan till disk och profilera testerna trots att de använder nock.
Gör såhär:
Installera nodetime med ”npm install nodetime”. Öppna ”node_modules/nodetime/lib/saas/saas-client.js” och leta reda på metoden ”SaasClient.prototype._push”. Det är den här metoden som står för själva uppladdandet. Först i den metoden lägger du till:
|
1
|
require("fs").writeFileSync("profile.json "> |
Det kommer se till att profileringsdatan sparas ner i JSON-dokumentet ”profile.json”. Nu spelar det inte längre någon roll om nätverksuppkopplingen fungerar eller inte!
Lägg nu till nodetime start-koden i ditt långsamma testfall och kör det många gånger i rad enligt ovan, växla över till https://nodetime.com/ och aktivera CPU-profilering. Vänta lite och profile.json dyker strax upp. I den här filen har du all exekveringsinformation i all sin härlighet. Sök efter det reguljära uttrycket ”[0-9]{2,}\.[0-9]{2}%” så hittar du alla funktioner i koden som tar upp mer än 10% av tiden. Förhoppningsvis hittar du någon sådan och har du tur är det något självklart.
I mitt fall visade det sig att testerna av en webbapplikation gick onödigt långsamt eftersom mall-cachning var avslaget när testerna kördes.
Varje testanrop till webbapplikationen innebar att en hel hög med mallar kompilerades om från scratch. Genom att aktivera mall-cachning, vilket bara krävde en ändring i en konfigurationfil, så gick testerna mer än tre gånger så snabbt!
Förhoppningsvis lyckas du också snabba upp dina tester, med ovanstående teknik, och får njuta av utveckling med mindre väntetid. Lycka till!