Arhitectura bazată pe microservicii este în mare vogă în ultimii ani. Aceasta permite descentralizarea responsabilităţii unei aplicaţii monolit în microservicii cu responsabilitate specifică prin a căror orchestrare se obţine funcţionalitatea de business dorită. Microserviciile comunică printr-o API (Application Programming Interface), independentă de limbajul de programare, prin intermediul interogărilor REST (Representational State Transfer), folosind ca model de date JSON (Javascript Object Notation) sau XML (Extended Markup Language). Un avantaj al microserviciilor- care se construiesc pe standardul de comunicare HTTP, nu depind de limbajul de programare ales şi comunică prin API- este faptul că se pot implementa în paralel, în limbaje de programare diferite şi în spații fizice diferite. Ca metodologii de dezvoltare se pot alege cele de tipul agil cum ar fi SCRUM sau Kanban. Codul sursă poate fi versionat folosind unelte precum git sau Mercurial. API-urile pot fi generate folosind unelte cum ar fi openapi şi Swagger pe baza unor fișiere YAML (Yet Another Markup Language).
Testele de unitate funcţională se pot crea pentru fiecare microserviciu individual. Ele pot rula întâi local şi ulterior, după desfăşurarea aplicaţiei în cloud. Este de dorit ca testele de unitate funcţională să fie cât mai multe pentru a avea o acoperire cât mai mare cu teste ale codului sursă. Ele au avantajul că rulează repede, pot fi integrate într-un pipeline de livrare şi testare continuă, reușind să dea feedback rapid despre funcţionalitatea de business implementată. Un exemplu de unealtă pentru testele de unitate funcţională este Junit.
Testele pe componente sunt un nivel peste testele funcţionale şi testează componentele şi interacţiunile dintre componentele care formează un microserviciu. Aici pot fi folosite mockuri pentru a asigura funcţionalitatea unei componente. Un exemplu de unealtă este Mockito. Aceste teste asigură o testabilitate bună pentru că microserviciile sunt relativ mici. Defectele găsite sun locale fiecărui microserviciu.
Teste de integrare vin pe nivelul următor şi testează funcţionalitatea folosirii unei serii de servicii care deservesc împreună o funcţionalitate de business. O soluţie pentru acest tip de testare este o suită JUnit de teste cu apeluri către API-urile fiecărui microserviciu. Când se găsesc defecte ele pot fi şi din cauza interfeţelor.
Teste end to end urmăresc comportamentul aplicaţiei de la microservicii până la baza de date. O soluţie pentru baza de date este baza de date în memorie (ex. H2) pentru teste locale pentru viteza ei, iar în cloud o bază de date normală.
Testele de sistem se fac privind întreaga structură de microservicii împreună cu baza de date şi cu alte servicii externe ca un tot unitar. Defectele care pot fi găsite sunt observate după integrarea tuturor părţilor care compun aplicaţia şi pot da indicii despre integrarea defectuoasă cu servicii externe, incompatibilităţi în interfeţe, timpi de răspuns necorespunzători, supraîncărcarea memoriei, suprasolicitarea unor microservicii etc.
Testarea de acceptanţă este în principal manuală, fiind efectuată de experţii de domeniu după criteriile impuse la construirea aplicaţiei web sau mobile.
Pentru testarea automatizată există pipeline-uri care deservesc foarte bine necesităţile de testare enumerate mai sus, astfel încât să se realizeze testarea continuă. Prin aceasta, la fiecare desfăşurare a aplicaţiei, toate testele pot fi rulate. Feedbackul primit în urma lor poate fi încorporat în următoarea etapă de dezvoltare. O astfel de unealtă este Jenkins.
În cazul aplicaţiilor in cloud este necesară urmărirea şi controlul activităţii microserviciilor, valorificându-se soluţiile pentru logurile microserviciilor: Kibana. Aceasta poate urmări microserviciile în timp real, logurile generate pot fi inspectate pentru erori și excepţii, iar memoria consumată poate fi evaluată pentru o mai bună încărcare a microserviciilor şi o eventuală distribuţie optimizată a încărcării.
Pentru a asigura izolarea microserviciilor şi comunicarea între ele, se poate folosi o soluţie de containere, cum ar fi Docker. Aceasta abstractizează infrastructura la nivel de aplicaţie spre deosebire de aplicaţiile monolit care necesitau virtualizarea. De asemenea, Docker implică un consum mai mic de resurse de memorie şi spaţiu in cloud.
Kubernetes este soluţia de automatizare a desfăşurării microserviciilor, de scalare și gestionare a lor.
Pentru testarea încărcării sistemului de microservicii se poate folosi Gatling. Pentru această unealtă se pot specifica numărul de utilizatori simulaţi, intervalul de timp între interogări şi numărul de repetări. Testele se scriu în Scala.
O unealtă utilizată pentru revizuirea modificărilor codului sursă, foarte simplu de folosit este Bitbucket.
Pentru gestionarea documentaţiei testelor, a specificării cerinţelor, a urmăririi progresului în dezvoltare şi testare se poate folosi Confluence pentru că integrează JIRA și Xray.
Maven este o unealtă care uşurează rularea testelor pentru aplicaţia dezvoltată.
Pentru raportarea rezultatelor testelor rulate există Allure, ce poate fi folosită cu două pluginuri de maven (surefire și failsafe).
Un exemplu de test end to end este o suită de teste din care redau un fragment în Java folosind REST Assured si JUnit:
import static io.restassured.RestAssured.given;
@Test
public void app_test_007_upload_form(){
given()
.accept(„*/*”)
.cookie(„COOKIE”, generateCookie())
.queryParam(„account”,accountDTO.getId())
.multiPart(file)
.when()
.post( „https://my-domain.net/accounts”)
.then()
.statusCode(200);
}
de Mircea Vădan
de Ovidiu Mățan
de Diana Țelman