Fixie – framework testare

Fixie – framework testare

Acum ceva timp am dat peste un tweet postat de unul din prietenii mei despre un nou framework de testare open-source numit Fixie – in acel tweet persoana respectiva vorbea despre cat de multumit este de acest program. Era atat de placut impresionat de el incat s-a decis sa revizuiasca toate testele din proiectul la care lucra folosind acest tool. Asa ca a trebuit sa vad despre ce era vorba.
29 Mar 2016 9818
Acum ceva timp am dat peste un tweet postat de unul din prietenii mei despre un nou framework de testare open-source numit Fixie – in acel tweet persoana respectiva vorbea despre cat de multumit este de acest program. Era atat de placut impresionat de el incat s-a decis sa revizuiasca toate testele din proiectul la care lucra folosind acest tool. Asa ca a trebuit sa vad despre ce era vorba.

In acest articol vreau sa va ofer o privire de ansamblu asupra acestui framework si a caracteristicilor sale aslfel incat sa vedem daca la final il putem folosi in munca noastra sau nu.

Asa cum spune si in prezentarea de pe site, Fixie este Conventional Testing pentru .Net adica testing by agreement. Agreement inseamna ceva cu care majoritatea dintre noi suntem obisnuiti. Cel mai adecvat exemplu in acest caz este ceea ce am numi scaffolding – atunci cand agreem ca test classes contin cuvantul Test sau ca test classes sunt publice si nu returneaza nimic. Apoi aceste clase vor fi recunoscute ca test classes. Fara alte atribute. Doar clase si metode.

La prima vedere totul pare a fi ok. Trebuie doar sa denumesti metodele si clasele corect. In acelasi timp poti sa instruiesti echipa ta sa faca acelasi lucru.

Instalarea si primul test

In mod implicit, Fixie este construit in asa fel incat sa considere tot ce se termina cu Tests ca reprezentand test classes. Test methods reprezinta tot ce se afla in aceste clase si nu returneaza nici o valoare. In teorie urmatorul cod ar fi recunoscut ca test:

fixie1.jpg

Inainte de a merge mai departe, este util sa vorbim un pic despre instalarea si cerintele Fixie.

fixie2.jpg

Aceasta este comanda nuget pentru instalarea frameworkului. Dar nu este totul. Acest framework nu ofera o metoda built-in pentru scrierea de data checks in cadrul unui test. Pentru a le utiliza trebuie sa folosesti un third party solution precum:
  • FluentAssertions
  • Should
  • Shouldly
Toate acestea pot fi instalate folosind NuGet. In exemplul de mai sus folosim pachetul FluentAssertion din simplul motiv ca il prefer – diferentele nu sunt asa de mari fata de altele. Si acesta este tot, acum putem scrie cod. In special daca te afli la inceput in software development si testare.

Integrare

In ceea ce priveste rularea testelor, autorul recunoaste ca a trebuit sa ruleze testele din consola astfel ca a facut integrarea cu studio abia ca ultim pas. Exista un plugin pentru ReSharper dar este pentru versiunile de la 8.1 pana la 8.3 – nu este suportat de noile versiuni. Nu am vrut sa fac un downgrade catre o versiune mai veche doar pentru a rula testele astfel ca nu pot spune cat de usor de folosit este. Integrarea cu studio se face la nivel de detectare a testelor si rulare – editorul nu va evidentia. Acest lucru se refera la test icons speciale.

fixie3.jpg

Aici din punctul meu de vedere pot avea loc erori. Typos. Nu este chiar atat de greu sa scrii gresit cuvantul “Tests” lucru care va duce la ignorarea acelei clase. Vizual nu sunt marcate in nici un fel. Aceasta situatie este destul de rara daca folosesti instrumentele studio corecte si nu rulezi testele in masa ci doar acele teste care nu fost rulate.

fixie4.jpg

In general putem spune ca, avand in vedere ca frameworkul este nou si relativ necunoscut, anumite instrumente lipsesc. In ceea ce priveste detectarea testelor si generarea rezultatelor, documentatia ne spune ca Fixie poate genera rapoarte in stilul Nunit si xUnit, ceea ce va face mai usoara viata celor care au un CI construit normal.

Tuning

Principalul punct forte al frameworkului este posibilitatea de a ajusta in mod flexibil modul in care testele tale vor fi indentificate, incepute si validate. Nimic nu este oferit implicit in framework. Insa in repository putem gasi diferite exemple. Pentru a face totul mai interesant hai sa vedem cum acest framework poate sa raspunda nevoilor noastre. Spre exemplu, cum sa facem pentru ca si alte clase sa fie indentificate ca test classes.

Toate setarile se fac in class constructor-ul mostenit din Conventie.

fixie5.jpg

Implicit aceste setari arata asa:

fixie6.jpg

Codul spune ca test classes trebuie sa se termine cu Tests si test methods sunt tot ce este returnat ca null. Per ansamblu este decent. Incerc sa urmez principiul care spune ca test class incep cu When si testele cu Then. Astfel imaginea din testrunner este destul de curata si atunci cand scriem teste stim deja ce vom testa si trebuie sa ne gandim doar la efectele testului. Un bonus este ca test classes sunt scurte si responsabilitatea intre teste nu se combina.

fixie7.jpg

Uitandu-ma la lista mea de teste, pot sa vad ca nu toate clasele se termina cu Tests sau incep cu When.

Nu exista o strategie de numire in teste, in sensul in care testele ar trebui sa inceapa cu Should, spre exemplu. Insa in opinia mea, atunci cand citesti teste esti constient de ce se intampla. Vorbesc din experienta. La acest proiect lucrez de 3 sau 4 ani cu diferite grade de succes si de fiecare data cand ma reintorc stiu ce am facut si ce ar trebui sa fac.

In acest stil de numire imi este usor teama (si lene) sa numesc cuvintele cheie prin care clasele de teste vor fi identificate. Mai mult decat atat, abordarea When / Then inseamna ca exista o metoda de setup care porneste la inceputul fiecarui test astfel ca rezultatele testului sunt fie verificate in test sau obiectul creat este afectat intr-un fel. Adica va trebui sa marchezi sau sa specifici in mod explicit metoda de setup (SetUp).

Pentru implementare pot sa apelez in mod specific metoda de setup pentru fiecare test. Spre exemplu:

fixie8.jpg

Bineinteles, ca in viata reala este necesar sa scriem ceva mai informativ decat SetUpEnvironment (), insa idea este clara. Aceasta implementare ofera class variables care isi vor pastra valorile intre teste, lucru care poate duce cu usurinta la teste dependente daca uit sa scriu un initialization string in cateva dintre ele.

Fixie ofera o solutie pentru aceasta situatie. Iata:

fixie9.jpg

Cu alte cuvinte trebuie sa implementam un descendant al CaseBehaviour si sa scriem tot ce avem nevoie acolo. Documentatia spune ca implementarea este:

  • CaseBeh * avior = [SetUp] / [TearDown]
  • FixtureExecution = [FixtureSetUp] / [FixtureTearDown]
Dar chiar si asa, in aceasta abordare vedem ca trebuie sa dezvoltam foarte multe variante “DefaultConvention” si sa scriem initialization logic departe de teste, si la inceput nici nu stim ce contine un asemenea test.

Este greu sa demonstram asta. Daca DefaultConvention este ca in exemplul de mai sus atunci cand incepe clasa:

fixie10.jpg

Nimic nu imi spune ca este un SetUp / TearDown.

Acest lucru este complet contrar faptului ca testele ar trebui sa fie transparente. Chiar si daca scriu o extensie pentru CaseBehavior in aceeasi clasa, acest lucru nu va rezolva problema, deoarece nu va fi foarte evident unde sa ne uitam dupa clasa. Un proces continuu de copy-paste nu este raspunsul.

Sa comparam:

fixie11.jpg

Versus:

fixie12.jpg

Sunt mai putine linii de cod in cazul Nunit, si SetUp din cadrul clasei nu va fi pierdut in proiect.

Poate ca am anumite prejudecati si scriu teste incorect dar ... nu cred. Nu am vazut foarte multe articole care sa spuna ca SetUp este rau. Totul poate fi redus la absurd si poti sa faci initializari pentru jumatate din proiect dar asta este o alta poveste. Exista insa o solutie si aici. Self-made attributes pot sa fie folosite pentru a identifica elementele relevante – test parts, teste si clase. Poti sa imiti Nunit, xUnit in proiectul tau.

Prin intermediul atributelor poti sa dezvolti:

  • Suport pentru categorii
  • Teste parametrizate
  • Teste rulate intr-o anumita ordine
Iata un exemplu de creare si activare a categoriilor.

fixie13.jpg

Si rularea:

Fixie.Console.exe path/to/your/test/project.dll –include CategoryA

Solutia mea

Sunt mai multe lucruri de spus despre Fixie insa este momentul sa rezumam. Fixie este de fapt un metaframework de testare. Esti liber sa construiesti tot felul de reguli si oportunitati de testare – sunt si usor de construit. Singura intrebare este daca se merita. Este necesar sa facem toate astea? Lipsa de support pe R# si faptul ca nu pot sa vad daca testul este chiar un test si daca este recunoscut de framework este usor descurajant.

Nu as folosi acest program in productie insa pentru utilizarea personala Fixie este interesant.

Andrey Gordienkov

Software Architecture and Development Consultant




Share the knowledge

Mai ai intrebari?
Contacteaza-ne.
Thank you!
The form has been submitted successfully.