Ce este testarea concurenței în testarea software-ului?
⚡ Rezumat inteligent
Testarea concurențială detectează defectele care apar doar atunci când mai mulți utilizatori acționează asupra aceleiași aplicații în același moment, expunând blocaje, actualizări pierdute și probleme de blocare pe care verificările funcționale secvențiale nu le dezvăluie niciodată.
Ce este testarea concurenței?
Testarea concurenței este o tehnică de testare utilizată pentru a detecta defectele într-o aplicație atunci când mai mulți utilizatori sunt conectați. Cu alte cuvinte, monitorizează efectul în timp ce mai mulți utilizatori efectuează aceeași acțiune în același timp.
Testarea concurenței este denumită și testare multi-utilizatorTestarea unui program concurent este mai dificilă decât testarea unui program secvențial, din cauza problemelor de nedeterminism și sincronizare: același test poate trece la o rulare și poate eșua la următoarea fără ca măcar o linie de cod să se modifice.
Diagrama de mai jos ilustrează ideea — mai mulți utilizatori ajung la aceeași resursă a aplicației în același moment, iar testul observă ce face aplicația cu suprapunerea.
De ce testarea concurenței
Două întrebări justifică efortul, ambele fiind invizibile pentru rulările funcționale cu un singur utilizator.
- Identifică efectele accesării acelorași înregistrări din baza de date, module sau cod de aplicație în același timp.
- Identifică și măsoară nivelul de interblocare, blocare, utilizarea codului cu un singur fir de execuție și accesul restricționat la resursele partajate.
O funcție poate fi complet corectă pentru un utilizator și totuși să piardă date pentru al doilea utilizator care sosește o milisecundă mai târziu, motiv pentru care această tehnică se potrivește alături de test de performanta mai degrabă decât în cadrul testării funcționale.
Cum se efectuează testarea concurenței
Testarea concurenței urmează o secvență repetabilă. Pașii de mai jos pornesc de la scoping la rezoluție.
- Pasul 1) Identificați fluxurile predispuse la concurență. Căutați stări partajate: conectări simultane, rezervări de locuri sau stocuri, actualizări de sold, joburi în lot care scriu același tabel și orice componentă cu un singur fir de execuție din cale.
- Pasul 2) Setați o țintă de concurență. Decideți câți utilizatori trebuie să acționeze în același timp, pornind de la vârfurile reale de utilizare, mai degrabă decât de la un număr rotund.
- Pasul 3) Proiectarea cazurilor de testare. Fiecare caz de testare combină resursa partajată, acțiunile concurente și starea finală așteptată - de exemplu, două sesiuni de retragere dintr-un cont nu trebuie să aibă succes ambele.
- Pasul 4) Scrieți scriptul și selectați instrumentul. Este necesar un generator de sarcină care generează utilizatori virtuali configurabili; JMeter este opțiunea comună open-source, iar setările sale pentru grupul de fire de execuție se potrivesc direct scenariilor de concurență.
- Pas 5) Ramp treptat. Creșterea numărului de utilizatori concurenți în etape, în loc de salturiping către țintă, astfel încât nivelul la care începe disputa să fie vizibil.
- Pasul 6) Monitorizare și analiză. Timpii de așteptare ai blocării supravegheate, răspândirea timpului de răspuns, ratele de eroare și blocarea bazei de date împreună - un defect de concurență apare adesea ca o anomalie de sincronizare înainte de a se manifesta ca o eroare.
- Pasul 7) Rezolvați și rulați din nou. Corectați cauza sincronizării, indexării sau blocării, apoi repetați aceeași rulare pentru a confirma că comportamentul s-a schimbat, nu a fost mutat.
Defecte comune de concurență
Defectele de concurență se încadrează într-un număr mic de clase recognoscibile, iar denumirea corectă a clasei indică de obicei direct către soluție.
| Defect | Ce se întâmplă | Simptomul tipic |
| Condiții de cursă | Rezultatul depinde de care sesiune s-a încheiat prima | Totaluri corecte la unele runde, greșite la altele |
| Impas | Două sesiuni dețin fiecare o blocare de care are nevoie cealaltă | Tranzacțiile se blochează în loc să returneze o eroare |
| Actualizare pierdută | O a doua scriere suprascrie prima fără a o citi | O modificare salvată dispare în mod silențios |
| Coruperea datelor | O structură partajată este scrisă doar parțial | Înregistrări într-o stare în care nicio tranzacție validă nu a putut fi creată |
| înfometare | O sesiune nu obține niciodată resursa pe care o așteaptă | O cale pentru un singur utilizator expiră în timp ce sistemul pare funcțional |
Deoarece aceste eșecuri sunt intermitente, fiecare rulare necesită capturarea jurnalelor și a marcajelor temporale; altfel, defectul nu poate fi semnalat în mod credibil prin intermediul procesul de management al defectelor.
Exemplu de testare concurențială
Să luăm în considerare un magazin online care deține ultima unitate a unui produs în stoc. Doi cumpărători deschid articolul în aceeași secundă și ambii apasă butonul Proprietăți.
- Scenariu: Două sesiuni citesc stoc = 1, ambele trec verificarea disponibilității și ambele scriu stoc = 0.
- Rezultat asteptat: O comandă este confirmată, cealaltă primește un mesaj de epuizare a stocului, iar stocul nu devine niciodată negativ.
- Indicator de defect: Ambele comenzi confirmă, sau stocul ajunge la -1, ceea ce arată că verificarea disponibilității și decrementarea nu sunt executate ca un singur pas atomic.
- Variații care merită rulate: Aceleași două sesiuni de editare a unei înregistrări de profil, două aprobări ale aceleiași solicitări și un job în lot care actualizează tabelul în timp ce un utilizator salvează.
Același model se generalizează: găsiți o resursă, doi scriitori și nicio garanție de comandă. Rularea scenariului în timpul testarea sistemului, înainte de adăugarea sarcinii, menține diagnosticul curat.
Avantajele testării concurenței
- Reduce relativ efortul necesar pentru testarea unei aplicații prin restricționarea domeniului de aplicare al interacțiunilor concurente la câteva componente utilizate pe scară largă și bine testate.
- Încapsularea permite analizarea comportamentului unei porțiuni a unui program fără a revizui întreaga bază de cod.
- Ajută la îmbunătățirea fiabilității și robusteții programelor concurente.
- Expune din timp limitele de blocare și blocare, astfel încât deciziile privind capacitatea se bazează pe măsurători ale concurenței, mai degrabă decât pe estimări.
Dezavantajele testării concurenței
Dezavantajele de mai jos sunt de obicei întâlnite de testeri atunci când efectuează teste de concurență.
- Aplicația trebuie testată pe mai multe platforme.
- Scenariile de concurență necesită teste mai intensive decât cele secvențiale.
- Funcțiile nu returnează rezultatul apelantului imediat; în schimb, rezultatul poate fi livrat ulterior prin notificări, blocuri, funcții de apel invers sau mecanisme similare, ceea ce face testarea mai dificilă.
- Fluxul de informații sau program nu este reflectat în stiva de apeluri.
- Numărul de căi de execuție în sistem poate fi extrem de mare, deoarece procesele dintr-un sistem concurent interacționează între ele în timp ce se execută.
- Programele concurente au o rată de eșec mai mare decât cele secvențiale.
- Depanarea programelor concurente este dificilă, deoarece atașarea unui depanator modifică momentul care a cauzat eșecul.

