De beste manieren om uw serverloze applicaties te testen

Serverless is meer dan een cloud computing-uitvoeringsmodel. Het verandert de manier waarop we apps plannen, bouwen en implementeren. Maar het verandert ook de manier waarop we onze apps testen.

Ontmoet Alex. Alex is een gewone JavaScript-ontwikkelaar, de laatste tijd gefocust op Node.js.

Dit is Alex

De afgelopen maanden praten zijn goede vrienden, Anna en Jeff, altijd over dat serverloze gedoe. Zelfs al zijn ze van tijd tot tijd vervelend, hij houdt van het idee van apps zonder server. Hij heeft op een gegeven moment zelfs enkele eenvoudige functies geïmplementeerd in AWS Lambda en Azure.

Anna en Jeff hebben het altijd over dat serverloze gedoe

Op een gegeven moment kregen Alex en zijn team een ​​nieuw project. Na enige analyse dacht Alex dat het de perfecte oplossing zou zijn voor serverloos. Hij presenteerde het idee aan zijn team. Sommige teamleden waren enthousiast, een van hen vond het niet leuk, maar de meeste hadden geen sterke mening. Dus besloten ze het te proberen - het project was niet te groot en het risico was laag.

Alex’s team bespreekt het gebruik van serverless op hun nieuwe project

Het team las over serverloos en ze kregen een idee hoe ze hun nieuwe app moesten structureren. Maar niemand wist zeker hoe ze serverloos in hun gemeenschappelijke ontwikkelingsproces moesten passen.

Op dat moment ziet hun proces er als volgt uit:

  1. Ze analyseren een nieuwe functie.
  2. Voor minder complexe functies beginnen ze met de code, vervolgens voeren ze deze lokaal uit en voegen uiteindelijk een aantal tests toe.
  3. Voor complexere functies maken ze hun versie van TDD: ze beginnen met tests, schrijven vervolgens de code en testen deze lokaal.
  4. Wanneer de functie gereed is, gaat deze naar de CI-tool die deze implementeert in de testomgeving.
  5. Vervolgens neemt het QA-team een ​​nieuwe functie voor nog een ronde van handmatig testen. Als alles er goed uitziet, gaat de app via CI naar productie.
Het gemeenschappelijke ontwikkelingsproces van het team van Alex

Ze besloten om stap voor stap te beginnen en vervolgens de problemen op te lossen die ze tegenkwamen.

Ze kozen een kleine functie, en omdat het eenvoudig was, begonnen ze met de code. Toen het codeergedeelte klaar was, troffen ze de eerste wegversperring: hoe voer je lokaal serverloze applicaties uit?

Lokaal testen

Met apps zonder server beheert u de infrastructuur niet. Klinkt geweldig, maar hoe voer je je applicatie vervolgens lokaal uit? Kun je dat zelfs?

Eerste wegversperring: hoe voer je een serverloze applicatie lokaal uit?

Afhankelijk van uw app en serverloze leverancier, kunt u sommige delen van uw app lokaal uitvoeren. Om dit te doen, kunt u enkele van de volgende hulpmiddelen en technieken gebruiken:

  • Azure Functions Core Tools (voor Azure-functies)
  • AWS SAM CLI (voor AWS Lambda-apps gebouwd met AWS SAM)
  • Tools van derden (bijv. Localstack)
  • docker-lambda voor lokale simulatie van AWS Lambda
  • Voer de Node.js-functie lokaal uit

Natuurlijk is de lijst niet compleet - er zijn meer tools en we zien nu bijna elke dag nieuwe tools.

De meeste van deze tools hebben bepaalde beperkingen. Ze kunnen serverloze functies en een paar andere services simuleren, zoals API Gateway. Maar hoe zit het met machtigingen, auth-laag en andere services?

Lokaal testen helpt bij snelle validaties om ervoor te zorgen dat uw functie werkt. Maar is er een betere manier om ervoor te zorgen dat uw serverloze app werkt zoals bedoeld? Ja dat is er. De eerste en belangrijkste stap is: schrijf tests.

Dus probeerden Alex en zijn team hun eerste functie lokaal, en het leek te werken. Toen gingen ze naar de volgende stap.

Geautomatiseerde tests

Alex en zijn team zijn net overgeschakeld naar Jest voor het testen van hun Node.js-applicaties. Ze doen nog steeds veel front-end, dus ze willen dezelfde tools gebruiken voor de volledige stapel wanneer ze maar kunnen. Kunnen ze Jest ook gebruiken voor het testen van serverloze apps? En wat moeten ze testen?

Tweede wegversperring: hoe beïnvloedt serverloos geautomatiseerd testen?

Na een snel onderzoek beseften ze dat ze hun favoriete Node.js-testtools konden gebruiken. Jest, Jasmine, Mocha en anderen werken prima met serverless.

Wat moet je testen in een serverloze app?

Met hun Node.js-apps volgen Alex en zijn team de drieledige testautomatiseringspiramide. De testpiramide werd voor het eerst genoemd door Mike Cohn in zijn boek 'Succeeding with Agile'.

Zoals de testpiramide definieert, hebben ze:

  • Veel unit tests, omdat ze het goedkoopst zijn (snelst om te schrijven en uit te voeren)
  • Minder integratietests, omdat ze duurder zijn en ze meer tijd nodig hebben om te draaien
  • Een paar UI-tests, omdat ze het duurst zijn (vereist een GUI-tool) en het langzaamst kunnen worden uitgevoerd

Naast deze hebben ze ook handmatige sessie-gebaseerde testen, gedaan door hun QA-team.

testpiramide met handmatig testen

Hoe beïnvloedt serverloos de testautomatiseringspiramide?

Het antwoord hangt af van de laag. Maar de testpiramide lijkt minder op de Egyptische piramides, en meer op de Maya-piramides.

De eenheidstestlaag wordt niet veel beïnvloed. Eenheidstests zijn nog steeds de goedkoopste om te schrijven en uit te voeren, maar de eenheden kunnen kleiner zijn.

Integratietestslaag wordt belangrijker dan ooit, omdat apps zonder server sterk afhankelijk zijn van integraties. Het is ook goedkoper, omdat een serverloze database alleen voor testen goedkoop is. Dus in een serverloze "testpiramide" moet u meer integratietests hebben.

GUI-testlaag is ook goedkoper en sneller, vanwege goedkopere parallellisatie.

Handmatige testlaag blijft hetzelfde. Maar serverloos kan u helpen om het enigszins te verbeteren. We zullen daar later op in gaan.

Serverloze 'testpiramide'

Alex en zijn team hadden eindelijk een idee waar ze zich op moesten concentreren. Het volgende probleem was hoe een functie te schrijven om ze gemakkelijker te testen.

Hoe een testbare serverloze functies te schrijven

U moet nadenken over de volgende risico's terwijl u een serverloze functie schrijft:

  • Configuratierisico's Zijn de database en de tabel correct? Of heeft u toegangsrechten?
  • Technische workflow-risico's Ontleden en gebruikt u het inkomende verzoek zoals u zou moeten? Of gaat u correct met reacties en fouten om?
  • Risico's van bedrijfslogica Hebt u alle regels voor bedrijfslogica gevolgd die uw toepassing heeft?
  • Integratierisico's Leest u de inkomende aanvraagstructuur correct? Of slaat u de bestelling correct op in de database?

Om te bevestigen dat uw serverloze functie correct werkt, moet u al deze risico's testen.

U kunt elk van deze testen, net zoals bij de integratietests. Maar het instellen en configureren van de service telkens wanneer u op een van deze risico's wilt testen, is niet optimaal. Zoals mijn vriend Aleksandar Simovic graag zegt:

Stel je voor dat het testen van auto's op die manier werd gedaan. Dat zou betekenen dat je elke keer dat je een enkele schroef of zelfs een spiegel in een auto wilde testen, de hele auto moest monteren en demonteren.

Om de app testbaarder te maken, is de duidelijke oplossing om uw functie op te splitsen in verschillende kleinere.

Een van de beste manieren om dit te doen, is Hexagonale architectuur toepassen op uw serverloze functies.

Hexagonale architectuur, of poorten en adapters, is een vorm van applicatie-architectuur die de scheiding van zorgen bevordert door middel van verantwoordelijkheidslagen. Als de maker, Alistair Cockburn, legt uit:

Toestaan ​​dat een applicatie op dezelfde manier wordt aangestuurd door gebruikers, programma's, geautomatiseerde test- of batchscripts, en wordt ontwikkeld en getest in isolatie van de eventuele runtime-apparaten en databases.

Dus, hoe is dat van toepassing op serverloze functies?

Toen Alex en zijn team AWS gebruikten, kregen ze een structuur als de volgende:

  • Functie bedrijfslogica legt weinig "poorten" bloot (of verwacht weinig argumenten). Bijvoorbeeld een voor een inkomende gebeurtenis, een voor permanente opslag en een voor meldingen.
  • Ze hebben twee adapters voor het evenement dat een functie activeert, een voor de echte AWS Lambda-trigger en een andere voor lokale tests.
  • Ze hebben verschillende adapters voor permanente opslag en meldingen. Bijvoorbeeld DynamoDB tafeladapter en geheugenadapter.
Zeshoekige architectuur van AWS Lambda-functie

Alex en zijn team waren blij dat ze vooruit gingen. Maar voordat we verder gaan, laten we kijken hoe zeshoekige architectuur elke laag van de testpiramide beïnvloedt.

Testen van een eenheid

Eenheidstests bleven hetzelfde. Maar het is gemakkelijker om eenheidstests te schrijven vanwege de hexagonale architectuur. Ze kunnen eenvoudig een lokale adapter of mock als adapter gebruiken om de functionele bedrijfslaag afzonderlijk te testen.

Integratie testen

Integratietests hebben veel geprofiteerd van Hexagonal Architecture. Ze waren in staat om integraties die ze bezitten volledig te testen. Integraties van derden worden gesimuleerd met andere adapters.

Hoe werkt dat in de praktijk?

Elk van hun serverloze functies heeft lambda.js- en main.js-bestanden. Het hoofdbestand bevat de bedrijfslogica van een serverloze functie. En het lambda.js-bestand is verantwoordelijk voor het bedraden van de adapters en het aanroepen van het main.js-bestand.

Het hoofdbestand heeft zijn eigen unit- en integratietests. Maar de integratietests testen niet de volledige integratie met eindservices, zoals AWS S3, omdat dat hen zou vertragen. In plaats daarvan gebruiken ze een adapter in het geheugen om de functie met integratie van bestandsopslag te testen.

AWS S3-integratie gebeurt via de FileRepository, die zijn eigen unit- en integratietests heeft. Integratietests controleren AWS S3 om er zeker van te zijn dat de eindintegratie echt werkt.

In tegenstelling tot main.js heeft het bestand lambda.js geen tests, omdat het meestal maar een paar regels code heeft.

Visuele weergave van enkele AWS Lambda-functie met tests

Deze aanpak lijkt op de techniek die het MindMup-team gebruikt om serverloze functies te testen. Hiermee kunt u eenvoudig integraties van uw functies testen en uw integratietests nog sneller maken.

GUI testen

Omdat Alex en zijn team een ​​back-end voor de app bouwden, was de GUI-testlaag niet relevant. Maar toen ze meer leerden over serverloos, realiseerden ze zich dat ze het konden gebruiken om de GUI-testlaag te verbeteren voor de andere apps waaraan ze werkten.

UI-tests zijn duur en traag, omdat ze in de browser worden uitgevoerd. Maar serverloos is goedkoop en schaalt snel.

Als ze een browser in AWS Lambda zouden kunnen draaien, zouden ze goedkope parallellisatie krijgen. Dat zou hun UI-tests goedkoper en sneller maken.

Maar kunt u een browser, zoals Chrome, uitvoeren in een serverloze functie?

Ja! En het is eenvoudig met behulp van tools zoals Serverless Chrome, Chromeless en Puppeteer.

AWS Lambda-functies gebruiken voor parallellisatie van UI-tests

Een combinatie van serverloze en headless browsers kan ons een nieuwe generatie UI-testtools brengen. We kunnen er al enkele zien en uitproberen, zoals Appraise.

CI / CD

Toen Alex en zijn team hun eerste serverloze functie testten, was het tijd om de code in de testomgeving te implementeren. Dat bracht een nieuwe vraag op: hoe kunnen ze CI / CD-tools gebruiken om hun serverloze app te implementeren?

Het antwoord is eenvoudig: ze kunnen een CI-tool gebruiken om de tests uit te voeren en de app te implementeren. Gebruik de populaire tool, zoals Claudia.js, AWS SAM en Serverless Framework om de app te implementeren.

U kunt nog steeds uw favoriete CI-tool gebruiken (zoals Jenkins, TravisCI of SemaphoreCI), of als u bij AWS wilt blijven, kunt u AWS CodeBuild proberen.

Handmatig testen

Zelfs door handmatig testen wordt het niet direct beïnvloed door serverloos, het team heeft een manier gevonden om hun QA-proces te verbeteren.

Stadia en implementaties van een serverloze app zijn goedkoop en vaak snel in te stellen. Met serverloos betaal je ook niet voor de app als niemand hem gebruikt.

Dit betekent dat het hebben van een testomgeving nooit goedkoper is geweest!

Met serverless kunt u de functie vaak van de ene fase naar de andere promoten. Dit betekent dat uw QA-team een ​​functie kan testen en wanneer ze bevestigen dat deze werkt, kunt u dezelfde functie promoten bij de productie.

Verder testen

Alex en zijn team hebben hun eerste serverloze functie naar pre-productie verzonden en het team was blij dat ze leerden hoe ze serverloze apps konden testen.

Ze bleven serverloos gebruiken in het project en introduceerden het in enkele andere projecten. Alex voegde zich bij zijn vrienden Anna en Jeff, als een derde, soms irritante, serverloze prediker. En ze leefden nog lang en gelukkig.

Serverloze predikersploeg heeft een nieuw lid

Post-script

Maar hoewel hun app goed was getest, gebeurde er iets 's nachts.

Na een onderzoek kwamen ze erachter dat een van de integraties veranderde. Ze leerden dat testen belangrijk is voor apps zonder server, maar het is niet genoeg.

Aangezien apps zonder server sterk afhankelijk zijn van integraties, verschuift het risico van uw code naar de integraties. En om integratiewijzigingen te kunnen opvangen en snel te kunnen reageren, heeft uw app een goede monitoring nodig.

Gelukkig zijn er elke dag meer en meer serverloze monitoringtools op de markt. Sommige van de goede en populaire opties zijn IOpipe, Thundra, Dashbird en Epsagon.

Maar serverloze apps hebben vaak een dikke client, wat betekent dat back-end monitoring niet genoeg is. U hebt een soortgelijk hulpmiddel nodig voor uw frontend. Deze markt heeft ook veel leuke tools, zoals Sentry en Rollbar.

Maar in de geest van serverloos hebben we een open source-app voor het bijhouden van fouten gemaakt, genaamd Desole. Het is een serverloze app die u in uw AWS-account kunt installeren. Het stelt organisaties in staat uitzonderingen en fouten van applicaties te volgen zonder te hoeven kiezen tussen het gemak van software-as-a-service en de beveiliging van een zelfgehoste oplossing. Je kunt het hier bekijken: https://desole.io.

Desole, open source error-tracking, nauw geïntegreerd met AWS
Alle illustraties zijn gemaakt met de SimpleDiagrams4-app.

Als je meer wilt weten over het testen en bouwen van serverloze apps met behulp van Node.js en AWS, bekijk dan "Serverloze toepassingen met Node.js", het boek dat ik schreef met Aleksandar Simovic voor het Manning-publicaties:

Het boek leert je meer over serverloos testen, met codevoorbeelden, maar je leert ook hoe je een echte serverloze API (met DB en authenticatie) kunt bouwen en debuggen met behulp van Node en Claudia.js. En je leert hoe je chatbots bouwt voor Facebook Messenger en SMS (met behulp van Twilio) en Alexa-vaardigheden.