Automatisearre testen fan mikrotsjinsten yn Docker foar trochgeande yntegraasje

Yn projekten yn ferbân mei de ûntwikkeling fan microservice arsjitektuer, CI / CD beweecht fan de kategory fan in noflike kâns nei de kategory fan in driuwende needsaak. Automatisearre testen is in yntegraal ûnderdiel fan trochgeande yntegraasje, in foechhawwende oanpak dy't it team in protte noflike jûnen mei famylje en freonen kin jaan. Oars riskearret it projekt nea ôf te kommen.

It is mooglik om te dekken de hiele microservice koade mei ienheid tests mei mock foarwerpen, mar dit mar foar in part lost it probleem en lit in protte fragen en swierrichheden, benammen by it testen fan wurk mei gegevens. Lykas altyd binne de meast driuwende it testen fan gegevenskonsistinsje yn in relationele databank, testen fan wurk mei wolktsjinsten, en it meitsjen fan ferkearde oannames by it skriuwen fan mock-objekten.

Dit alles en in bytsje mear kinne wurde oplost troch de heule mikroservice te testen yn in Docker-kontener. In sûnder twifel foardiel foar it garandearjen fan de jildigens fan tests is dat deselde Docker-ôfbyldings dy't yn produksje geane wurde hifke.

Automatisearring fan dizze oanpak presintearret in oantal problemen, wêrfan de oplossing hjirûnder wurdt beskreaun:

  • konflikten fan parallelle taken yn deselde docker-host;
  • identifierkonflikten yn 'e databank by test-iteraasjes;
  • wachtsje op mikrotsjinsten om klear te wêzen;
  • gearfoegjen en útfieren fan logs nei eksterne systemen;
  • testen fan útgeande HTTP-oanfragen;
  • web socket testen (mei SignalR);
  • testen fan OAuth-ferifikaasje en autorisaasje.

Dit artikel is basearre op myn spraak by SECR 2019. Dus foar dyjingen dy't te lui binne om te lêzen, hjir is in opname fan de taspraak.

Automatisearre testen fan mikrotsjinsten yn Docker foar trochgeande yntegraasje

Yn dit artikel sil ik jo fertelle hoe't jo in skript brûke om de tsjinst ûnder test út te fieren, in database en Amazon AWS-tsjinsten yn Docker, dan testen op Postman en, nei't se binne foltôge, stopje en wiskje de makke konteners. Tests wurde útfierd elke kear as de koade feroaret. Op dizze manier soargje wy derfoar dat elke ferzje goed wurket mei de AWS-database en tsjinsten.

Itselde skript wurdt útfierd sawol troch de ûntwikkelders sels op har Windows-buroblêden en troch de Gitlab CI-tsjinner ûnder Linux.

Om te rjochtfeardigjen, soe it ynfieren fan nije tests de ynstallaasje fan ekstra ark net nedich wêze op 'e kompjûter fan' e ûntwikkelder of op 'e server wêr't de tests wurde útfierd op in commit. Docker lost dit probleem op.

De test moat rinne op in lokale server om de folgjende redenen:

  • It netwurk is nea folslein betrouber. Ut tûzen fersiken kin men mislearje;
    Yn dit gefal sil de automatyske test net wurkje, it wurk sil stopje, en jo moatte sykje nei de reden yn 'e logs;
  • Te faak oanfragen binne net tastien troch guon tsjinsten fan tredden.

Derneist is it net winsklik om de stand te brûken, om't:

  • In stand kin net allinnich brutsen wurde troch minne koade dy't derop rint, mar ek troch gegevens dy't de juste koade net ferwurkje kin;
  • Nettsjinsteande hoe hurd wy besykje alle feroarings werom te kearen makke troch de test tidens de test sels, der kin wat mis gean (oars, wêrom test?).

Oer it projekt en prosesorganisaasje

Us bedriuw ûntwikkele in mikroservice-webapplikaasje dy't rint yn Docker yn 'e Amazon AWS-wolk. Unit tests waarden al brûkt op it projekt, mar flaters faak barde dat de ienheid tests net ûntdekke. It wie nedich om in folsleine mikroservice te testen tegearre mei de database en Amazon-tsjinsten.

It projekt brûkt in standert trochgeande yntegraasjeproses, dat omfettet it testen fan de mikrotsjinst mei elke commit. Nei it tawizen fan in taak makket de ûntwikkelder wizigingen oan 'e mikrotsjinst, testet it mei de hân en rint alle beskikbere automatisearre tests út. As it nedich is, feroaret de ûntwikkelder de tests. As der gjin problemen wurde fûn, wurdt in commit makke foar de tûke fan dit probleem. Nei elke commit wurde tests automatysk op 'e tsjinner útfierd. It gearfoegjen yn in mienskiplike tûke en it lansearjen fan automatyske tests derop bart nei in suksesfolle resinsje. As de tests op 'e dielde tûke passe, wurdt de tsjinst automatysk bywurke yn' e testomjouwing op Amazon Elastic Container Service (bank). De stand is nedich foar alle ûntwikkelders en testers, en it is net oan te rieden om it te brekken. Testers yn dizze omjouwing kontrolearje in reparaasje as in nije funksje troch hânmjittich testen út te fieren.

Projekt arsjitektuer

Automatisearre testen fan mikrotsjinsten yn Docker foar trochgeande yntegraasje

De applikaasje bestiet út mear as tsien tsjinsten. Guon fan harren binne skreaun yn .NET Core en guon yn NodeJs. Elke tsjinst rint yn in Docker-kontener yn 'e Amazon Elastic Container Service. Elk hat in eigen Postgres-database, en guon hawwe ek Redis. D'r binne gjin mienskiplike databases. As ferskate tsjinsten deselde gegevens nedich binne, dan wurde dizze gegevens, as se feroaret, oerdroegen oan elk fan dizze tsjinsten fia SNS (Simple Notification Service) en SQS (Amazon Simple Queue Service), en de tsjinsten bewarje it yn har eigen aparte databases.

SQS en SNS

SQS lit jo berjochten yn in wachtrige pleatse en berjochten fan 'e wachtrige lêze mei it HTTPS-protokol.

As ferskate tsjinsten ien wachtrige lêze, dan komt elk berjocht mar nei ien fan har. Dit is handich by it útfieren fan ferskate eksimplaren fan deselde tsjinst om de lading tusken har te ferdielen.

As jo ​​​​wolle dat elk berjocht wurdt levere oan meardere tsjinsten, moat elke ûntfanger in eigen wachtrige hawwe, en SNS is nedich om berjochten yn meardere wachtrigen te duplikearjen.

Yn SNS meitsje jo in ûnderwerp en abonnearje jo dêrop, bygelyks in SQS-wachtrige. Jo kinne berjochten stjoere nei it ûnderwerp. Yn dit gefal wurdt it berjocht stjoerd nei elke wachtrige dy't ynskreaun is op dit ûnderwerp. SNS hat gjin metoade foar it lêzen fan berjochten. As jo ​​by it debuggen of testen moatte útfine wat nei SNS stjoerd wurdt, kinne jo in SQS-wachtrige oanmeitsje, it abonnearje op it winske ûnderwerp en de wachtrige lêze.

Automatisearre testen fan mikrotsjinsten yn Docker foar trochgeande yntegraasje

API Gateway

De measte tsjinsten binne net direkt tagonklik fan it ynternet. Tagong is fia API Gateway, dy't tagongsrjochten kontrolearret. Dit is ek ús tsjinst, en d'r binne ek tests foar.

Real-time notifikaasjes

De applikaasje brûkt SignalRom real-time notifikaasjes oan de brûker te sjen. Dit wurdt ymplementearre yn 'e notifikaasjetsjinst. It is direkt tagonklik fan it ynternet en wurket sels mei OAuth, om't it ûnpraktysk bliek te wêzen om stipe foar Web-sockets yn Gateway te bouwen, yn ferliking mei it yntegrearjen fan OAuth en de notifikaasjetsjinst.

Bekende testbenadering

Ienheidstests ferfange dingen lykas de databank mei mock-objekten. As in mikrotsjinst, bygelyks, besiket in rekord te meitsjen yn in tabel mei in frjemde kaai, en it record ferwiisd troch dy kaai bestiet net, dan kin it fersyk net útfierd wurde. Ienheidstests kinne dit net ûntdekke.

В artikel fan Microsoft It wurdt foarsteld om in databank yn it ûnthâld te brûken en mock-objekten út te fieren.

In-memory-database is ien fan 'e DBMS's dy't stipe wurde troch it Entity Framework. It is spesjaal makke foar testen. Gegevens yn sa'n databank wurde allinich bewarre oant it proses dat it brûkt wurdt beëinige. It fereasket gjin oanmeitsjen fan tabellen en kontrolearret de yntegriteit fan gegevens net.

Mock-objekten modellearje de klasse dy't se ferfange allinich foar safier't de testûntwikkelder begrypt hoe't it wurket.

Hoe kinne jo Postgres krije om migraasjes automatysk te begjinnen en út te fieren as jo in test útfiere, is net spesifisearre yn it Microsoft-artikel. Myn oplossing docht dit en foegje boppedat gjin koade ta spesifyk foar tests oan de mikrotsjinst sels.

Litte wy nei de oplossing gean

Tidens it ûntwikkelingsproses waard dúdlik dat ienheidstests net genôch wiene om alle problemen op 'e tiid te finen, dus waard besletten om dit probleem út in oare hoeke te benaderjen.

It opsetten fan in testomjouwing

De earste taak is it ynsetten fan in testomjouwing. Stappen nedich om in mikrotsjinst út te fieren:

  • Konfigurearje de tsjinst ûnder test foar de lokale omjouwing, spesifisearje de details foar ferbining mei de databank en AWS yn 'e omjouwingsfariabelen;
  • Start Postgres en fier de migraasje út troch Liquibase út te fieren.
    Yn relationele DBMS's, foardat jo gegevens yn 'e databank skriuwe, moatte jo in gegevensskema oanmeitsje, mei oare wurden, tabellen. By it bywurkjen fan in applikaasje moatte tabellen wurde brocht nei it formulier dat brûkt wurdt troch de nije ferzje, en, leafst, sûnder gegevens te ferliezen. Dit wurdt migraasje neamd. It meitsjen fan tabellen yn in ynearsten lege databank is in spesjaal gefal fan migraasje. Migraasje kin yn 'e applikaasje sels ynboud wurde. Sawol .NET as NodeJS hawwe migraasjekaders. Yn ús gefal, om feiligens redenen, mikrotsjinsten wurde ûntnommen fan it rjocht om it gegevensskema te feroarjen, en de migraasje wurdt útfierd mei Liquibase.
  • Starte Amazon LocalStack. Dit is in ymplemintaasje fan AWS-tsjinsten om thús te rinnen. D'r is in klearmakke ôfbylding foar LocalStack op Docker Hub.
  • Run it skript om de nedige entiteiten yn LocalStack te meitsjen. Shell-skripts brûke de AWS CLI.

Wurdt brûkt foar testen op it projekt Postrinner. It bestie earder, mar it waard mei de hân lansearre en testte in applikaasje dy't al ynset wie op 'e stand. Dit ark lit jo willekeurige HTTP(S)-oanfragen meitsje en kontrolearje oft de antwurden oerienkomme mei ferwachtingen. Queries wurde kombinearre yn in kolleksje, en de hiele kolleksje kin útfierd wurde.

Automatisearre testen fan mikrotsjinsten yn Docker foar trochgeande yntegraasje

Hoe wurket de automatyske test?

Tidens de test wurket alles yn Docker: de tsjinst ûnder test, Postgres, it migraasje-ark, en Postman, of leaver syn konsoleferzje - Newman.

Docker lost in oantal problemen op:

  • Unôfhinklikens fan hostkonfiguraasje;
  • Ofhinklikens ynstallearje: Docker downloadt ôfbyldings fan Docker Hub;
  • It systeem werombringe nei syn oarspronklike steat: gewoan de konteners fuortsmite.

Docker-komponearje ferbynt konteners yn in firtueel netwurk, isolearre fan it ynternet, wêryn konteners inoar fine troch domeinnammen.

De test wurdt regele troch in shell skript. Om de test op Windows út te fieren brûke wy git-bash. Sa is ien skript genôch foar sawol Windows as Linux. Git en Docker wurde ynstalleare troch alle ûntwikkelders op it projekt. By it ynstallearjen fan Git op Windows, is git-bash ynstalleare, dus elkenien hat dat ek.

It skript fiert de folgjende stappen:

  • Bouwe docker-ôfbyldings
    docker-compose build
  • It starten fan de database en LocalStack
    docker-compose up -d <контейнер>
  • Databankmigraasje en tarieding fan LocalStack
    docker-compose run <контейнер>
  • Starting fan de tsjinst ûnder test
    docker-compose up -d <сервис>
  • De test útfiere (Newman)
  • Stopje alle konteners
    docker-compose down
  • Resultaten pleatse yn Slack
    Wy hawwe in petear wêr't berjochten mei in griene vinkje of in read krús en in keppeling nei it log gean.

De folgjende Docker-ôfbyldings binne belutsen by dizze stappen:

  • De tsjinst dy't wurdt hifke is itselde byld as foar produksje. De konfiguraasje foar de test is fia omjouwingsfariabelen.
  • Foar Postgres, Redis en LocalStack wurde klearmakke ôfbyldings fan Docker Hub brûkt. Der binne ek klearmakke ôfbyldings foar Liquibase en Newman. Wy bouwe ús op har skelet, en foegje dêr ús bestannen ta.
  • Om LocalStack ta te rieden, brûke jo in klearmakke AWS CLI-ôfbylding en meitsje in ôfbylding mei dêrop in skript basearre.

Mei help fan voluminten, jo hoege net in Docker-ôfbylding te bouwen allinich om bestannen ta te foegjen oan 'e kontener. Folumes binne lykwols net geskikt foar ús omjouwing, om't Gitlab CI-taken sels yn konteners rinne. Jo kinne Docker kontrolearje fan sa'n kontener, mar folumes mount allinich mappen fan it hostsysteem, en net fan in oare kontener.

Problemen dy't jo miskien tsjinkomme

Wachtsje op reewilligens

As in kontener mei in tsjinst rint, betsjut dit net dat it ree is om ferbiningen te akseptearjen. Jo moatte wachtsje oant de ferbining trochgiet.

Dit probleem wurdt soms oplost mei in skript wait-for-it.sh, dy't wachtet op in kâns om in TCP-ferbining te meitsjen. LocalStack kin lykwols in 502 Bad Gateway-flater smite. Boppedat, it bestiet út in protte tsjinsten, en as ien fan harren is klear, dit seit neat oer de oaren.

beslút: LocalStack foarsjenningsskripts dy't wachtsje op in 200 antwurd fan sawol SQS as SNS.

Parallelle taakkonflikten

Meardere tests kinne tagelyk rinne op deselde Docker-host, dus kontener- en netwurknammen moatte unyk wêze. Boppedat kinne tests fan ferskate tûken fan deselde tsjinst ek tagelyk rinne, dus it is net genôch om har nammen yn elk komponistriem te skriuwen.

beslút: It skript stelt de COMPOSE_PROJECT_NAME fariabele yn op in unike wearde.

Windows Features

D'r binne in oantal dingen dy't ik wol oanjaan by it brûken fan Docker op Windows, om't dizze ûnderfiningen wichtich binne om te begripen wêrom't flaters foarkomme.

  1. Shell-skripts yn in kontener moatte Linux-line-einings hawwe.
    It shell CR-symboal is in syntaksisflater. It is lestich te sizzen út it flaterberjocht dat dit it gefal is. By it bewurkjen fan sokke skripts op Windows hawwe jo in goede tekstbewurker nedich. Derneist moat it ferzjekontrôlesysteem goed konfigureare wurde.

Dit is hoe't git is konfigureare:

git config core.autocrlf input

  1. Git-bash emulearret standert Linux-mappen en, by it roppen fan in exe-bestân (ynklusyf docker.exe), ferfangt absolute Linux-paden mei Windows-paden. Dit makket lykwols gjin sin foar paden dy't net op 'e lokale masine (of paden yn in kontener) binne. Dit gedrach kin net útskeakele wurde.

beslút: foegje in ekstra slash ta oan it begjin fan it paad: //bin ynstee fan /bin. Linux begrypt sokke paden; dêrfoar binne ferskate slashes itselde as ien. Mar git-bash herkent sokke paden net en besiket se net te konvertearjen.

Log útfier

By it útfieren fan tests wol ik logs sjen fan sawol Newman as de tsjinst dy't wurdt hifke. Sûnt de barrens fan dizze logs binne mei-inoar ferbûn, is it kombinearjen yn ien konsole folle handiger as twa aparte bestannen. Newman lansearret fia docker-compose run, en sa einiget syn útfier yn 'e konsole. It bliuwt allinich om te soargjen dat de útfier fan 'e tsjinst dêr ek giet.

De oarspronklike oplossing wie te dwaan Docker-komposearje gjin flagge -d, mar mei help fan de shell-mooglikheden, stjoer dit proses nei de eftergrûn:

docker-compose up <service> &

Dit wurke oant it nedich wie om logs fan Docker nei in tsjinst fan tredden te stjoeren. Docker-komposearje stoppe mei it útfieren fan logs nei de konsole. It team wurke lykwols docker taheakke.

beslút:

docker attach --no-stdin ${COMPOSE_PROJECT_NAME}_<сервис>_1 &

Identifikaasjekonflikt tidens test-iteraasjes

Tests wurde útfierd yn ferskate iteraasjes. De databank is net wiske. Records yn 'e databank hawwe unike ID's. As wy spesifike ID's yn oanfragen opskriuwe, krije wy in konflikt by de twadde iteraasje.

Om it te foarkommen, moatte de ID's unyk wêze, of moatte alle objekten makke troch de test wurde wiske. Guon objekten kinne net wiske wurde fanwege easken.

beslút: generearje GUID's mei Postman-skripts.

var uuid = require('uuid');
var myid = uuid.v4();
pm.environment.set('myUUID', myid);

Brûk dan it symboal yn 'e query {{myUUID}}, dy't ferfongen wurde mei de wearde fan 'e fariabele.

Gearwurking fia LocalStack

As de teste tsjinst lêst of skriuwt nei in SQS-wachtrige, dan moat de test sels ek wurkje mei dizze wachtrige om dit te ferifiearjen.

beslút: fersiken fan Postman nei LocalStack.

De AWS tsjinsten API is dokumintearre, wêrtroch fragen kinne wurde makke sûnder in SDK.

As in tsjinst nei in wachtrige skriuwt, dan lêze wy it en kontrolearje de ynhâld fan it berjocht.

As de tsjinst berjochten nei SNS stjoert, makket LocalStack yn 'e tariedingstadium ek in wachtrige en abonnearret op dit SNS-ûnderwerp. Dan komt it allegear del op wat hjirboppe beskreaun is.

As de tsjinst in berjocht fan 'e wachtrige moat lêze, dan skriuwe wy yn' e foarige teststap dit berjocht nei de wachtrige.

Testen fan HTTP-oanfragen dy't komme fan 'e mikrotsjinst ûnder test

Guon tsjinsten wurkje oer HTTP mei wat oars as AWS, en guon AWS-funksjes wurde net ymplementearre yn LocalStack.

beslút: yn dizze gefallen kin it helpe MockServer, dat hat in ready-made ôfbylding yn Docker hub. Ferwachte oanfragen en antwurden op har wurde konfigureare troch in HTTP-fersyk. De API is dokumintearre, dus wy meitsje oanfragen fan Postman.

Testen fan OAuth-ferifikaasje en autorisaasje

Wy brûke OAuth en JSON Web Tokens (JWT). De test fereasket in OAuth-provider dy't wy lokaal kinne útfiere.

Alle ynteraksje tusken de tsjinst en de OAuth-provider komt del op twa oanfragen: earst wurdt de konfiguraasje oanfrege /.bekend/openid-konfiguraasje, en dan wurdt de iepenbiere kaai (JWKS) frege op it adres fan 'e konfiguraasje. Dit alles is statyske ynhâld.

beslút: Us test OAuth-provider is in statyske ynhâldserver en twa bestannen derop. It token wurdt ien kear generearre en ynset foar Git.

Funksjes fan SignalR testen

Postman wurket net mei websockets. In spesjaal ark is makke om SignalR te testen.

In SignalR-kliïnt kin mear wêze dan allinich in browser. Der is in client bibleteek foar it ûnder .NET Core. De kliïnt, skreaun yn .NET Core, makket in ferbining, wurdt authentisearre en wachtet op in spesifike folchoarder fan berjochten. As in ûnferwacht berjocht ûntfongen is of de ferbining is ferlern, giet de kliïnt út mei in koade fan 1. As it lêste ferwachte berjocht ûntfongen is, giet de kliïnt út mei in koade fan 0.

Newman wurket tagelyk mei de klant. Ferskate kliïnten wurde lansearre om te kontrolearjen dat berjochten wurde levere oan elkenien dy't se nedich hat.

Automatisearre testen fan mikrotsjinsten yn Docker foar trochgeande yntegraasje

Brûk de opsje om meardere kliïnten út te fieren --skaal op de docker-compose kommandorigel.

Foardat it útfiert, wachtet it Postman-skript op alle kliïnten om ferbiningen te meitsjen.
Wy hawwe al tsjinkaam it probleem fan wachtsjen op in ferbining. Mar d'r wiene tsjinners, en hjir is de kliïnt. In oare oanpak is nedich.

beslút: de kliïnt yn 'e kontener brûkt it meganisme Sûnens Tsjekom it skript op 'e host te ynformearjen oer syn status. De kliïnt makket in bestân op in spesifyk paad, sis mar /healthcheck, sa gau as de ferbining is oprjochte. It HealthCheck-skript yn it docker-bestân sjocht der sa út:

HEALTHCHECK --interval=3s CMD if [ ! -e /healthcheck ]; then false; fi

team docker ynspektearje Toant de normale status, sûnensstatus en útgongskoade foar de kontener.

Neidat Newman foltôge, kontrolearret it skript dat alle konteners mei de kliïnt binne beëinige, mei koade 0.

Happinnes bestiet

Neidat wy de hjirboppe beskreaune swierrichheden oerwûn hawwe, hiene wy ​​in set stabile rinnende tests. Yn tests wurket elke tsjinst as ien ienheid, ynteraksje mei de database en Amazon LocalStack.

Dizze tests beskermje in team fan 30+ ûntwikkelders tsjin flaters yn in applikaasje mei komplekse ynteraksje fan 10+ mikrotsjinsten mei faak ynset.

Boarne: www.habr.com

Add a comment