Det er nemt (for nogle eller de fleste af os) at blive begejstret for nye teknologier, og anvende dem uden at have afprøvet dem først eller overvejet om de passer til ens behov, til brugernes behov eller om de passer til forretningsfunktionaliteten. Vi bør evaluere hver eneste gang vi overvejer at bruge et nyt smart værktøj eller indføre en ny teknologi. Evaluering er en af de grundlæggende tekniske færdigheder, og alt efter hvad ens mål er, så ændrer denne evaluering karakter, alt efter om man overvejende hører til forretningen, softwarearkitekterne, DevOps etc.
Én måde at evaluere hvilke nye teknologier, man evt. kunne tage i brug, hedder “The Spine model”, hvor man i stedet for kun at diskutere hvilke nye tools man kunne tilføje (en diskussion der ofte tager udgangspunkt i personlige præferencer), så bør man diskutere projektets/organisationens behov ud for hvert niveau af pyramiden – hele vejen op fra bunden til toppen. Hør mere om dette emne i denne talk.
Vil microservices fx være et godt match for et nyt projekt, man skal i gang med? Der findes nok lige så mange artikler derude, der taler for, som der taler imod – alt efter hvad man googler efter. For at svare på spørgsmålet skal man først forstå de generelle arkitekturprincipper, der ligger bag microservices. Der er skrevet meget om hvilke faldgruber man skal passe på med mht. microservices, og selv rutinemæssige opgaver såsom testing kan se ud til at blive en kompleks opgave.
Jeg har i et projekt arbejdet på en microservice platform, og indtil videre har testdelen bestået af unit tests, manuelle tests (end-to-end tests), og automatiske integrationstests af kørende, eksisterende microservices ved at bruge Postman collections og Newman CLI kommandoer. Med Postman collections opretter og gemmer man testscenarier, som derefter køres via kommandolinjen. Men det kræver at hver enkelt microservice er færdigimplementeret og kører et sted hvor man kan nå den.
Service virtualisation
Det er her microservice virtualisation og API simulation kommer ind i billedet, som var emnet til søndagens sidste GOTO CPH foredrag med titlen “Effective Testing with API simulation and (micro)service virtualisation”
Dine automatiske tests skal som altid have en kort feedback loop, ingen gider vente særligt længe på at en test kører igennem. Men hvis man skal teste et distribueret softwaresystem, hvor hvert API-kald, hvert kald til en microservice, tager tid – og der er mange microservices – så vil en end-to-end test eller en integrationstest tage forholdsvis lang tid… Ville det ikke være skønt med et testtool, der i stedet kan simulere forskellige services i ens testsetup, og lynhurtigt give et response tilbage for hver request?
Men at køre integrationstests, der tester al forretningsfunktionalitet – og som dermed kalder de forskellige microservices, kræver at samtlige microservices kører, at databaserne kører og at alle andre tredjeparts API’er er klar til test. Derudover kan det være svært at teste samtlige fejlscenarier i sådan et distribueret setup.
Service virtualisation kan gøre livet nemmere mht. tests af microservices. Tools som Hoverfly eller WireMock kan simulere andre services, således at man kun tester én komponent ad gangen. Men dette kræver til gengæld at nye opdateringer til kodebasen (for hver enkelt microservice) også bliver opdateret i stub’en. Hvordan sørger man for at overholde regler om hvilke API versioner man tester? Løsningen hedder Consumer-Driven Contract (CDC) testing.
Open source tool’et Hoverfly er en letvægts proxy, som kan bruges til at simulere microservices i ens testsetup. Først skal hele microservice setup’et op at køre, som hvis det var en ægte end-to-end test, hvorefter Hoverfly bliver startet op i en capture mode, hvor den opsnapper alle requests og responses imellem services. Alle interaktioner bliver altså opsamlet og gemt i Hoverfly.
I stedet for manuelle tests og i stedet for selv at implementere alle mocks eller stubs af de services, som den services der er under test, skal interagere med, så kan man på denne måde
- skrive og køre testcases op mod de ægte, kørende microservices og tredjeparts komponenter, hvorefter Hoverfly opsnapper og gemmer al kommunikation.
- Når alle tests kører uden fejl, så sættes man Hoverfly i simulation mode og kører alle tests igen, men denne gang er det Hoverfly der svarer tilbage på et request – og denne gang meget hurtigere end hvis det var den “rigtige” microservice – og vi ved at Hoverfly svarer tilbage med det korrekte request, som jo blev opsnappet i capture mode.
- For at teste mulige fejlscenarier, kan man indføre middleware til sit Hoverfly setup, hvor man fx kan ændre på responses eller svarkoder for et givent request for at teste negative testcases og uforudset opførsel af eksterne services, eller bruge middleware til at simulere en højere netværkslatency i et API-kald osv.
Hvad er dine erfaringer med microservice testing, fordele og ulemper i forhold til en mere traditionel tilgang?