ABONAMENTE VIDEO TESTE REDACȚIA
RO
EN
×
▼ LISTĂ EDIȚII ▼
Numărul 64
Abonament PDF

Eleganța unei arhitecturi avansate de testare automată, bazată pe componente open source

Adrian Vaidos
IT Operations Manager–Applications @ Siemens
PROGRAMARE


Atunci când un proiect software trebuie să fie supus în premieră unui testări automate, probabil că primul lucru la care ne gândim este folosirea unui software comercial destinat tipului de software care urmează a fi testat. De foarte puține ori avem în vedere sau avem curajul să abordam, o soluție de testare automată bazată exclusiv pe componente gratuite și open source, deși în final putem obține rezultate mult mai elegante și mai eficiente comparativ cu soluția comercială.

 În funcție de experiența profesională a celor implicați și ținând cont de tipul proiectului software care urmează a fi testat (aplicație desktop, web, mobile, etc.), sau de tipul de testare automată (UI, API, Performance, DB, etc.), putem avea în vedere soluțiile HP UFT, LeanFT, Microsoft Coded UI, clasicul Selenium cu Visual Studio sau Java. Desigur că există o mulțime de alte soluții comerciale mai mult sau mai puțin cunoscute care pot fi avute în vedere, cum ar fi TestComplete, Tricentis, Ranorex, eggPlant, etc. . Criteriile principale pentru alegerea unei soluții ar fi în ordinea importanței: gratuitatea, costul licențelor, al resurselor necesare și al eventualelor traininguri, deținerea unei soluții (ducând la așa numitul sunk-cost bias sau capcana costurilor îngropate), experiența profesională în general și în particular cu soluția respectivă a celor implicați în decizie, recomandări, demo-uri și cercetare personală. Alte criterii de alegere pot fi cele ce țin de politica companiei, de colaborare, de existența suportului comercial, dar și de soluțiile impuse de către client. Deși de cele mai multe ori, marketingul și evaluările externe de tip marketing pot avea o influență hotărâtoare. 

Dacă nu avem nici un fel de experiență cu soluția de testare automată respectivă, putem începe cu facilitatea "record and playback" pentru a înregistra câteva teste și a le rula, demonstrând astfel viabilitatea soluției respective. Cu toate că de cele mai multe ori această facilitate eșuează în proiectele reale, fiind mai degrabă o facilitate existentă în scop de marketing, de multe ori aceasta este utilă pentru un start rapid în faza inițială de evaluare a diferitelor soluții de testare automată.

Pentru a iniția cu succes un proiect de testare automată, sunt recomandate următoarele condiții prealabile:

 Deși sunt destul de cunoscute, merită să reamintim aici avantajele testării automate, care pot fi aduse ca argumente atunci când încercăm să influențăm decizia de a iniția un proiect de testare automată, și anume:

Mergând mai departe, soluția de testare automată poate fi uneori una simplă, prin simpla utilizare a uneltei de testare alese, conform recomandărilor furnizorului soluției, respectiv fără implementarea unui Framework. Dacă soluția de testare automată este mai complexă, și aceasta presupune crearea unei arhitecturi software, împreună cu unul sau mai multe Frameworkuri, pornind de la una sau mai multe soluții comerciale sau open source cunoscute, procesul în linii mari ar fi același ca în cazul dezvoltării oricărui proiect software, respectiv cerințe, arhitectură, design, implementare, integrare, testare, instalare, întreținere. Desigur că este important să se țină cont și de metodologia de dezvoltare a proiectului software supus testării. Din păcate, în proiectele reale, de multe ori se începe direct cu implementarea Frameworkului pentru testarea automată a unui software departe de a fi finalizat și astfel instabil, ignorând lipsa condițiilor prealabile exemplificate mai sus precum și trecerea peste etapele premergătoare de definire a cerințelor, arhitectură și design, insuccesul fiind astfel garantat.   Ținând cont de aceste principii de mai sus, în continuare vom exemplifica o arhitectură avansată de testare automată, elegantă și modernă, bazată exclusiv pe componente open source sau gratuite pentru uzul comercial. După cum se poate vedea mai jos, această arhitectură integrează toate aceste componente, bazate pe multiple și diverse tehnologii, într-o soluție inovatoare, unică și completă, care poate satisface cerințele oricărui proiect de testare automată, în cazul de față al unui software web complex.

 Următoarele componente fac parte din această arhitectură:

Deși există biblioteci open source disponibile în Robot Framework pentru fiecare dintre componentele SikuliX, Selenium și AutoIT, doar biblioteca Selenium este destul de avansată și folosită pe larg, astfel încât ne putem baza pe ea. Scriptul AutoIT este apelat ca proces separat din Robot Framework, deși poate fi implementată și o bibliotecă Robot Framework dacă se consideră necesar. Pentru SikuliX este recomandată implementarea unei biblioteci noi, mai degrabă decât rularea ca proces separat ale unor scripturi exclusive SikuliX. Implementarea acestor biblioteci în Robot Framework permite executarea combinată, în funcție de nevoi, a oricărei acțiuni prin intermediul celor 3 componente. De exemplu, verificarea și clickul pe un element identificat cu Selenium, apoi verificarea și clickul pe un element identificat cu SikuliX și eventual extragerea informațiilor din baza de date, de exemplu pentru login, cu ajutorul AutoIT.

Avantajele acestei soluții ar fi:

Dezavantajele acestei soluții ar fi:

Deși utilizarea diferitelor componente open source sau gratuite pentru uzul comercial este exemplificată în detaliu în diferite articole, bloguri sau pe site-urile oficiale de distribuție ale componentelor, integrarea completă și funcțională ale tuturor componentelor în arhitectura prezentată mai sus poate fi considerată dificilă. Deși nu este o descriere completă, pentru a înțelege în mare cum a fost construită și integrată aceasta arhitectură, pașii ar fi următorii:

  1. Se instalează Python27, robotframework, robotframework-selenium2library, PyCharm, plugin-ul Robot Framework Support pentru PyCharm, SixuliX, jython2.7.0, autoit-v3, KeePass-2.35, și driverele Selenium (chromedriver, geckodriver, IEDriverServer).

  2. Dacă se dorește o configurație "portabilă", toate aceste componente se instalează în același path de bază sau pe un Virtual Hard Disk, asigurând configurările necesare astfel încât toate componentele să ruleze în modul "portabil", folosind pathuri relative, respectiv orice legătură cu sistemul de operare cu privire la path-uri sau variabile de sistem trebuind înlăturată.

  3. Implementarea unei biblioteci noi folosind facilitatea Remote Library din Robot Framework, cu Jython, ceea ce presupune în principiu crearea unei clase în Python, de exemplu
class SikuliRemoteLib(BaseLogger):
    def __init__(self):
        self.appRegion=Region()
    ..
    def click_object(self,img,offsetX=0,offsetY=0):
        self._find_object(img,offsetX,offsetY)
        self.appRegion.click(self.appPattern)
    ... 

care va conține toate keywordurile necesare a fi apelate din Robot Framework, sub forma unor funcții care să apeleze funcțiile din SikuliX prin intermediul jython, și apoi instanțierea acestei clase în main:

if __name__ == '__main__':
    import sys
    from robotremoteserver import RobotRemoteServer

    RobotRemoteServer(SikuliRemoteLib(), 
    *sys.argv[1:])

Moștenirea din BaseLogger permite în plus personalizarea logurilor, pentru ca acestea să conțină atât imaginea de referință cât și imaginea reală cu care se compară, pentru mai multă siguranță la verificarea rezultatelor execuției testelor, cât și pentru corectarea ulterioară a unor imagini de referință.

4.Serverele SikuliX și Selenium se pot porni în mod automat din Robot Framework, folosind fișierul special init.robot, care poate conține următoarele linii de cod:

Resource        ${CURDIR}/Common/sikuliremote.robot
Suite Setup     Start And Import Remote Library  SikuliRemoteLib/sikuliremotelib.py
Suite Teardown  Stop Remote Library  ${True}

Iar Start And Import Remote Library conține codul prin care se pornește SikuliX prin procesul java jython.jar, precum și Selenium, de exemplu pentru chromedriver.

Mai multe detalii pentru această procedură se pot explora în documentația Robot Framework precum și direct în codul sursă de pe Git.

Având toată această arhitectură integrată, nu ne rămâne decât să creăm proiectul final, structurat pe module în funcție de specificul aplicației, să decidem locația imaginilor de referință și să realizăm primul fișier de tipul robot cu primele teste.

Presupunând că dorim să implementam un test de regresie pentru profilul de utilizator Facebook, instrucțiunile de testare, folosind Visual Studio cu Selenium, ar fi următoarele:

[Test]
public void FbTest()
{
    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

    driver.Navigate().GoToUrl(
      "https://www.facebook.com");
    // 1. Assume new browser profile, 
    // thus logon required all the time

    wait.Until(ExpectedConditions.
       ElementIsVisible(By.Id("email")));
    // hardcoded here for demo only, otherwise would 
    // call a keyword that will use KeePass instead

    driver.FindElement(By.Id("email")) 
      .SendKeys("username");

    driver.FindElement(By.Id("pass"))
      .SendKeys("password");
    driver.FindElement(By.Id("loginbutton")).Click();

    // 2. Close notification dialog if appearing
    IWebElement element = IsElementPresent(
       By.XPath(
    "//*[@aria-labelledby='notification-permission-title']//a"));
    if (element != null)
        element.Click();

    // 3. Check if FB logo and search field are displayed correctly
    driver.FindElement(By.XPath(
       "//*[@data-testid='blue_bar_fb_logo']"));
    driver.FindElement(By.XPath(
       "//*[@data-testid='search_input']"));

    // 4. Click on user name to display user profile
    driver.FindElement(By.XPath(
       "//*[@id='u_0_4']/div[1]/div[1]/div/a/span"))
        .Click();
    // Check the Profile Picture element exists
    driver.FindElement(By.XPath(
       "//*[@class='profilePicThumb']"));

    // 5. Check the tabs Timeline, 
    // Friends and Photos exist
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='timeline']"));
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='friends']"));
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='photos']"));

    // 6. Check the tab More exists, 
    // click it in order to activate popup items
    driver.FindElement(By.XPath(
       "//*[@id='fbProfileCover']/div[2]/div[2]/ul/
        li[5]/div/a")).Click();

    // Check if the popup items exist
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='map']"));
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='sports']"));
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='books']"));
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='likes']"));
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='events']"));
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='fitness']"));
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='reviews']"));
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='groups']"));
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='notes']"));

    // 7. Check and click on About tab
    driver.FindElement(By.XPath(
       "//*[@data-tab-key='about']")).Click();
    // Check if the About menu is displayed correctly
    driver.FindElement(By.XPath(
       "//*[@id='medley_header_about']/a"));

    // Several checks still missing, e.g. is the 
    // About tab selected and with black color while 
    // the other tabs are blue?
    // Or, are the menu items displayed correctly in 
    // English language?
    // ...

Instrucțiunile în limbaj Robot Framework, ar fi următoarele:

Basic FB check
  [Documentation]   Test Fb login, profile picture, main tabs and click on About tab
  [Tags]  Warmup  Fb
  go to   https://www.facebook.com

  # 1. Assume new browser profile, thus logon required 
  # all the time
  wait until element is visible   id=email

  # hardcoded here for demo only, otherwise would 
  # call a keyword that will use KeePass instead
  press key           id=email  username
  press key           id=pass   password
  click button        //*[@id='loginbutton']/input

  # 2. Close notification dialog if appearing
  Run Keyword And Ignore Error click element    
  //*[@aria-labelledby=
  // 'notification-permission-title']//a

  # "T01-1 fb logo and search" and upcoming are .PNG 
  # files, taken as reference images on a very specific 
  # region
  # The next used keywords are Python functions 
  # implemented in SikuliRemoteLib, that in turn are 
  # calling SikuliX methods for finding and executing   
  # actions on images, then logging the results.
  # The numbers are x, y click coordinates, exactly 
  # as seen e.g. on Paint application.

  # 3. Check if FB logo and search field are displayed 
  # correctly
  wait for object     T01-1 fb logo and search

  # 4. Click on user name to display user profile
  verify and click object  T01-2 main controls   
    ${-20}  ${18}

  # Check the Profile Picture element exists
  wait until element is visible   //*[@class='profilePicThumb']

  # 6. Check the tab More exists, hover mouse over it 
  # in order to activate popup items
  hover over object        T01-3 timeline tab   
    ${382}  ${18}

  # Check if the popup items exist
  verify object            T01-4 more popup menu
  hover mouse right        ${100}

  # 5. Check the tabs Timeline, Friends and Photos 
  # elements exist
  # 7. Check and click on About tab
  verify and click object  T01-3 timeline tab   
    ${116}  ${18}

  # check the About tab is displayed correctly
  verify object            T01-5 about tab
  # Check if the About menu is displayed correctly
  verify object            T01-6 about menu displayed

  # No more checks are missing for this basic test. 
  # About tab is selected correctly and with the 
  # correct colors displayed
  # All menu items are displayed correctly in 
  # English language, as in the reference image

După cum se poate vedea mai sus, instrucțiunile în Robot Framework sunt mult mai elegante și mai naturale, implementarea unui caz de testare fiind mult mai accesibilă chiar și pentru un inginer de testare fără experiență în programare pentru că logica acestor teste urmărește destul de aproape pașii din testul manual, spre deosebire de implementarea în C# și Selenium, unde cunoștințele de programare sunt obligatorii. Mai mult decât atât, timpul de scriere al unui caz de testare automat, relativ complex, este mult mai mic atunci când se folosește testarea automată bazată pe recunoașterea imaginilor, de exemplu, cu SikuliX, decât atunci când se folosește recunoașterea elementelor ascunse în pagina web ca în cazul Selenium. Concret, dacă un caz de testare în Selenium cu Visual Studio ar necesita 10 "man days", același caz de testare cu arhitectura prezentată mai sus poate fi finalizat cel mult în 1 "man day", deci de 10 ori mai repede sau cu 10% din resurse.

În concluzie, indiferent dacă criteriile de alegere a unei soluții de testare automată pun costul soluției pe un loc principal sau secundar, atunci când suntem dispuși să renunțam la varianta evidentă, populară, comercială și care beneficiază de marketing din plin și decidem să acordăm o șansă soluțiilor alternative, putem avea surpriza să obținem o soluție de testare automată nu doar gratuită, ci una cu mult mai puternică, mai elegantă și mai flexibilă pentru proiectul software care urmează a fi testat automat, atât în beneficiul membrilor echipei care vor lucra în acel proiect, cât mai ales în beneficiul clientului final al cărui produs software urmează a fi testat.

LANSAREA NUMĂRULUI 79, CLUJ

Prezentări articole și
Panel: Smart Technology

Luni, 21 Ianuarie, ora 18:00
clădirea Casino, Parcul Mare

Înregistrează-te

Facebook Meetup

Sponsori

  • ntt data
  • 3PillarGlobal
  • Betfair
  • Telenav
  • Accenture
  • Siemens
  • Bosch
  • FlowTraders
  • MHP
  • BCR
  • Itiviti
  • Connatix
  • UIPatj
  • MicroFocus
  • Colors in projects