ABONAMENTE VIDEO REDACȚIA
RO
EN
NOU
Numărul 150
Numărul 149 Numărul 148 Numărul 147 Numărul 146 Numărul 145 Numărul 144 Numărul 143 Numărul 142 Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 98
Abonament PDF

Abordări pentru testare End to End în sisteme de tip Pull

Alexandru Albu
Software Architect @ Bosch



TESTARE


Testarea e vitală în căutarea noastră de a lansa software performant și fără buguri. Pentru a îmbunătăți viteza de dezvoltare și a asigura un produs final de înaltă calitate, se depune un efort considerabil în crearea unui context unde acest software poate fi testat. Sistemele de tip pull sunt de obicei închise, având nivele reduse pentru Controlabilitate si Observabilitate, prin urmare calea spre îmbunătățirea Testabilității se face din mers.

Sistemul

În sistemele tradiționale (de tip push), clientul inițiază comunicarea prin lansarea unei cereri (request) către sistem. Sistemul procesează cererea și livrează un răspuns înapoi clientului.

Într-o arhitectură de tip pull, sistemul nu așteaptă să fie invocat, ci inițiază el însuși conversația prin solicitarea de sarcini de la client. După ce sarcinile sunt îndeplinite, rezultatul este livrat ca răspuns înspre client.

Abordarea de tip pull este regăsită în sistemele distribuite bazate pe evenimente sau cele proiectate să îndeplinească sarcini programate, spre exemplu procesări care durează foarte mult.

În astfel de sisteme, rolul tradițional de client (cel care inițiază comunicarea) este jucat de către sistem, iar beneficiarul rezultatului procesării este un alt sistem. Asemănător unui client tradițional, acest sistem "beneficiar" deține input data și așteaptă output data, iar de cele mai multe ori nu este mai mult decât un Data Source.

Sarcinile de procesare sunt efectuate de către componente numite workers. Ele primesc acces la datele ce trebuie procesate cu ajutorul componentelor agent, capabile să convertească nu doar date, ci și tipuri de comunicare (sincronă <-> asincronă). Progresul procesării este monitorizat de către componente tracker iar toată procesarea este inițiată de către componente trigger.

Acest tip de sistem este reprezentat mai jos, într-o diagramă de componente:

Următoarea diagramă de comunicare prezintă o perspectivă mai bună asupra comunicării între componente:

Problema

În principiu avem un sistem închis care a fost proiectat să nu accepte solicitări. La un moment dat, acest sistem trebuie testat.

Deși componentele sistemului pot fi testate în izolare (Unit, Integration), testele End to End pot interacționa doar cu Data Source. Se poate asigura că datele de intrare sunt disponibile și se verifică corectitudinea livrării datelor de ieșire (au conținutul așteptat și schimbul de mesaje a avut loc conform planului).

În stilul BDD, un astfel de scenariu poate arăta ca în următorul fragment:

Given valid <input> available in the Data Source
Given predefined <schedule>
When Data Source is checked
Then the system should have called for <input> according to <schedule>
Then the system should have delivered valid <output>

Execuția unui astfel de test are nevoie de o amplasare ca în următoarea diagramă:

Problema principală este că testele de mai sus pot fi executate doar după ce întregul sistem a fost deja dezvoltat. Dacă sistemul este dezvoltat într-o manieră Agile, se dorește a fi validat cât de timpuriu posibil.

O altă problemă este numărul limitat de variabile care compun scenariul de test (input, schedule, output). În teorie, întregul sistem poate fi testat cu un singur scenariu dacă variabilele sunt jucate corespunzător. Cu așa de puțin control Testabilitatea sistemului are de suferit. Este foarte greu de pus presiune pe sistem în așa fel încât caracteristicile sale invizibile, dar totuși puternice să fie declanșate. Aceste caracteristici sunt de obicei NFR-uri (cerințe non-funcționale), precum Toleranța la erori, Fiabilitatea, Rezistența/Elasticitatea și Robustețea.

Urmărim un mod de a îmbunătăți Testabilitatea și a face atât sistemul cât și dezvoltarea lui cât mai transparente către toate părțile implicate. Un proces transparent, chiar dacă are doar realizări mărunte, face proiectul mai ușor de urmărit din mai multe perspective: de management, aprecierea riscurilor și financiare.

Mai mult potențial pentru Testabilitate aduce mai multe oportunități și pentru membrii echipei. Acesta deschide noi moduri de a fi implicați în asigurarea calității proiectului pe care îl dezvoltă. Dintr-o perspectivă tehnică, acesta devine capabil să acomodeze tot mai multe tehnologii de ultimă oră și invită spre inovație.

Descompunerea problemei

Primele componente ce sunt dezvoltate sunt algoritmii de procesare. De obicei, aceștia pornesc ca programe prototip, pentru ca, ulterior, tot mai multe funcționalități sau componente de sprijin să fie adăugate în jurul lor.

Elementul central al acestui sistem constă în componentele (sau micro serviciile) worker. Are sens să le grupăm într-un subsistem și să ne asigurăm că funcționează în armonie cu toate dependențele lor de înlănțuire angajate.

Următorul pas ar fi să ne asigurăm că procesarea este monitorizată corespunzător, iar pentru aceasta adăugăm componentele (sau micro serviciile) tracker. Astfel formăm un alt subsistem.

Ultimul subsistem necesită includerea componentelor (sau micro serviciilor) trigger. Această descompunere în subsisteme este prezentată mai jos:

Subsistemul Workers

Din perspectiva BDD, acest sistem este cel mai simplu:

Având pregătite date de intrare predefinite și comandând procesarea pe canale specializate, subsistemul poate fi validat prin felul în care își cere datele de intrare, corectitudinea datelor de ieșire și înregistrarea evenimentelor ce sunt declanșate în timpul procesării.

Următorul fragment BDD ilustrează cum pot fi proiectate cazuri de test pentru acest subsistem:

Given <input> for when the subsystem calls on 
<input_req_ch> with <input_req_params>

When processing command is sent on <command_ch> with <command_params>

Then the <input_req_ch> should be called with 
<input_req_params> 

Then the <output_data_ch> should be called with 
<output>

Then the <log_events_ch> should be called with <events>

Subsistemul Trackers

Acest subsistem prezintă intrări similare cu subsistemul precedent, dar verifică efectele secundare la granițele subsistemelor tracker.

Următorul fragment BDD ilustrează cum pot fi proiectate cazuri de test pentru acest subsistem:

Given <input> for when the subsystem calls on 
<input_req_ch> with <input_req_params>

When processing command is sent on <command_ch> 
with <command_params>

Then the <input_req_ch> should be called 
with <input_req_params> 

Then the <output_data_ch> should be called 
with <output>

Then calling on <check_events_ch> 
with <check_events_params> should return <events>

Subsistemul Triggers

Ultimul subsistem include componentele de planificare, iar corectitudinea inițiativelor de pull poate fi validată aici, într-o configurare controlată.

Given <input> for when the subsystem calls on 
<input_req_ch> with <input_req_params>

When the subsystem is configured with <schedule>

Then the <input_req_ch> should be called with 
<input_req_params> according to <schedule>

Then the <output_data_ch> should be called 
with <output>

Soluțiile

Nu ne vom concentra atenția pe instrumente (cum sunt Cucumber sau Serenity BDD), ci mai degrabă pe abordări de infrastructură.

Luăm în calcul soluții care au potențial să faciliteze integrarea într-un deployment pipeline, astfel încât poate fi luată în calcul o abordare automatizată pentru Continuous Delivery.

Având o Strategie de Testare adaptată specifc pentru proiect ajută la reducerea timpului ciclului (Cycle Time) și îmbunătățește productivitatea doar având mai multă automatizare și mai puțină intervenție umană. În acest fel, putem valida soluția cât mai timpuriu posibil și revalida încontinuu cât de frecvent posibil.

Soluțiile prezentate nu sunt complet dovedite. Este nevoie de câteva proiecte realizate de echipe diferite pentru a aduna destule date și a trage concluziile finale. Avantajele și dezavantajele sunt prezentate așa cum au fost observate până acum în dezvoltarea continuă.

Medii de test permanente

Cea mai evidentă soluție e și cea mai simplă și presupune câte un mediu de testare real pentru fiecare subsistem.

Desfășurarea poate fi efectuată în medii On-Premise sau Cloud, cum sunt AWS EC2 Instances sau ECS, [Azure Virtual Machines](https://azure.microsoft.com/en-us/services/virtual-machines/ ), sau AKS, CloudFoundry sau Heroku Buildpacks, ș.a.m.d.

Această abordare oferă disponibilitate, stabilitate și transparență. Subsistemele sunt prezente întotdeauna ca ținte pentru testele E2E.

Există și unele dezavantaje, cum sunt costul, complexitatea managementului pe măsură ce sistemul crește, și nevoia de personal calificat să opereze toate aceste infrastructuri.

Medii de test temporare

După cum sugerează și numele, aceste medii sunt solicitate doar pe durata testelor, apoi se renunță la ele. Este foarte ușor să realizăm o soluție în medii Cloud, cu ajutorul tehnologiilor Spot și Reserved Instances, dar și să refolosim o infrastructură bazată pe containere pentru un timp, doar să rulăm un set de teste.

Cel mai mare dezavantaj aici e disponibilitatea subsistemelor în afara programului de testare. Poate fi puțin neclar pentru toate părțile implicate ce se întâmplă, ar putea considera aceste sisteme instabile. Pe de alta parte, cu toate că se poate îmbunătăți dramatic costul, complexitatea managementului crește în lipsa unei o soluții automatizate.

Pentru automatizarea creării/distrugerii unui mediu temporar, se pot folosi tehnologii IaC (Infrastracture-as-Code), cum sunt AWS CloudFormation, Azure Resource Manager, Terraform, etc.

De fapt, este cu totul posibil ca ciclul de viață al mediilor să fie integrat chiar în ciclul de viață al testelor E2E. Să luăm Java spre exemplu, unde instrumentele de testare pot fi integrate cu instrumentele de build automation, cum sunt Maven sau Gradle. Un proiect de testare E2E este un proiect de sine stătător, decuplat de restul componentelor care sunt în dezvoltare.

Pentru a executa testele, este suficient să declanșăm buildul acestui proiect E2E, iar testele vor rula ca parte a fazei test sau verify. Din acest punct de vedere ele nu sunt diferite de testele Unit sau Integration.

În JUnit, avem la dispoziție instrumente cum sunt @BeforeClass, @AfterClass, @ClassRule pe care le-am putea folosi să ne asigurăm că mediul nostru țintă pentru un subsistem specific e pregătit și rulează înaintea declanșării testelor. La sfârșitul testelor, aceleași instrumente ne pot ajuta să distrugem mediul de test.

În interiorul acestor metode putem face orice e nevoie, cum ar fi:

Principalul beneficiu al integrării ciclului de viață al mediului în ciclul de viață al buildului este acela că responsabilitatea menținerii mediilor cade în mâinile dezvoltatorilor de teste. În acest caz, chiar putem folosi mecanismele IaC pentru îmbunătățirea Testabilității.

Concluzii

Deoarece sistemele de tip pull sunt văzute din perspectiva testării în calitate de clienți, doar teste End to End la nivelul sistemului s-ar putea dovedi a fi insuficiente. Felul în care descompunem problema ne poate da o indicație pentru felul în care compunem subsistemele, iar în final ne poate ajuta să îmbunătățim testablitatea sistemului.


NUMĂRUL 149 - Development with AI

Sponsori

  • Accenture
  • BT Code Crafters
  • Accesa
  • Bosch
  • Betfair
  • MHP
  • BoatyardX
  • .msg systems
  • P3 group
  • Ing Hubs
  • Cognizant Softvision
  • Colors in projects