Cos'è il test di concorrenza nei test del software?
⚡ Riepilogo intelligente
I test di concorrenza rilevano i difetti che si manifestano solo quando più utenti agiscono contemporaneamente sulla stessa applicazione, mettendo in luce deadlock, aggiornamenti persi e problemi di blocco che i controlli funzionali sequenziali non rivelano mai.
Cos'è il test di concorrenza?
Test di concorrenza È una tecnica di test utilizzata per rilevare difetti in un'applicazione quando più utenti sono connessi contemporaneamente. In altre parole, monitora l'effetto dell'esecuzione simultanea della stessa azione da parte di più utenti.
Il test di concorrenza è anche chiamato test multiutenteTestare un programma concorrente è più complesso che testare un programma sequenziale, a causa del non determinismo e dei problemi di sincronizzazione: lo stesso test può avere successo in un'esecuzione e fallire nella successiva senza che sia stata modificata una sola riga di codice.
Il diagramma seguente illustra il concetto: più utenti accedono alla stessa risorsa dell'applicazione nello stesso istante e il test osserva come l'applicazione gestisce la sovrapposizione.
Perché i test di concorrenza
Due domande giustificano lo sforzo, ed entrambe risultano invisibili durante le esecuzioni funzionali a utente singolo.
- Consente di identificare gli effetti dell'accesso simultaneo agli stessi record del database, moduli o codice applicativo.
- Identifica e misura il livello di deadlock, di blocco, di utilizzo di codice a thread singolo e di accesso limitato alle risorse condivise.
Una funzionalità può essere perfettamente corretta per un utente e comunque perdere dati per il secondo utente che arriva un millisecondo dopo, motivo per cui questa tecnica si affianca test delle prestazioni piuttosto che all'interno dei test funzionali.
Come eseguire test di concorrenza
Il test di concorrenza segue una sequenza ripetibile. I passaggi seguenti vanno da scoping alla risoluzione.
- Passaggio 1) Identificare i flussi soggetti a concorrenza. Verifica la presenza di stati condivisi: accessi simultanei, prenotazioni di posti o azioni, aggiornamenti del saldo, processi batch che scrivono sulla stessa tabella e qualsiasi componente a thread singolo nel percorso.
- Passaggio 2) Impostare un obiettivo di concorrenza. Decidete quanti utenti devono agire contemporaneamente, basandovi sui picchi di utilizzo reali anziché su un numero tondo.
- Fase 3) Progettare i casi di test. Ogni caso di prova associa la risorsa condivisa, le azioni concorrenti e lo stato finale previsto; ad esempio, due sessioni di prelievo dallo stesso conto non devono entrambe avere successo.
- Passaggio 4) Scrivere lo script e selezionare lo strumento. È necessario un generatore di carico che crei utenti virtuali configurabili; JMeter è la scelta open-source più comune e le sue impostazioni dei gruppi di thread si adattano direttamente agli scenari di concorrenza.
- Passo 5) Ramp in modo incrementale. Aumentare gli utenti simultanei gradualmente invece di saltareping al bersaglio, in modo che il livello al quale inizia la contesa sia visibile.
- Fase 6) Monitorare e analizzare. Monitorando contemporaneamente i tempi di attesa dei blocchi, la variabilità dei tempi di risposta, i tassi di errore e i blocchi del database, un difetto di concorrenza si manifesta spesso come un'anomalia temporale prima ancora di presentarsi come un errore.
- Passaggio 7) Risolvi e riavvia. Risolvi il problema di sincronizzazione, indicizzazione o blocco, quindi ripeti la stessa esecuzione per confermare che il comportamento sia cambiato e non si sia spostato.
Difetti comuni di concorrenza
I difetti di concorrenza rientrano in un numero limitato di classi riconoscibili e, di solito, identificare correttamente la classe porta direttamente alla soluzione.
| Difetto | Che succede | Sintomo tipico |
| Condizioni di gara | Il risultato dipende da quale sessione è terminata per prima | Totale corretto in alcune partite, sbagliato in altre. |
| Deadlock | Due sessioni, ciascuna delle quali tiene un lucchetto, l'altra ne ha bisogno | Le transazioni si bloccano invece di restituire un errore. |
| Aggiornamento perso | Una seconda scrittura sovrascrive la prima senza leggerla | Una modifica salvata scompare silenziosamente |
| Corruzione dei dati | Una struttura condivisa è scritta solo parzialmente | Record in uno stato in cui nessuna transazione valida potrebbe essere creata |
| Fame | Una sessione non ottiene mai la risorsa che sta aspettando | Un singolo percorso utente va in timeout mentre il sistema sembra funzionare correttamente. |
Poiché questi guasti sono intermittenti, ogni esecuzione necessita di registri e timestamp acquisiti; altrimenti il difetto non può essere segnalato in modo credibile attraverso il processo di gestione dei difetti.
Esempio di test di concorrenza
Consideriamo un negozio online che detiene l'ultima unità di un prodotto in magazzino. Due acquirenti aprono l'articolo nello stesso secondo ed entrambi premono Acquista.
- Scenario: Due sessioni leggono stock = 1, entrambe superano il controllo di disponibilità ed entrambe scrivono stock = 0.
- Risultato atteso: Un ordine viene confermato, l'altro riceve un messaggio di esaurimento scorte e le scorte non diventano mai negative.
- Indicatore di difetto: Entrambi gli ordini vengono confermati, oppure il valore delle scorte si attesta a -1, il che dimostra che il controllo di disponibilità e il decremento non vengono eseguiti come un unico passaggio atomico.
- Varianti che vale la pena provare: Le stesse due sessioni di modifica di un record del profilo, due approvazioni della stessa richiesta e un processo batch che aggiorna la tabella mentre un utente salva.
Lo stesso schema si generalizza: trova una risorsa, due scrittori e nessuna garanzia di ordinamento. Esecuzione dello scenario durante test di sistema, prima che venga aggiunto il carico, mantiene la diagnosi pulita.
Vantaggi del test di concorrenza
- Riduce relativamente la quantità di lavoro necessaria per testare un'applicazione, limitando l'ambito delle interazioni simultanee a pochi componenti ampiamente utilizzati e ben testati.
- L'incapsulamento consente di analizzare il comportamento di una porzione di un programma senza dover esaminare l'intero codice sorgente.
- Contribuisce a migliorare l'affidabilità e la robustezza dei programmi concorrenti.
- Questo sistema individua tempestivamente i limiti di blocco e di congestione, consentendo così di basare le decisioni relative alla capacità su dati di contesa misurati anziché su stime.
Svantaggi del test di concorrenza
Gli svantaggi elencati di seguito sono quelli che i tester riscontrano tipicamente durante l'esecuzione di test di concorrenza.
- L'applicazione deve essere testata su più piattaforme.
- Gli scenari di concorrenza richiedono test più intensivi rispetto a quelli sequenziali.
- Le funzioni non restituiscono immediatamente il risultato al chiamante; il risultato può essere fornito in un secondo momento tramite notifiche, blocchi, funzioni di callback o meccanismi simili, il che rende i test più complessi.
- Le informazioni o il flusso del programma non si riflettono nello stack di chiamate.
- Il numero di percorsi di esecuzione nel sistema può essere estremamente elevato, poiché i processi in un sistema concorrente interagiscono tra loro durante l'esecuzione.
- I programmi concorrenti presentano un tasso di fallimento più elevato rispetto a quelli sequenziali.
- Eseguire il debug di programmi concorrenti è difficile, perché collegare un debugger modifica la tempistica che ha causato l'errore.

