Costruire Suite di Test Efficaci per Microservizi
Uno studio di caso su test funzionali e di carico per sistemi a microservizi.
― 10 leggere min
Indice
I Microservizi sono un modo super popolare per costruire sistemi che girano nel cloud. In un setup di microservizi, ogni parte del sistema funziona da sola, il che rende più facile aggiornare o aggiungere funzionalità. Ogni microservizio è responsabile di un compito specifico legato alle necessità dell'organizzazione. Questo approccio aiuta a gestire le parti del sistema separatamente e permette loro di crescere quando serve.
Quando crei un microservizio, non devi dipendere da tecnologie specifiche, il che significa che puoi usare strumenti e piattaforme diverse. Tuttavia, questi servizi sono creati e mantenuti da team diversi, anche se gli utenti vedono tutto come un unico prodotto completo.
È fondamentale che l'intero sistema funzioni bene insieme, anche se le sue parti sono separate. Man mano che i sistemi diventano più complessi, specialmente quando sono costruiti da team diversi, diventa difficile assicurarsi che ogni parte sia coperta da test. Solo quando ogni funzione è testata possiamo essere certi che il sistema risponde correttamente sia a input buoni che cattivi.
Oltre a testare se ogni pezzo funziona correttamente, è anche importante vedere come il sistema gestisce molti utenti contemporaneamente. Questo si chiama test di carico e controlla come si comporta il sistema sotto stress. Questo tipo di test dovrebbe andare di pari passo con test funzionali che controllano quanto bene il sistema sta funzionando.
Abbiamo notato che la comunità che lavora sui microservizi manca di un set standard di test che possa essere usato per la ricerca e l'avanzamento in questo ambito. Per affrontare questa lacuna, abbiamo creato uno studio di caso per iniziare a sviluppare un tale set standard di test.
Il nostro obiettivo principale è fornire un dettagliato set di test per due sistemi di microservizi ampiamente usati. Ci stiamo concentrando particolarmente sui test funzionali, che verificano se il sistema si comporta correttamente, e sui test di carico, che esaminano quanto bene può gestire molti utenti e richieste contemporaneamente.
In questo articolo, presenteremo i nostri benchmark di test attraverso uno studio di caso e parleremo di alcune sfide che abbiamo affrontato lungo il cammino. Condivideremo anche pratiche utili che possono essere usate quando si testano questi sistemi. Abbiamo creato un set completo di test che copre le diverse parti di ogni sistema di microservizi. Questo set di test può aiutare i ricercatori a convalidare il loro lavoro nel testing dei microservizi.
Il resto di questo articolo è organizzato come segue: la sezione successiva fornisce informazioni di base sui microservizi e sugli strumenti utilizzati per il testing. La sezione successiva discute il nostro studio di caso e dopo di che presentiamo i benchmark. Infine, concludiamo l'articolo.
Background
Il test funzionale assicura che le diverse funzionalità di un sistema funzionino secondo le aspettative. I casi di test sono spesso progettati in base alle specifiche del sistema, dove ogni test corrisponde a un requisito o funzione specifica. Questo assicura che ogni parte del software operi in modo indipendente come previsto.
Quando testiamo i microservizi, trattiamo il sistema come una scatola nera. Questo significa che ci concentriamo su ciò che gli utenti vedono sui loro schermi senza preoccuparci di come sia tutto assemblato. Vari strumenti e framework aiutano nella scrittura degli script di testing. Ad esempio, il framework Selenium aiuta a testare le applicazioni web automatizzando i browser per simulare le interazioni degli utenti.
Il test di regressione funzionale è un altro aspetto chiave. Controlla se il sistema funziona ancora correttamente dopo che sono state apportate modifiche. Questo è cruciale per mantenere la qualità, poiché aiuta a catturare cambiamenti non intenzionali che potrebbero influenzare le prestazioni del sistema.
Un altro tipo importante di test è il test di carico. Questo testa come il sistema può gestire diversi livelli di richiesta. Il carico si riferisce al numero di utenti e richieste che il sistema deve gestire. Il test di carico evidenzia come il sistema si comporta sotto pressione e può rivelare debolezze o aree che necessitano miglioramenti.
Ci sono diversi modi per condurre test di carico, tra cui l'uso di utenti reali, driver di carico automatizzati o piattaforme specializzate per il testing. Analizzare come un sistema reagisce a carichi diversi può mostrare dove si possono fare miglioramenti, poiché alcuni problemi diventano evidenti solo sotto specifiche condizioni di carico.
Simile ai test funzionali, ci sono framework disponibili per aiutare ad automatizzare i test di carico. Ad esempio, Gatling può eseguire test di carico e generare report su come il sistema ha performato sotto pressione.
La Copertura dei Test è un'altra misura importante nel testing del software. Ci dice quanto del sistema è stato testato, mostrando quali parti sono state esercitate durante i test rispetto all'intero sistema.
Microservice System Benchmarks
Per dimostrare come funzionano i test funzionali e di carico per i microservizi, abbiamo scelto due sistemi ben noti che offrono una varietà di funzionalità per il nostro studio di caso. Il primo è Train-Ticket, un sistema di prenotazione di biglietti ferroviari costruito usando Java, e il secondo è eShopOnContainers, progettato per applicazioni di shopping online usando .NET.
Il sistema Train-Ticket è composto da 47 microservizi. L'architettura di Train-Ticket descrive come il front-end, il sistema di monitoraggio e vari servizi interagiscono tra loro. Comprendere questo setup aiuta a capire come ciascun microservizio sia connesso.
Ci sono diverse azioni degli utenti all'interno di Train-Ticket, come cercare un treno, prenotare un biglietto, aggiornare una prenotazione, pagare un biglietto, ritirarlo e entrare in una stazione. Le azioni degli admin coinvolgono la gestione degli ordini, dei percorsi, dei piani di viaggio e delle informazioni degli utenti.
Per il nostro studio di caso, abbiamo usato l'ultima versione di Train-Ticket disponibile. Questo sistema è stato sviluppato da un team universitario per servire come strumento di benchmarking per la prenotazione dei biglietti.
Il sistema eShopOnContainers è progettato come un'applicazione di riferimento per .NET Core. Divide il suo front-end tra un'app web tradizionale e un'applicazione a pagina singola. Questo sistema include vari casi d'uso per lo shopping online, come effettuare il login, aggiungere articoli al carrello, completare l'acquisto e rivedere ordini passati.
Nel nostro studio di caso, abbiamo utilizzato l'ultima versione di eShopOnContainers, che è anche supportata da una grande comunità che contribuisce al suo codice.
Case Study
L'obiettivo del nostro studio di caso è creare un set completo di test per tutti gli endpoint del sistema. Ci concentriamo sulla valutazione della reattività e funzionalità dei sistemi microservizi sotto stress.
Il test funzionale vede il sistema come una scatola nera e non considera come sia costruito internamente. Riflette l'esperienza dell'utente testando le interazioni dell'interfaccia utente per assicurarsi accuratezza e coerenza.
Il test di carico mira a identificare colli di bottiglia e problemi di prestazione all'interno del sistema. Controlla quanto bene i microservizi funzionano sotto diversi carichi, il che può influenzare notevolmente la soddisfazione dell'utente.
Durante i nostri test, abbiamo affrontato diverse sfide. Condivideremo le migliori pratiche e soluzioni a problemi comuni mentre presenteremo i nostri risultati.
Functional Regression Testing Case Study
Per garantire che il sistema di microservizi funzioni correttamente, abbiamo implementato un set di test automatizzati basati sul web utilizzando Selenium. Il nostro obiettivo era verificare che tutti i microservizi funzionassero come previsto su diversi browser.
Abbiamo creato manualmente un elenco dettagliato di tutte le potenziali azioni degli utenti all'interno dei microservizi e tracciato i nostri progressi nel completare questi test utilizzando un foglio di calcolo. Questo ci ha aiutato a rimanere organizzati e garantire una copertura completa dei test.
Inizialmente, abbiamo provato a usare Katalon Web Recorder per la creazione dei test ma ci siamo resi conto che produceva codice disordinato. Invece, abbiamo scritto i nostri script Selenium che potevano funzionare come test JUnit. All’inizio abbiamo usato il browser Chrome per il testing poiché ci permetteva di vedere come funzionava tutto e di fare debug facilmente.
Man mano che espandevamo i nostri test, siamo passati a utilizzare l'HTML Unit WebDriver, che non ha un'interfaccia grafica. Questo cambiamento ha accelerato il nostro processo di test. Abbiamo anche introdotto il framework TestNG per consentire l'esecuzione parallela dei test, il che ha notevolmente ridotto il tempo necessario per eseguirli.
Study Results
Attraverso i nostri test di regressione funzionale, ci siamo proposti di testare ogni possibile funzionalità utente all'interno dei sistemi. Abbiamo testato con successo 51 casi d'uso per il sistema Train-Ticket e 26 per eShopOnContainers.
Tuttavia, non siamo riusciti a testare completamente un caso d'uso relativo al servizio di consegna in Train-Ticket a causa di problemi di distribuzione. Tuttavia, i test che abbiamo effettuato hanno coperto tutti i casi d'uso lato client associati alla prenotazione dei biglietti.
Nel sistema eShopOnContainers, abbiamo eseguito test per varie azioni degli utenti, inclusi il login, la navigazione, l'aggiunta di articoli al carrello e il checkout. Abbiamo raggruppato casi d'uso simili per creare un processo di test più efficiente.
Load Testing
Per i test di carico, ci siamo concentrati su come diversi endpoint nei sistemi di microservizi rispondessero a vari carichi utente. L'obiettivo era fornire indicazioni su quanti utenti i sistemi potessero supportare contemporaneamente e identificare eventuali problemi che insorgevano sotto stress.
Abbiamo annotato le specifiche configurazioni hardware utilizzate per il testing e tenuto traccia delle prestazioni di ogni endpoint. Questo includeva dettagli sui microservizi coinvolti, i test corrispondenti e se erano adeguatamente coperti.
Abbiamo scritto tutti i test di carico manualmente, assicurando codice di test chiaro e focalizzato. Una delle sfide affrontate è stata gestire l'autenticazione degli utenti nei test. Abbiamo superato questo problema salvando i token di autenticazione nei nostri test per garantire accesso valido agli endpoint.
Per fornire input ai moduli utilizzati nelle richieste, abbiamo utilizzato due metodi principali: la funzione formparam per parametri semplici e RawFileBody per richieste più grandi, che ha aiutato a gestire i dati in modo più efficiente nei test.
Study Results
I risultati dei nostri test di carico hanno mostrato prestazioni variabili in base al carico utente. Ogni scenario di carico doveva essere testato accuratamente, in particolare sotto diverse condizioni server.
Nei nostri test per il sistema Train-Ticket, abbiamo identificato un totale di 240 endpoint. Tuttavia, solo 41 di questi avevano endpoint funzionali. I nostri test miravano a coprire adeguatamente tutti loro.
Per ogni caso d'uso, abbiamo misurato i tempi di risposta e annotato quanti richieste hanno superato gli 800 ms. Questa metrica ha aiutato a determinare quanto bene i sistemi performassero sotto specifici scenari di carico.
Analogamente, per il sistema eShopOnContainers, abbiamo monitorato le prestazioni in vari casi d'uso. Abbiamo osservato che il sistema poteva gestire bene carichi più leggeri, ma ha faticato quando il numero di utenti è aumentato significativamente.
Proposed Benchmark
Dal nostro studio di caso, abbiamo creato un benchmark di test per i sistemi di microservizi. Questo benchmark serve come modo per la comunità di capire come sistemi simili rispondono a diversi tipi di test e carico.
Il benchmark è essenziale per stabilire test ripetibili a cui altri possono fare riferimento. Può aiutare a confrontare le prestazioni di diversi sistemi nel tempo, fornendo indicazioni su come evolvono.
Ci siamo concentrati su carichi realistici durante i nostri test, partendo da 100 utenti fino a 5.000 utenti. Questo intervallo ha aiutato a creare una migliore comprensione del carico normale che i sistemi possono gestire.
Velocità e coerenza erano componenti chiave del nostro test. Abbiamo misurato ogni tempo di risposta e tenuto traccia di quelli che erano inferiori o superavano il nostro limite target. Abbiamo deciso che un sistema poteva gestire un carico dato finché meno del 20% delle richieste impiegava più di 800 ms.
Raggruppando i nostri test in base ai microservizi, abbiamo assicurato che ogni test includesse molte affermazioni riguardanti le prestazioni e la funzionalità del sistema. Il successo di un test dipendeva dal fatto che tutte le affermazioni passassero o fallissero nel loro insieme.
Una volta completati i nostri test, abbiamo condiviso i nostri risultati con la comunità per permettere ad altri di costruire sul nostro lavoro e ampliare le pratiche di testing per i sistemi di microservizi.
Le principali contribuzioni del nostro lavoro sono di due tipi. Prima di tutto, abbiamo fornito un esempio open-source di testing automatizzato per sistemi di microservizi. In secondo luogo, abbiamo sviluppato un robusto benchmark iniziale che altri possono usare per valutare sistemi simili in futuro.
Titolo: Benchmarks for End-to-End Microservices Testing
Estratto: Testing microservice systems involves a large amount of planning and problem-solving. The difficulty of testing microservice systems increases as the size and structure of such systems become more complex. To help the microservice community and simplify experiments with testing and traffic simulation, we created a test benchmark containing full functional testing coverage for two well-established open-source microservice systems. Through our benchmark design, we aimed to demonstrate ways to overcome certain challenges and find effective strategies when testing microservices. In addition, to demonstrate our benchmark use, we conducted a case study to identify the best approaches to take to validate a full coverage of tests using service-dependency graph discovery and business process discovery using tracing.
Autori: Sheldon Smith, Ethan Robinson, Timmy Frederiksen, Trae Stevens, Tomas Cerny, Miroslav Bures, Davide Taibi
Ultimo aggiornamento: 2023-06-09 00:00:00
Lingua: English
URL di origine: https://arxiv.org/abs/2306.05895
Fonte PDF: https://arxiv.org/pdf/2306.05895
Licenza: https://creativecommons.org/licenses/by/4.0/
Modifiche: Questa sintesi è stata creata con l'assistenza di AI e potrebbe presentare delle imprecisioni. Per informazioni accurate, consultare i documenti originali collegati qui.
Si ringrazia arxiv per l'utilizzo della sua interoperabilità ad accesso aperto.
Link di riferimento
- https://dl.acm.org/ccs.cfm
- https://www.scribbr.com/methodology/external-validity/#:~:text=There%20are%20seven%20threats%20to,aptitude%2Dtreatment%20and%20situation%20effect
- https://www.scribbr.com/methodology/internal-validity/#:~:text=What%20are%20threats%20to%20internal,mean%2C%20social%20interaction%20and%20attrition