De beste måtene å teste serverløse applikasjoner på

Serverløs er mer enn en eksekveringsmodell for cloud computing. Det endrer måten vi planlegger, bygger og distribuerer apper. Men det endrer også måten vi tester appene våre på.

Møt Alex. Alex er en vanlig JavaScript-utvikler, med fokus på Node.js i det siste.

Dette er Alex

I løpet av de siste månedene snakker alltid de gode vennene hans, Anna og Jeff, om den serverløse tingen. Selv gjennom de er irriterende fra tid til annen, liker han ideen om serverløse apper. Han distribuerte til og med få enkle funksjoner til AWS Lambda og Azure på et tidspunkt.

Anna og Jeff snakker alltid om den serverløse tingen

På et tidspunkt fikk Alex og teamet hans et nytt prosjekt. Etter litt analyse tenkte Alex at det ville være den perfekte passformen for serverløs. Han presenterte ideen for teamet sitt. Noen av gruppemedlemmene var begeistret, en av dem likte ikke det, men de fleste av dem hadde ikke en sterk mening. Så de bestemte seg for å prøve det - prosjektet var ikke for stort, og risikoen var lav.

Alexs team diskuterer bruk av serverløs på det nye prosjektet deres

Teamet leste om serverløst, og de fikk en ide om hvordan de strukturerte sin nye app. Men ingen var sikre på hvordan de skulle passe serverløse inn i deres felles utviklingsprosess.

I det øyeblikket ser prosessen slik ut:

  1. De analyserer en ny funksjon.
  2. For mindre komplekse funksjoner begynner de med koden, deretter kjører de den lokalt og legger til noen tester til slutt.
  3. For mer komplekse funksjoner gjør de sin versjon av TDD: de starter med tester, skriver deretter koden og tester den lokalt.
  4. Når funksjonen er klar, går den til CI-verktøyet som distribuerer det til testmiljøet.
  5. Da tar QA-teamet en ny funksjon for en ny runde med manuell testing. Hvis alt ser bra ut, går appen gjennom CI til produksjon.
Alex teamets felles utviklingsprosess

De bestemte seg for å starte trinn for trinn, og deretter løse problemene når de møtte dem.

De valgte en liten funksjon, og da det var enkelt, startet de med koden. Da kodingsdelen var klar, traff de den første veisperringen: hvordan kjører du serverløse applikasjoner lokalt?

Lokal testing

Med serverløse apper administrerer du ikke infrastrukturen. Høres bra ut, men hvordan kjører du applikasjonen din lokalt? Kan du til og med gjøre det?

Første veisperring: hvordan kjører du serverløs applikasjon lokalt?

Avhengig av appen din og serverløs leverandør, kan du kjøre noen deler av appen din lokalt. For å gjøre det, kan du bruke noen av følgende verktøy og teknikker:

  • Azure Functions Core Tools (for Azure-funksjoner)
  • AWS SAM CLI (for AWS Lambda-apper bygget med AWS SAM)
  • Tredjepartsverktøy (dvs. localstack)
  • docker-lambda for AWS Lambda lokal simulering
  • Kjør Node.js-funksjonen lokalt

Listen er selvfølgelig ikke komplett - det er flere verktøy, og vi ser nye verktøy nesten hver dag nå.

De fleste av disse verktøyene har visse begrensninger. De kan simulere serverløse funksjoner og noen få andre tjenester, for eksempel API Gateway. Men hva med tillatelser, autorisasjon og andre tjenester?

Lokal testing hjelper med raske valideringer for å sikre at funksjonen din fungerer. Men er det en bedre måte å sørge for at den serverløse appen din fungerer som den er ment? Ja det er. Det første og viktigste trinnet er: skrive tester.

Så Alex og teamet hans prøvde sin første funksjon lokalt, og da det så ut til å virke. Så gikk de til neste trinn.

Automatiserte tester

Alex og teamet hans byttet til Jest for å teste sine Node.js-applikasjoner. De gjør fremdeles mye frontend, så de vil bruke de samme verktøyene for full bunke når de kan. Kan de bruke Jest til å teste serverløse apper også? Og hva skal de teste?

Andre veisperring: hvordan påvirker serverløs automatisert testing?

Etter en rask undersøkelse innså de at de kan bruke sine favoritt Node.js-testverktøy. Jest, Jasmine, Mocha og andre fungerer fint med serverløst.

Hva bør du teste i en serverløs app?

Med Node.js-appene sine følger Alex og teamet hans den tre-lags automatiseringspyramiden. Testpyramiden ble først omtalt av Mike Cohn i sin bok "Succeeding with Agile".

Som testpyramiden definerer, har de:

  • Mange enhetstester, fordi de er de billigste (raskest å skrive og kjøre)
  • Færre integrasjonstester, fordi de er dyrere, og de tar mer tid å kjøre
  • Noen få UI-tester, fordi de er de dyreste (krever noe GUI-verktøy) og tregest å kjøre

I tillegg til disse har de også manuell øktbasert testing, utført av deres QA-team.

testpyramide med manuell testing

Hvordan påvirker serverløs testautomatiseringspyramiden?

Svaret avhenger av nivået. Men testpyramiden ligner mindre på de egyptiske pyramidene, og mer som mayapyramidene.

Enhetstestsjiktet påvirkes ikke mye. Enhetstester er fremdeles de billigste å skrive og kjøre, men enhetene kan være mindre.

Integrasjonstestlag blir viktigere enn noen gang, fordi serverløse apper er veldig avhengige av integrasjoner. Det er også billigere, for det er billig å ha en serverløs database bare for testing. Så i en serverløs "testpyramide" må du ha flere integrasjonstester.

GUI-testlag er også billigere og raskere, på grunn av billigere parallellisering.

Manuelt testlag forblir det samme. Men serverløs kan hjelpe deg med å forbedre det litt. Vi vil gå nærmere inn på detaljene om det senere.

Serverløs

Alex og teamet hans hadde endelig en ide om hvor de skulle fokusere. Neste problem var hvordan man skriver en funksjon for å teste dem lettere.

Hvordan skrive en testbar serverløs funksjon

Du må tenke på følgende risikoer mens du skriver en serverløs funksjon:

  • Konfigurasjonsrisiko Er databasen og tabellen riktig? Eller har du tilgangsrettigheter?
  • Teknisk arbeidsflytrisiko Analyserer du og bruker den innkommende forespørselen som du burde? Eller håndterer du vellykkede svar og feil riktig?
  • Risiko for virksomhetslogikk Følg du alle forretningslogikkreglene som søknaden din har?
  • Integreringsrisiko Leser du den innkommende forespørselsstrukturen riktig? Eller lagrer du ordren korrekt i databasen?

For å bekrefte at den serverløse funksjonen din fungerer korrekt, må du teste alle disse risikoene.

Du kan teste hver av disse som du gjorde for integrasjonstestene. Men å konfigurere og konfigurere tjenesten hver gang du vil teste for en av disse risikoene er ikke optimalt. Som min venn Aleksandar Simovic elsker å si:

Tenk om testing av biler ble gjort på den måten. Det ville bety at hver gang du ville teste en enkelt skrue eller til og med et speil i en bil, måtte du sette sammen og deretter demontere hele bilen.

For å gjøre appen mer testbar er den klare løsningen å dele opp funksjonen din i flere mindre.

En av de gode måtene å gjøre dette på er å bruke Hexagonal Architecture på serverløse funksjoner.

Hexagonal Architecture, eller porter og adaptere, er en form for applikasjonsarkitektur som fremmer separasjon av bekymringer gjennom lag av ansvar. Som skaperen, Alistair Cockburn, forklarer:

Tillat at en applikasjon på samme måte blir drevet av brukere, programmer, automatiserte test- eller batch-skripter, og at den skal utvikles og testes isolert fra eventuelle kjøretidsenheter og databaser.

Så, hvordan gjelder det serverløse funksjoner?

Da Alex og teamet hans bruker AWS, endte de opp med en struktur som følgende:

  • Funksjonell virksomhetslogikk avslører få "porter" (eller forventer få argumenter). For eksempel en for en innkommende hendelse, en for permanent lagring og en for varsler.
  • De har to adaptere til arrangementet som utløser en funksjon, en for den virkelige AWS Lambda-triggeren og en annen for lokal testing.
  • De har flere adaptere for permanent lagring og varsler. For eksempel DynamoDB bordadapter og adapter i minnet.
Sekskantet arkitektur av AWS Lambda-funksjon

Alex og teamet hans var glade for at de gikk videre. Men før vi går videre, la oss se hvordan Hexagonal Architecture påvirker hvert nivå av testpyramiden.

Enhetstesting

Enhetstester forble den samme. Men det er lettere å skrive enhetstester på grunn av sekskantet arkitektur. De kan ganske enkelt bruke en lokal adapter eller mock som adapter for å teste funksjonsforretningslaget isolert.

Integrasjonstesting

Integrasjonstester hadde stor fordel av Hexagonal Architecture. De var i stand til å teste integrasjoner som de eier fullt ut. Tredjepartsintegrasjoner simuleres med andre adaptere.

Hvordan fungerer det i praksis?

Hver av deres serverløse funksjoner har lambda.js og main.js filer. Hovedfilen inneholder forretningslogikken til en serverløs funksjon. Og lambda.js-filen er ansvarlig for å koble til adapterne og påkalle main.js-filen.

Hovedfilen har egne enhets- og integrasjonstester. Men integrasjonstestene deres tester ikke full integrasjon med sluttjenester, for eksempel AWS S3, fordi det ville bremse dem. I stedet bruker de en adapter i minnet for å teste funksjonen med fillagringsintegrasjon.

AWS S3-integrasjon gjøres gjennom FileRepository, som har egne enhets- og integrasjonstester. Kontroller av integrasjonstester bruker AWS S3 for å være sikker på at sluttintegrasjonen faktisk fungerer.

I motsetning til main.js har ikke lambda.js-filen tester, fordi det for det meste bare har noen få kodelinjer.

Visuell representasjon av enkelt AWS Lambda-funksjon med tester

Denne tilnærmingen er som teknikken MindMup-teamet bruker for å teste serverløse funksjoner. Med den kan du enkelt teste integrasjoner av funksjonene dine, og fremdeles gjøre integrasjonstestene raskere.

GUI-testing

Siden Alex og teamet hans bygde en back end for appen, var ikke GUI-testnivået relevant. Men etter hvert som de lærte mer om serverløs, forsto de at de kunne bruke den til å forbedre GUI-testnivået for de andre appene de jobbet med.

UI-tester er dyre og trege, fordi de kjører i nettleseren. Men serverløs er billig, og det skaleres raskt.

Hvis de kunne kjøre en nettleser i AWS Lambda, ville de fått billig parallellisering. Det ville gjøre UI-testene deres billigere og raskere.

Men kan du kjøre en nettleser, for eksempel Chrome, i en serverløs funksjon?

Ja! Og det er enkelt ved hjelp av et verktøy som Serverless Chrome, Chromeless og Puppeteer.

Bruke AWS Lambda-funksjoner for parallellisering av UI-tester

En kombinasjon av serverløse og hodeløse nettlesere kan gi oss en ny generasjon UI-testverktøy. Vi kan allerede se og prøve noen av dem, for eksempel taksere.

CI / CD

Da Alex og teamet hans testet sin første serverløse funksjon, var det på tide å distribuere koden til testmiljøet. Det reiste et nytt spørsmål: hvordan kan de bruke CI / CD-verktøy for å distribuere den serverløse appen sin?

Svaret er enkelt: De kan bruke et CI-verktøy for å kjøre testene og distribuere appen. For å distribuere appen, bruk ethvert populært verktøy, for eksempel Claudia.js, AWS SAM og Serverless Framework.

Du kan fremdeles bruke ditt favoritt CI-verktøy (som Jenkins, TravisCI eller SemaphoreCI), eller hvis du vil holde fast ved AWS, kan du prøve AWS CodeBuild.

Manuell testing

Selv gjennom manuell testing blir ikke direkte påvirket av serverløs, fant teamet en måte å forbedre sin QA-prosess på.

Stadier og distribusjoner av serverløs app er billige og ofte raske å installere. Med serverløs betaler du heller ikke for appen hvis ingen bruker den.

Dette betyr at det aldri har vært billigere å ha et testmiljø!

Med serverløs kan du også ofte promotere funksjonen fra et trinn til et annet. Dette betyr at QA-teamet ditt kan teste en funksjon, og når de bekrefter at det fungerer, kan du markedsføre samme funksjon til produksjon.

Utover testing

Alex og teamet hans sendte sin første serverløse funksjon til forproduksjon, og teamet var glade for at de lærte seg å teste serverløse apper.

De fortsatte å bruke serverløst på prosjektet, og introduserte det for få andre prosjekter. Alex ble med vennene sine Anna og Jeff, som en tredje, noen ganger irriterende, serverløs forkynner. Og de levde lykkelig alle sine dager.

Serverløst forkynnere har fått et nytt medlem

Post-script

Men selv om appen deres var testet godt, skjedde det noe over natten.

Etter en undersøkelse fant de ut at en av integrasjonene endret seg. De lærte at testing er viktig for serverløse apper, men det er ikke nok.

Ettersom serverløse apper er veldig avhengige av integrasjoner, skifter risikoen fra koden din til integrasjonene. Og for å kunne fange integrasjonsendringer og reagere raskt, trenger appen din riktig overvåking.

Heldigvis finnes det flere og flere serverløse overvåkingsverktøy på markedet hver dag. Noen av de gode og populære alternativene er IOpipe, Thundra, Dashbird og Epsagon.

Men serverløse apper har ofte en tykk klient, noe som betyr at overvåkning på baksiden ikke er nok. Du trenger et lignende verktøy for frontend. Dette markedet har mange fine verktøy også, for eksempel Sentry og Rollbar.

Men i ånden av serverløs skapte vi en åpen kildekode-feilsporingsapp kalt Desole. Det er en serverløs app du kan installere i AWS-kontoen din. Det gjør det mulig for organisasjoner å spore applikasjons unntak og feil uten å måtte velge mellom bekvemmeligheten av software-as-a-service og sikkerheten til en løsning som er hostet. Du kan sjekke det her: https://desole.io.

Desole, åpen kildekode feilsporing, tett integrert med AWS
Alle illustrasjoner er laget med SimpleDiagrams4-appen.

Hvis du vil lære mer om å teste og bygge serverløse apper ved å bruke Node.js og AWS, sjekk ut “Serverless Applications with Node.js”, boken jeg skrev med Aleksandar Simovic for Manning Publications:

Boken vil lære deg mer om serverløs testing, med kodeeksempler, men du vil også lære å bygge og feilsøke en ekte verdens serverløs API (med DB og autentisering) ved hjelp av Node og Claudia.js. Og du lærer hvordan du bygger chatbots, for Facebook Messenger og SMS (ved hjelp av Twilio) og Alexa ferdigheter.