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
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
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.
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
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.
В
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
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
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
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.
- 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
- 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
Testen fan OAuth-ferifikaasje en autorisaasje
Wy brûke OAuth en
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.
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
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