Decipherarea jargonului de testare

În ultima vreme, am auzit și citit din ce în ce mai mult despre dezvoltarea bazată pe teste. Acest domeniu, cu toate acestea, vine cu o serie de expresii și jargon specifice care pot fi confuze pentru nou-veniți. Acest articol vă va îndruma prin cele mai comune definiții, tipuri de încercări și părți de testare. Vor fi furnizate cazuri de utilizare și, dacă este posibil, un cod din PHP va fi de asemenea prezentat.


Prima zi la un nou loc de muncă

Cu câțiva ani în urmă, un nou programator a fost angajat la o echipă de dezvoltare. Ca orice alt nou venit, a fost destul de confuz în prima zi. În timp ce ascultase discuțiile din jurul lui în birou, au fost folosite o mulțime de teste specifice. Acestea erau expresii necunoscute noului programator fictiv.

Din fericire pentru el, aceasta fiind prima lui zi de muncă, cei doi colegi au fost mai târziu desemnați să-i explice tot acest jargon. Ei au început cu o listă de termeni legați de funcționarea interioară a unui test.

Testul automat

Software de testare software este practic un test automat. Testul de automatizare a fost în jur de înainte de PC; primele cadre automate de testare au apărut în timpurile mainframe-urilor și consolelor. Astăzi, testarea automată este calea evidentă de parcurs. De ce? Deoarece testarea este o sarcină dificilă și repetitivă - ceva care nu este potrivit pentru ființele umane. Testarea automată este mult mai rapidă și mai precisă decât testarea manuală. Și nu, nu elimină testerul uman sau o echipă de QA din sistem. Pur și simplu îi face să facă o slujbă mai potrivită pentru oameni și să le permită să o facă bine.

Configurarea / Exercitarea / Verificarea / Teardown

Orice test ar trebui să fie pătrat în patru părți:

  • Înființat - indiferent ce trebuie să fie pregătit înainte ca codul să poată fi rulat
  • Exercițiu - rulați codul pe care dorim să îl testați
  • Verifica - comparați rezultatul rundei cu o anumită stare așteptată
  • Dărâma - curățați toate lucrurile suplimentare pe care le-am folosit pentru testare, astfel încât sistemul să fie în aceeași stare ca și înainte de a începe testul curent (statul din Înființat Etapa).

Proiectăm fiecare test pentru a avea patru faze distincte care sunt executate în ordine: configurarea dispozitivului de fixare, exercițiul SUT, verificarea rezultatelor și fixarea teardonului. - Modele de testare xUnit: Codul de testare a reactivării, de Gerard Meszaros

Un dispozitiv de testare

Un dispozitiv reprezintă toate informațiile pe care le are nevoie testul pentru a fi exercitate. Un element de fixare poate fi la fel de simplu ca și crearea unui obiect simplu $ testObject = nou RealObject ();, sau ceva la fel de complicat ca baze de date populare și de pornire interfețe de utilizator.

Tot ceea ce trebuie să aibă un sistem în curs de testare (SUT), astfel încât să putem exercita SUT în scopul verificării comportamentului său. - Modele de testare xUnit: Codul de testare a reactivării de către Gerard Meszaros

SUT: Testul sistemului

Probabil ați observat acest termen recurent. Programatorii se vor referi de obicei la aceasta ca SUT. Acesta reprezintă toate lucrurile necesare pentru a fi testate. În funcție de tipul testului (vezi mai jos pentru tipurile de testare) SUT poate fi multe lucruri de la o metodă sau o clasă la întregul sistem.

Orice lucru testezi. SUT este întotdeauna definită din perspectiva testului. - Modele de testare xUnit: Codul de testare a reactivării, de Gerard Meszaros


Descoperirea Mai mult ...

Începând cu a doua zi la locul de muncă, programatorul nostru a scris primul său test. Era mai dificil decât anticipase. Pentru a scrie, avea nevoie de o cadru de testare, și a trebuit să creeze o caz test și apoi executați toate metode de testare. Au existat și câteva dependențe ciudate pe care trebuia să le înțeleagă. Se părea că învățați DOC era în program.

Testarea cadrului

Un cadru de testare este o aplicație care este proiectată special pentru testarea codului într-o anumită limbă. Conceptul de a cadru de testare a fost pionierat de Kent Beck la începutul anilor '90. Munca sa a dus ulterior la un cadru pentru SmallTalk, numit SmalltalkUnit, și apoi redenumit Sunit.

Smalltalk a suferit din cauza lipsei unei culturi de testare. Această coloană descrie o strategie simplă de testare și un cadru care să o susțină. Strategia și cadrul de testare nu sunt intenționate să fie soluții complete, ci mai degrabă un punct de pornire de la care pot fi construite instrumente și proceduri de rezistență industrială. - Testarea simplă de mici dimensiuni: cu modele, de Kent Beck

A fost prima xUnit cadru și a definit conceptul de bază al testării și termenii prezentați mai sus. Astăzi, aproape fiecare limbaj de programare oferă versiunea sa a acestui cadru: PHPUnit pentru PHP, JUnit pentru Java, ShUnit pentru UNIX Shell Scripts și așa mai departe. Ați fi surprins să aflați câte lucruri pot fi testate astăzi și câte teste pot fi automatizate.

Caz de testare

Inițial, un "caz test" a fost definit ca fiind cea mai mică unitate de testare a lui Kent Beck.

Când vorbești cu un tester, cea mai mică unitate de testare despre care vorbește este un caz de testare. TestCase este Obiectul utilizatorului, reprezentând un singur caz de test. - Testarea simplă de mici dimensiuni: cu modele de Kent Beck

Aceste zile, noi folosim metoda de test pentru a defini această parte mai mică și un caz de testare se referă în cea mai mare parte la un set de metode de testare conexe. De exemplu, o situație tipică este când ne testăm unitatea codul nostru și un caz de testare se referă la totalitatea metodelor de testare care testează o anumită clasă sau orice este cea mai mică unitate din limba noastră de programare. Un caz de testare, de multe ori, este pur și simplu denumit: "un test."

Metoda de test

O metodă de testare este cea mai mică parte a unei arhitecturi de testare. O metodă de testare este unitatea care constă din părțile definite mai sus: setup / exercise / verify / teardown. Este partea esențială a oricărui test; cel care face munca.

O metodă de testare este o procedură definitivă care produce un rezultat al testului. - Manual de formular și stil, ASTM, 2012

DOC - Componenta dependentă

Acesta a fost cu ușurință unul dintre termenii cei mai confuzi pentru noul nostru programator. Acesta reprezintă toate celelalte clase și componente ale sistemului pe care SUT are nevoie pentru a putea funcționa corespunzător. Dar, de asemenea, DOC trebuie să furnizeze metode specifice care să ne permită să o observăm și să o testăm. Conceptele batjocoritor și testul se dublează sunt strâns legate de DOC.

O clasă individuală sau o componentă granulată pe care depinde sistemul testat (SUT). Dependența este, de obicei, una de delegare prin apeluri metodice. - Modele de testare xUnit: Codul de testare a reactivării, de Gerard Meszaros


Există teste diferite de unitate?

Curând după ce a scris primele teste, noul om a realizat că testează diferite părți logice ale aplicației. Uneori, este mai bine să testați o parte mică în izolare; de altă dată, este necesar să testați un grup de obiecte împreună și modul în care se vorbește unul cu celălalt; și alteori, trebuie să testați întregul sistem. Lucrurile păreau mai complicate decât se presupunea anterior; așa că programatorul nostru a continuat să citească o carte, alta și alta și, în cele din urmă, a înțeles.

Piramida de testare

Piramida de testare a fost definită pentru prima dată în carte, Succes cu Agile Software Development Utilizând Scrum, de Mike Cohn, și apoi adoptate în curând de comunitatea software.

Piramida reprezintă cele trei straturi principale de testare: UI, Service și Unitate.

UI strat reprezintă nivelul maxim de testare: când sistemul este exercitat prin interfața de utilizare și întreaga aplicație este testată ca una. Acest strat ar trebui să reprezinte cea mai mică sumă din multitudinea de teste.

Nivelul de serviciu conține mai multe tipuri diferite de teste. Este vorba în principal de comunicarea internă a modulelor și de funcționarea corectă a API-ului extern (interfața de programare a aplicației) a unei aplicații. Ar trebui să existe mai multe astfel de teste în apartamentele noastre, dar ele nu ar trebui să fie o bază pentru testarea noastră. Aceste teste sunt de obicei de formare a mai multor părți ale cererii, și, prin urmare, acestea sunt destul de lente. Acestea ar trebui să fie executate cât mai des posibil, dar nu la fiecare salvare a codului. Probabil la fiecare construire a sistemului sau când se întâmplă o comitere cu sistemul de versiuni.

Unitatea stratului se referă la teste care exercită cele mai mici unități posibile ale codului nostru în izolare completă. Aceste teste ar trebui să reprezinte marea majoritate a testelor. Acestea ar trebui să fie foarte rapide (1-4 milisecunde / test) și ar trebui să fie executate cât mai des posibil. Dezvoltarea bazată pe teste (TDD) este un bun exemplu pentru modul în care se maximizează utilizarea testelor unității.

Detalierea piramidei de testare

Pe baza exemplului de mai sus, comunitatea a elaborat mai multe versiuni mai detaliate ale piramidei de testare. Cel pe care îl consider cel mai bun poate fi văzut în imaginea de mai jos.

Cele trei straturi principale pot fi distinse clar, însă stratul central este mai detaliat. Odată cu trecerea timpului, comunitatea software a descoperit și a definit câteva metode noi de testare. Unele dintre ele au fost incluse pe piramida.

Vă rugăm să rețineți: tehnicile de testare automate și cadrele se schimbă foarte rapid. De aceea, după cum puteți vedea mai jos, unele expresii nu sunt încă clare și există mai mulți termeni pentru aceleași definiții în funcție de comunitatea care le-a promovat.

Testul unității

Un test de unitate reprezintă testarea limbajului de programare al celei mai mici unități. În programarea orientată obiect, acestea sunt clase / obiecte. În alte limbi, ele pot fi module mici sau chiar funcții / proceduri.

A Test în aceste definiții se referă la același lucru ca și cazul unui test.

Un test care verifică comportamentul unei mici părți a sistemului global. Ceea ce transformă un test într-un test de unitate este că sistemul testat (SUT) este un subset foarte mic al întregului sistem și poate fi nerecunoscut pentru cineva care nu este implicat în construirea software-ului. - Modele de testare xUnit: Codul de testare a reactivării de către Gerard Meszaros

Testele unităților reprezintă marea majoritate a testelor pe care un programator le scrie. Da, este adevărat: testele unice sunt cele mai multe ori scrise de programatori. Testul unității îi ajută pe dezvoltatori să dezvolte aplicația, să prevină erorile comune, greșelile și regresiile. Sunt teste efectuate de programatori pentru programatori.

Din acest motiv, testele unitare sunt mai tehnice și mai criptice. Ei sunt aici pentru a ajuta programatorii să scrie cod mai bun; atunci când ceva nu reușește la un nivel de testare a unității, este de obicei o problemă pentru un programator de a repara.

Teste componente

După cum sugerează și numele, testele pentru componente sunt scrise pentru bucăți puțin mai mari ale aplicației. Un test al componentelor exercită de obicei un întreg modul sau un grup de unități logic interdependente.

Componenta este o consecință a uneia sau a mai multor decizii de proiectare, deși comportamentul acesteia poate fi urmărit, de asemenea, la un anumit aspect al cerințelor. - Modele de testare xUnit: Codul de testare a reactivării de către Gerard Meszaros

Desigur, un test de componentă exercită mai mult cod decât un test de unitate. De asemenea, poate testa modul în care unele unități lucrează împreună și vorbesc unul cu celălalt.

O componentă poate fi, de asemenea, urmărită înapoi la o cerință sau o parte dintr-o cerință. Acest lucru înseamnă că un test de componente nu este doar pentru programatori. Liderii de echipă, maeștrii de scrum, arhitecții și alți oameni implicați din punct de vedere tehnic sunt cu siguranță interesați de module, de organizarea lor și, uneori, chiar de lucrările lor interioare. Nu este necesar ca acești oameni să fie familiarizați cu un anumit limbaj de programare. Testul trebuie să se concentreze mai mult pe comportament și să definească așteptările într-un mod mai ușor de înțeles.

De exemplu, un test de unitate poate avea un mesaj de eroare care să ateste că:

TestFileAccessCanWriteToAFile: Nu s-a afirmat că fișierul "/ tmp / testfile" este prezent în sistem.

Un astfel de mesaj nu ar fi de ajutor unui arhitect sau unui manager sau unui lider de echipă. Un test de componentă poate eșua cu o eroare mai descriptivă:

Test de administrare a contului: Eșuat când am încercat să specificăm 0 (zero) ca suma totală a unui utilizator pe contul său.

Un astfel de test exercită o funcționalitate de nivel superior. Pe baza mesajului de eroare de mai sus, pot exista mai multe straturi de comunicare și clase / obiecte implicate în operațiunea de specificare a unei sume ca totalul în contul someones.

Testul de integrare

Acest tip de test necesită mai multe module și verifică modul în care se integrează unul cu celălalt. Verifică dacă modulele API interne sunt compatibile și funcționează conform așteptărilor.

Cu toate acestea, termenul permite o gamă largă de utilizări posibile. Unele comunități de software se referă puternic la testele de integrare, testând modul în care aplicația noastră funcționează în mediul pe care trebuie să-l ruleze. Cu alte cuvinte, cum se integrează în sistemul superior.

Alții definesc testul de integrare la diferite niveluri: orice definire a comunicării între două elemente poate fi văzută ca o integrare. Aceste elemente pot fi unități, cum ar fi clase, module sau chiar părți funcționale superioare ale software-ului.

Nu există o definiție unanim acceptată a termenului, test de integrare.

Teste API

GUI-ul unei aplicații se referă la software-ul prin API-ul software-ului. Testarea la acest nivel exercită o mulțime de cod și poate dura o perioadă relativ semnificativă de timp.

API este mijlocul prin care alte aplicații software pot invoca anumite funcționalități. - Modele de testare xUnit: Codul de testare a reactivării de către Gerard Meszaros

În programarea orientată obiect, astfel de API-uri sunt definite de metodele publice ale clasei. Cu toate acestea, dacă aruncăm o privire la o schemă de proiectare arhitecturală la nivel înalt, semnificația API poate fi limitată la metodele publice ale clasei care oferă funcționalitate prin limitele logicii de afaceri. Aceste clase de limită reprezintă API-ul și trebuie să testați că, atunci când le sunăm și le folosim, sistemul se comportă așa cum era de așteptat.

De obicei, aceste teste sunt efectuate periodic și durează mult timp până la terminare.

Testarea interfeței grafice

Ar trebui să existe doar câteva cazuri rare când doriți să vă prezentați o cerere. Nu există nicio logică în stratul GUI, doar prezentare.

Testarea dacă un buton este verde sau roșu sau dacă are 30px în lățime este inutilă, și este prea mult de un overhead. Deci, nu sari in testarea opiniilor tale. Dacă se întâmplă ceva rău cu GUI, va fi observat în faza de testare manuală experimentală.

Testarea vizualizărilor ar trebui să facă doar două lucruri: prezentarea condiționată a testului și testarea faptului că se solicită API-ul așteptat.

Sărind-te în testarea opiniilor tale poate fi tentantă. Nu-i! Testați numai ceea ce credeți că poate eșua. Testați numai pentru valori sau pentru apeluri funcționale. Nu verificați niciodată elementele GUI sau proprietățile acestora. Utilizați REGEX ori de câte ori este posibil pentru a se potrivi cu șiruri de caractere și pentru a verifica cuvintele cheie care nu sunt susceptibile de a se schimba.

De exemplu, următorul cod pseudo este un exemplu rău pentru testarea prezenței unui șir pe ecran.

function testItCanTellTheNameOfTheUser () // logica unui cod de redare aici $ renderedName = $ this-> renderName (); $ this-> assertEquals ('Utilizatorul are numele'. $ renderedName ['first']. "$ renderedName ['last']. '

Nu numai că acest test este dificil de citit, dar testează o expresie exactă - ceva de genul "Utilizatorul are numele John Doe"., inclusiv semne de punctuație! De ce e rău? Deoarece cineva poate schimba cu ușurință forma acestei fraze fără a-și schimba semnificația.

Ce se întâmplă dacă clientul nostru are nevoie Ultimul nume primul nume care trebuie prezentat? Asta ar face ca testul nostru să nu reușească. Trebuie să ne întrebăm: în cazul în care testul eșuează? Am schimbat logica software-ului? Eu spun nu, nu ar trebui să eșueze. Numele ar mai fi prezent pe ecran; ordinea celor două părți ar fi pur și simplu diferită. Acesta este un test mai potrivit.

function testItCanTellTheNameOfTheUser () // logica unui cod de redare aici $ renderedName = $ this-> renderName (); $ this-> assertRegExp ($ rangedName ['prima'], $ rangedName); $ this-> assertRegExp ($ renderedName ['ultima'], $ rangedName); 

Acest lucru asigură acum că numele este prezent, dar nu-i pasă de construcția lexicală. Cineva ar putea schimba fraza inițială în ceva, cum ar fi Don, John este numele utilizatorului actual. Semnificația va rămâne aceeași și testul va trece în continuare corect!


Ce lipsește din Piramida?

După o lună de lucru la locul de muncă, noul nostru programator fictiv înțelege că, chiar dacă piramida este destul de rece, nu este completă. Uneori, există un test de cuplu sau diferit care ar trebui să fie executat - și sunt destul de greu de plasat pe piramida.

Acceptarea testelor

Acestea sunt unul dintre cele mai controversate teste. În funcție de ce fel de cărți citești, testele de acceptare ar putea fi numite Teste funcționale

sau

  • End-to-End Teste
  • sau

  • Acceptarea testelor
  • sau

  • Teste ale clienților.

    Fiecare nume provine de la o altă comunitate sau autor. Eu personal prefer Acceptarea testelor sau End-to-End Teste.

    Un test de acceptare verifică comportamentul unei fragmente a funcționalității vizibile a sistemului global. - Modele de testare xUnit: Codul de testare a reactivării de către Gerard Meszaros

    Un astfel de test va face ceva pe GUI. Schimbarea se va întâmpla în întregul sistem. Datele vor fi salvate în baza de date sau în sistemul de fișiere. Se va face comunicarea în rețea. În cele din urmă, interfața grafică va fi verificată pentru răspunsul din sistem. Astfel de teste încearcă să imite complet un utilizator.

    Testele de acceptare sunt strâns legate de părțile interesate din cererea noastră. Acestea sunt de obicei definite în limba de afaceri, și, atunci când ceva nu merge bine, o funcționalitate întreaga este considerată defunct. Aceste teste sunt de asemenea utilizate pentru a defini funcționalitatea la nivel înalt a aplicației.

    De obicei, acestea sunt scrise de QA și de management și sunt implementate de programatori. Inițial, au fost inventate ca o punte între management și producție. În unele situații, au reușit. Limba testelor este suficient de flexibilă pentru a fi scrisă și înțeleasă de persoane care nu sunt direct implicate în scrierea de software.

    Există cadre speciale pentru astfel de teste, cum ar fi Fitness, Selenium, Watir, Castraveți și alții.

    Teste contractuale

    Acestea sunt un caz mai special, și nu sunt folosite prea des. Le puteți folosi uneori în limbi orientate obiect atunci când interfețele și moștenirea trebuie testate. Testul asigură în principiu că o clasă implementează cu adevărat toate interfețele pe care le are.

    Testele de contract explică modul în care o clasă ar trebui să extindă o superclasă sau să implementeze o interfață. - J. B. Rainsberger

    În unele aplicații, termenul contracta este folosit pentru un alt tip de testare. Această a doua definiție a testului contractual verifică dacă se respectă contractul dintre aplicația noastră și o componentă terță parte pe care depindem. Aceste teste utilizează codul curent și codul terților, asigurând că rezultatele sunt conform așteptărilor.


    Toate aceste teste trebuie să fie executate!

    După o vacanță bine meritată, programatorul noștri atât de junior este din nou la locul de muncă. Acesta a fost primul său concediu și se simte plin cu o nouă putere de a scrie teste și cod. După șase luni, se simte bine la locul de muncă; el sa integrat frumos în echipă și scrie un cod foarte bun. Dar din când în când, are un sentiment frustrant. Executarea a cinci tipuri diferite de seturi de testare într-o ordine strict definită în fiecare seară este plictisitoare și predispusă la erori.

    Apoi, există o altă discuție ciudată între liderul său de echipă și conducere. Vorbesc despre asta C.l.. și CD.. Ce ar putea însemna asta? A fost prea criptic pentru noul nostru programator să înțeleagă. Câteva săptămâni mai târziu, a existat un mesaj la nivel de companie: "Vă rog să nu mai faceți testele de seară. Avem C.I.!. Pentru a afla mai multe, sa dus la conducătorul echipei și a întrebat: "Ce este CI și CD-ul?".

    Integrare continuă (CI)

    Echipele care se bazează foarte mult pe testarea automată au nevoie de o modalitate de a conduce toate aceste teste într-un mod organizat și eficient. Un sistem de integrare continuă ajută la acest lucru.

    Integrarea continuă este o practică de dezvoltare software în care membrii unei echipe integrează munca frecventă, de obicei, fiecare persoană se integrează cel puțin zilnic - ceea ce duce la multiple integrații pe zi. Fiecare integrare este verificată de o construcție automată (inclusiv testul) pentru a detecta erorile de integrare cât mai repede posibil. - Martin Fowler

    Bazându-ne pe această definiție, procesul de integrare continuă va face treaba să ne desfășurăm testele fără intervenția omului. În definiție, integrarea frecventă este exemplificată ca zilnic, dar vă pot spune că este foarte interesant să lucrați la o bază de software care este testată automat pe fiecare comitet. Angajarea frecventă înseamnă că orice modificare care este completă trebuie să fie comisă, astfel încât să aveți zeci de angajamente într-o singură zi. Fiecare comitet va declanșa o testare completă a sistemului și veți primi un e-mail frumos, verde sau roșu, în funcție de rezultat, în doar câteva minute. Dacă e-mailul este verde, produsul este teoretic imediat expediabil.

    Livrarea continuă (CD)

    Acest lucru nu este legat atât de testare, ci de CI. În timp ce CI vă permite să aveți un sistem livrat, versiunile se fac încă periodic și manual.

    Livrarea continuă automatizează toți pașii de la cod la client.

    După ce totul se face la nivel de CI, livrarea continuă o face și mai departe și construiește kiturile de instalare a software-ului, le publică după cum este necesar și chiar poate declanșa proceduri de actualizare de la distanță pentru clienți. Scopul unui astfel de sistem este de a livra produsul cât mai repede posibil utilizatorului final. Este foarte dependent de testele automate și, dacă toate acestea trec, produsul este livrat. Perioadă.

    Chiar dacă, în unele situații, acest lucru poate părea foarte atractiv, în majoritatea aplicațiilor, este încă prea periculos. De obicei, orice sistem critic decent trebuie să treacă printr-o sesiune de testare manuală experimentală înainte de livrare.


    De ce este încă folosit testul manual??

    Există părți ale unei proceduri de testare care sunt pur și simplu prea dificilă - dacă nu imposibilă - să automatizeze. Tocmai de aceea Studiu manual experimental sesiunea este de obicei făcută înainte de fiecare lansare de software. Aceste teste pot fi efectuate de testeri specializati sau de programatori in functie de structura echipei si a companiei.

    Testarea manuală presupune imaginație. Ființele omenești se zbat în jurul sistemului, asigurând funcționarea și aspectul dorit.

    Unele echipe consideră testarea manuală a << Break it if you can! >> concept.


    concluzii

    Nu puteți evita testarea jargonului. Sperăm că acest articol a scos în evidență diferențele dintre diferitele forme de testare. Alte intrebari? Cereți mai jos!

  • Cod