Arta testării layout-ului cu Galen Framework

Publicat: 2022-03-10
Rezumat rapid ↬ Când proiectați o interfață grafică cu utilizatorul, există întotdeauna o întrebare deschisă: Cum automatizăm testarea pentru aceasta? Și cum ne asigurăm că aspectul site-ului web rămâne receptiv și se afișează corect pe toate tipurile de dispozitive cu diferite rezoluții? Adăugați la aceasta complicațiile care decurg din conținutul dinamic, cerințele de internaționalizare și localizare și devine o adevărată provocare. În acest articol, vă voi ghida printr-o nouă tehnică interesantă de testare a aspectului. Folosind Galen Framework , voi oferi un tutorial detaliat pentru scrierea unor teste de aspect generalizate semnificative, care pot fi executate în orice browser și pe orice dispozitiv și, în același timp, utilizate ca o singură sursă de adevăr în documentația de proiectare.

Când proiectăm o interfață grafică cu utilizatorul, există întotdeauna o întrebare deschisă: Cum automatizăm testarea pentru aceasta? Și cum ne asigurăm că aspectul site-ului web rămâne receptiv și se afișează corect pe toate tipurile de dispozitive cu diferite rezoluții? Adăugați la aceasta complicațiile care decurg din conținutul dinamic, cerințele de internaționalizare și localizare și devine o adevărată provocare.

În acest articol, vă voi ghida printr-o nouă tehnică interesantă de testare a aspectului. Folosind Galen Framework, voi oferi un tutorial detaliat pentru scrierea unor teste de aspect generalizate semnificative, care pot fi executate în orice browser și pe orice dispozitiv și, în același timp, utilizate ca o singură sursă de adevăr în documentația de proiectare.

Citiți suplimentare despre SmashingMag:

  • Dezvoltare vizuală bazată pe teste pentru proiectarea interfeței receptive
  • Elementele de bază ale automatizării testelor pentru aplicații, jocuri și web mobil
  • Cadre diverse de testare-automatizare pentru aplicațiile native React

De asemenea, voi demonstra cum am venit cu un test optimizat pentru o pagină de mesagerie pe site-ul nostru de anunțuri, Marktplaats. Vom învăța cum să extindem sintaxa lui Galen cu propriul nostru limbaj, cum să îmbunătățim codul de testare și cum să transformăm o rutină de testare a aspectului în artă.

Mai multe după săritură! Continuați să citiți mai jos ↓

Introducere în cadrul Galen

Galen Framework a fost tratat acum un an în „Dezvoltarea vizuală bazată pe teste pentru proiectarea interfeței receptive”. La acea vreme, sintaxa sa era limitată. S-a îmbunătățit mult de atunci și a primit multe funcții noi, pe care le vom analiza aici.

În cazul în care nu sunteți familiarizat cu Galen Framework, acesta este un instrument pentru testarea aspectului receptiv și între browsere și testarea funcțională, cu propriul limbaj de testare, numit Galen Specs. Se bazează pe Selenium WebDriver și are, de asemenea, un API JavaScript bogat care vă permite să lucrați direct cu WebDriver. Pentru că aveți control asupra WebDriver, puteți rula teste în orice browser, în cloud (SauceLabs, BrowserStack, PerfectoMobile etc.) sau pe dispozitive mobile reale folosind Appium.

Instalare și Execuție

Configurarea Galen Framework este ușoară. Pur și simplu executați următoarea comandă pentru a o instala prin npm:

 npm install -g galenframework-cli

Dacă nu utilizați npm, descărcați cea mai recentă arhivă Galen Framework, extrageți pachetul și urmați instrucțiunile de instalare.

Odată instalat, Galen Framework poate fi lansat în diferite moduri. De exemplu, puteți utiliza comanda check pentru a lansa un test rapid al unei singure pagini. Pentru această comandă, trebuie să furnizați un fișier .gspec cu validările de aspect și apoi îl puteți invoca astfel:

 galen check loginPage.gspec --url https://example.com --size 1024x768 --include desktop --htmlreport reports

Această comandă va lansa un browser, va deschide adresa URL specificată, va redimensiona fereastra browserului la 1024 × 768 pixeli și va executa toate validările declarate în fișierul loginPage.gspec . Ca rezultat, veți obține un raport HTML detaliat.

Gestionarea suitelor de testare

În lumea reală, o aplicație web reală nu constă doar din pagini statice. Destul de des va trebui să efectuați unele acțiuni pentru a ajunge la locul pe care doriți să îl verificați. În acest caz, Galen oferă suite de testare JavaScript și API-ul JavaScript GalenPages pentru implementarea modelului obiect al paginii. Iată un exemplu simplu de test JavaScript Galen:

 test("Home page", function() { var driver = createDriver("https://galenframework.com", "1024x768"); checkLayout(driver, "homePage.gspec", ["desktop"]); });

Și iată o implementare a modelului obiect de pagină pentru o pagină de logare, preluată dintr-un proiect real.

 WelcomePage = $page("Welcome page", { loginButton: "#welcome-page .button-login" }); LoginPage = $page("Login page", { username: "input[name='login.username']", password: "input[name='login.password']", loginButton: "button.button-login" loginAs: loggedFunction ("Log in as ${_1.username} with password ${_1.password}", function(user) { this.username.typeText(user.username); this.password.typeText(user.password); this.loginButton.click(); }) }); test("Login page", function() { var driver = createDriver("https://testapp.galenframework.com", "1024x768"); var welcomePage = new WelcomePage(driver).waitForIt(); welcomePage.loginButton.click(); new LoginPage(driver).waitForIt(); checkLayout(driver, "loginPage.gspec", ["desktop"]); });

Pentru utilizare avansată, vă sfătuiesc să vă uitați la proiectul Galen Bootstrap. Este o extensie JavaScript creată special pentru Galen. Oferă unele funcționalități suplimentare pentru testarea UI și o modalitate mai ușoară de a configura browsere și de a executa suite de testare complexe.

Test de aspect simplu

Permiteți-mi să încep prin a introduce un test simplu de aspect în Galen Framework. Apoi, voi trece la cazuri de utilizare avansate și voi demonstra cum să extind sintaxa Galen Specs. Pentru aceasta, ne vom uita la un antet cu o pictogramă și legenda:

Pictogramă și legenda
Pictogramă și legenda (Vezi versiunea mare)

În codul HTML, ar putea arăta cam așa:

 <body> <!-- … --> <div> <img class="header-logo" src="/imgs/header-logo.png"/> <h1>My Blog</h1> </div> <!-- … --> </body>

Cea mai simplă formă a unui test de aspect Galen ar arăta cam ca următorul. În primul rând, trebuie să declarăm obiecte cu selectoare CSS.

 @objects header #header icon #header img caption #header h1

Apoi, declarăm o secțiune de testare cu un nume semnificativ și punem toate validările noastre sub ea.

 = Icon and Caption = icon: left-of caption 10 to 15px width 32px height 32px inside header 10px top caption: aligned horizontally all header inside header

Aici am testat două elemente de antet: pictograma și legenda. Toate validările enumerate sub elementele pictograme și subtitrări sunt de fapt specificații Galen standard. Aceste specificații sunt elementele fundamentale cu care vă puteți asambla propria soluție de testare a aspectului. Fiecare specificație verifică o singură proprietate (cum ar fi lățimea, înălțimea, textul), poziționarea relativă (cum ar fi interiorul, stânga, deasupra) sau pixelii din captură de ecran (cum ar fi schema de culori, imaginea).

Testarea mai multor elemente folosind buclele forEach

Exemplul anterior demonstrează un scenariu simplu. Să vedem cum putem face față unei situații mai complicate: un meniu orizontal. Mai întâi, să încercăm o tehnică simplă de testare a aspectului.

Meniu orizontal
Meniu orizontal (Vezi versiunea mare)

Începeți prin potrivirea mai multor elemente de pe pagină. Cu următorul cod, îi spunem lui Galen să caute elemente care se potrivesc cu selectorul CSS #menu ul li .

 @objects menu #menu item-* ul li

Mai târziu, ne putem referi la aceste elemente cu nume precum menu.item-1 și menu.item-2 și putem repeta peste toate elementele de meniu folosind o buclă @forEach .

 = Menu = menu.item-1: inside menu 0px top left bottom @forEach [menu.item-*] as menuItem, next as nextItem ${menuItem}: left-of ${nextItem} 0px aligned horizontally all ${nextItem}

După cum puteți vedea, chiar dacă verificarea reală nu este atât de complexă, codul a devenit deja mai puțin intuitiv. Imaginați-vă dacă am avea mai multe coduri similare în testele noastre. La un moment dat, va deveni o mizerie de neîntreținut. Ar trebui să existe o modalitate de a o îmbunătăți.

Regândirea testării aspectului

Dacă vă gândiți la exemplul anterior, se pare că am putea exprima aspectul în doar una sau două propoziții. De exemplu, am putea spune ceva de genul „Toate elementele de meniu ar trebui să fie aliniate orizontal, fără marjă între ele. Primul element de meniu ar trebui să fie situat în partea stângă a meniului, fără marjă.” Deoarece am formulat propoziții pentru a explica aspectul pe care îl dorim, de ce nu le putem folosi în codul nostru? Imaginează-ți dacă am putea scrie codul astfel:

 = Menu = |first menu.item-* is in top left corner of menu |menu.item-* are aligned horizontally next to each other

De fapt, acesta este un cod de lucru real, copiat din proiectul meu. În ultimele două rânduri (începând cu pipe, | ), invocăm funcții personalizate care își colectează argumentele prin analizarea acestor două instrucțiuni. Desigur, exemplul de mai sus nu va funcționa așa cum este. Pentru a se compila, trebuie să implementăm handlerele pentru aceste două instrucțiuni. Vom reveni la această implementare mai târziu.

Punctul cheie cu exemplul de mai sus este că testarea aspectului a trecut de la testarea bazată pe obiecte la testarea bazată pe expresie . S-ar putea să nu fie evident dintr-un astfel de exemplu minor, dar cu siguranță este vizibil la o scară mai mare. Deci, de ce este acest lucru semnificativ? Răspunsul scurt este că acest lucru ne schimbă mentalitatea și afectează modul în care ne proiectăm software-ul și scriem teste pentru acesta.

Folosind această tehnică, nu tratăm pagina noastră ca pe o grămadă de obiecte cu relații specifice între ele. Nu testăm proprietățile CSS ale elementelor individuale. Și evităm să scriem coduri complicate non-triviale. În schimb, încercăm să ne gândim la modele comune de aspect și la declarații semnificative. În loc să testăm elementul de meniu 1, elementul de meniu 2 și așa mai departe separat, aplicăm declarații generice care:

  • sunt reproductibile pe alte elemente;
  • nu conțin valori codificate de pixeli;
  • sunt aplicate abstracțiilor și nu obiectelor concrete;
  • și, nu în ultimul rând, au sens atunci când le citim.

Cum functioneaza

Permiteți-mi să explic mecanismul expresiilor de aspect personalizate folosind acest exemplu simplu:

Schiță simplă
Schiță simplă (Vezi versiunea mare)

În acest exemplu, ar trebui să verificăm dacă butonul se întinde până la panou, fără margini pe partea stângă sau dreaptă. Fără reguli personalizate, îl putem aborda în moduri diferite, dar prefer următoarea soluție:

 button: inside some_panel 0px left right

Codul de mai sus ne oferă flexibilitatea de a declara marja personalizată pe părțile laterale și, de asemenea, testează implicit că butonul este conținut complet în panou. Dezavantajul este că nu este foarte lizibil, motiv pentru care voi pune această validare în spatele button stretches to some_panel . Pentru ca asta să funcționeze, trebuie să scriem o regulă personalizată ca aceasta:

 @rule %{elementName} stretches to %{parentName} ${elementName}: inside ${parentName} 0px left right

Asta e. Acum îl putem pune în testul nostru într-o singură linie:

 | button stretches to some_panel

După cum puteți vedea, această regulă are două argumente: elementName și parentName . Acest lucru ne permite să-l aplicăm și altor elemente. Doar înlocuiți numele acestor două obiecte.

 | login_panel stretches to main_container | header stretches to screen | footer stretches to screen # etc.

Implementarea propriului limbaj de testare

Să revenim la exemplele inițiale de expresii de aspect pentru meniul orizontal.

 = Menu = | first menu.item-* is in top left corner of menu | menu.item-* are aligned horizontally next to each other

Putem implementa prima regulă în felul următor:

 @rule first %{itemPattern} is in %{cornerSides} corner of %{parentElement} @if ${count(itemPattern) > 0} ${first(itemPattern).name}: inside ${parentElement} 0px ${cornerSides}

Când este folosit în exemplul nostru, ar analiza argumentele după cum urmează:

  • itemPattern = menu.item- menu.item-*
  • cornerSides = top left
  • parentElement = menu

Pentru că am terminat cu prima noastră expresie, putem trece la următoarea. În a doua expresie, ar trebui să testăm alinierea orizontală a tuturor elementelor de meniu. Vă propun trei pași simpli:

  1. Găsiți toate elementele din meniu.
  2. Repetați peste toate până la penultimul element.
  3. Verificați dacă elementul n este situat în stânga elementului n+1 și că marginile lor de sus și de jos sunt aliniate.

Pentru ca acesta să funcționeze, trebuie să luăm o buclă @forEach și specificațiile left-of și aligned . Din fericire, în Galen vă puteți referi la articolul anterior sau următor într-o buclă. În cazul în care ați declarat o referință la următorul element, acesta va repeta doar până la penultimul element, care este exact ceea ce avem nevoie.

 @rule %{itemPattern} are aligned horizontally next to each other @forEach [${itemPattern}] as item, next as nextItem ${item}: left-of ${nextItem} 0px aligned horizontally all ${nextItem}

S-ar putea să întrebați, ce se întâmplă dacă trebuie să specificăm o marjă în testul nostru (cum ar fi ~ 20px sau 10 to 20px )? Apoi, sugerez fie implementarea unei reguli separate, fie extinderea celei existente pentru a susține un argument %{margin} .

 @rule %{itemPattern} are aligned horizontally next to each other with %{margin} margin @forEach [${itemPattern}] as item, next as nextItem ${item}: left-of ${nextItem} ${margin} aligned horizontally all ${nextItem}

Asta e! Am creat o expresie generică care ne ajută să validăm meniul orizontal. Cu toate acestea, datorită flexibilității sale, putem face mult mai mult decât atât. Îl putem folosi pentru a testa orice alte elemente de pe pagină. Îl putem folosi chiar și pentru a testa alinierea a două butoane:

Butoane de formulare
Butoane de formular (Vezi versiunea mare)
 | menu.item-* are aligned horizontally next to each other with 0px margin | submit_button, cancel_button are aligned horizontally next to each other with 20px margin

S-ar putea să observați în aceste două exemple că am declarat primul argument în două moduri diferite. În prima expresie, primul argument este “menu.item-*” , iar în a doua expresie este declarat “submit_button, cancel_button” . Acest lucru este posibil deoarece bucla @forEach ne permite să folosim o listă de obiecte separate prin virgulă împreună cu operatorul stea. Dar încă nu am terminat cu refactorizarea. Am putea îmbunătăți în continuare codul și să-l facem mai lizibil. Dacă creăm grupuri pentru elementele de meniu și butoanele formularului de autentificare, am putea realiza ceva de genul acesta:

 @groups menu_items menu_item-* login_form_buttons submit_button, cancel_button = Testing login page = | &menu_items are aligned horizontally next to each other with 0px margin | &login_form_buttons are aligned horizontally next to each other with 20px margin

În acest caz, trebuie să folosim simbolul & , care reprezintă o declarație de grup. Acesta este deja un test bun. În primul rând, pur și simplu funcționează și putem testa ceea ce avem nevoie. De asemenea, codul este clar și ușor de citit. Dacă o altă persoană te-ar întreba cum ar trebui să arate pagina de conectare și care sunt cerințele de proiectare, ai putea să îi spui să se uite la test.

După cum puteți vedea, implementarea expresiilor personalizate pentru modele de aspect complexe nu este cu adevărat o mare problemă. Ar putea fi o provocare la început, dar seamănă totuși cu o activitate creativă.

Marje dinamice

Să ne uităm la un alt model de aspect rar pe care l-ați putea găsi uneori pe diferite site-uri web. Ce se întâmplă dacă am vrea să testăm că elementele au o distanță egală între ele? Să încercăm să implementăm o altă regulă pentru asta, dar de data aceasta folosind o implementare JavaScript. Propun o astfel de afirmație: “box_item-* are aligned horizontally next to each other with equal distance” . Acest lucru va fi puțin complicat pentru că nu cunoaștem marja dintre elemente și nu putem doar codifica valorile pixelilor. Prin urmare, primul lucru pe care trebuie să-l facem este să recuperăm marja reală dintre primul și ultimul element.

La fel de distant
La fel de îndepărtat (Vezi versiunea mare)

Odată ce obținem acea marjă, o putem declara într-o buclă @forEach similară cu cum am făcut-o înainte. Propun implementarea acestei reguli folosind API-ul JavaScript, deoarece logica necesară este puțin mai complexă decât în ​​toate exemplele noastre anterioare. Să creăm un fișier numit my-rules.js și să introducem acest cod:

 rule("%{objectPattern} are aligned horizontally next to each other with equal margin", function (objectName, parameters) { var allItems = findAll(parameters.objectPattern), distance = Math.round(Math.abs(allItems[1].left() - allItems[0].right())), expectedMargin = (distance - 1) + " to " + (distance + 1) + "px"; if (allItems.length > 0) { for (var i = 0; i < allItems.length - 1; i += 1) { var nextElementName = allItems[i + 1].name; this.addObjectSpecs(allItems[i].name, [ "aligned horizontally all " + nextElementName, "left-of " + nextElementName + " " + expectedMargin ]); } } });

În codul nostru de testare, îl vom folosi astfel:

 @script my-rules.js # … = Boxes = | box_item-* are aligned horizontally next to each other with equal distance

După cum puteți vedea, în Galen Framework putem alege între două limbi atunci când implementăm reguli: Galen Specs și JavaScript. Pentru expresiile simple, Galen Specs este mai ușor de folosit, dar pentru cele complexe aleg întotdeauna JavaScript. Dacă doriți să aflați mai multe despre regulile JavaScript, consultați documentația.

Galen Extra

După ce m-am jucat suficient cu diferite modele de aspect, mi-am dat seama că toate aceste reguli Galen ar putea fi aplicate cu ușurință în orice alt proiect de testare. Asta mi-a dat o idee de a compila cele mai comune expresii de aspect în propria bibliotecă. Așa am ajuns să creez proiectul Galen Extras. Mai jos sunt câteva exemple de ceea ce este capabilă această bibliotecă:

 | header.icon should be squared | amount of &menu_items should be > 3 | &menu_items are aligned horizontally next to each other | &list_items are aligned vertically above each other with equal distance | every &menu_item is inside menu 0px top and has width > 50px | first &menu_item is inside menu 0px top left | &menu_items are rendered in 2 column table | &menu_items are rendered in 2 column table, with 0 to 1px vertical and 10px horizontal margin | &login_form_elements sides are vertically inside content_container with 20px margin login_panel: | located on the left side of panel and takes 70 % of its width # etc …

Biblioteca Galen Extras conține multe dintre modelele de aspect pe care le-ați găsi în mod obișnuit pe site-uri web și o actualizez în continuare de îndată ce descopăr un model util. Odată ce această bibliotecă a fost înființată, am decis să o încerc pe un proiect de testare real.

Testarea aplicației de mesagerie

În prezent, lucrez ca inginer software la Marktplaats. La un moment dat, am decis să aplic toată experiența acumulată într-un proiect real. Trebuia să testez pagina de mesagerie de pe site-ul nostru. Iată cum arată:

Pagina de mesagerie
Pagina de mesagerie (Vezi versiunea mare)

Sincer să fiu, implementarea testelor pentru astfel de pagini mi s-a părut întotdeauna puțin înfricoșătoare, în special testele de layout. Dar, cu biblioteca Galen Extras, a mers destul de bine și în curând am reușit să vin cu acest cod:

 @import ../selected-conversation.gspec @groups (message, messages) messenger.message-* first_two_messages messenger.message-1,messenger.message-2 first_message messenger.message-1 second_message messenger.message-2 third_message messenger.message-3 (message_date_label, message_date_labels) messenger.date_label-* first_date_label messenger.date_label-1 second_date_label messenger.date_label-2 = Messages panel = = Messages and Date labels = |amount of visible &message_date_labels should be 1 |first &message_date_label has text is "17 november 2015" |amount of visible &messages should be 3 |&first_two_messages should be located at the left inside messenger with ~ 20px margin |&third_message should be located at the right inside messenger with ~ 20px margin |&messages are placed above each other with 10 to 15px margin |text of all &messages should be ["Hi there!", "I want to buy something", "Hello! Sure, it's gonna be 100 euros"] = Styling = |&first_two_messages should be styled as others message |&third_message should be styled as own message

Extragerea intervalelor de pixeli

Testul a arătat OK: a fost compact și lizibil, dar încă departe de a fi perfect. Nu mi-au plăcut foarte mult toate aceste definiții ale marjelor ( ~ 20px , 10 to 15px ). Unele dintre ele s-au repetat și a fost greu de înțeles ce reprezintă fiecare dintre ele. De aceea am decis să ascund fiecare marjă în spatele unei variabile semnificative.

 # ... @set messages_side_margin ~ 20px messages_vertical_margin 10 to 15px = Messages panel = = Messages and Date labels = |amount of visible &message_date_labels should be 1 |first &message_date_label has text is "17 november 2015" |amount of visible &messages should be 3 |&first_two_messages should be located at the left inside messenger with ${messages_side_margin} margin |&third_message should be located at the right inside messenger with ${messages_side_margin} margin |&messages are placed above each other with ${messages_vertical_margin} margin # ...

După cum puteți vedea, am mutat marginile în messages_vertical_margin și messages_side_margin . De asemenea, am declarat o marjă minimal , care este un interval între 0 și 1 pixel.

 # ... @set minimal 0 to 1px = Conversations Panel = | &conversations are aligned above each other with ${minimal} margin # ...

Validare bazată pe imagini și expresii personalizate

După ce am acoperit poziționarea tuturor elementelor principale pe pagină, am decis să testez și stilul. Am vrut să validez că fiecare mesaj are o culoare de fundal specifică rolului utilizatorului. Când utilizatorii sunt autentificați, mesajele vor avea un fundal albastru deschis. Mesajele pentru alți utilizatori ar avea un fundal alb. În cazul în care un mesaj nu a fost trimis, alerta de eroare va avea un fundal roz. Iată regula care m-a ajutat să validez aceste stiluri:

 @set OWN_MESSAGE_COLOR #E1E8F5 OTHERS_MESSAGE_COLOR white ERROR_MESSAGE_COLOR #FFE6E6 @rule %{item} should be styled as %{style} message ${item}: @if ${style === "own"} color-scheme > 60% ${OWN_MESSAGE_COLOR}, 0.2 to 20 % ${MAJOR_TEXT_MESSAGE_COLOR} @elseif ${style === "error"} color-scheme > 60% ${ERROR_MESSAGE_COLOR}, 0.2 to 20 % ${MAJOR_TEXT_MESSAGE_COLOR} @else color-scheme > 60% ${OTHERS_MESSAGE_COLOR}, 0.2 to 20 % ${MAJOR_TEXT_MESSAGE_COLOR}

Specificația color-scheme verifică distribuția proporțională a culorilor în cadrul unui element. Decupează o captură de ecran a paginii și analizează distribuția culorilor. Deci, pentru a verifica culoarea de fundal a unui element, verificăm doar dacă distribuția acestuia este mai mare de 60% din gama totală de culori. În test, această regulă este invocată astfel:

 = Styling = |&first_two_messages should be styled as others message |&third_message should be styled as own message

Configurarea suitelor de testare

Aplicația de mesagerie este o aplicație dinamică care funcționează împreună cu API-ul RESTful Messaging. Prin urmare, pentru a-și testa aspectul în toate stările diferite, trebuie să pregătim datele de testare. Am decis să machez API-ul de mesagerie, astfel încât să pot configura toate mesajele mele de testare în suita de teste. Iată un fragment din suita mea de teste care arată cum sunt structurate testele noastre.

 // ... testOnAllDevices("Unselected 2 conversations", "/", function (driver, device) { mock.onGetMyConversationsReturn(sampleConversations); refresh(driver); new MessageAppPage(driver).waitForIt(); checkLayout(driver, "specs/tests/unselected-conversations.gspec", device.tags); }); testOnAllDevices("When clicking a conversation it should reveal messages", "/", function (driver, device) { mock.onGetMyConversationsReturn(sampleConversations); mock.onGetSingleConversationReturn(sampleMessages); refresh(driver); var page = new MessageAppPage(driver).waitForIt(); page.clickFirstConversation(); checkLayout({ driver: driver, spec: "specs/tests/three-simple-messages-test.gspec", tags: device.tags, vars: { expectedTextProvider: textProvider({ "messenger.message-1": "Hi there!\n11:02", "messenger.message-2": "I want to buy something\n12:02", "messenger.message-3": "Hello! Sure, it's gonna be 100 euros\n13:02" }) } }); }); // ...

Prinderea insectelor

Implementarea acestor expresii simple are rezultate destul de repede. Să trecem peste ce fel de erori putem prinde cu suita noastră de teste.

Problemă de stil

Iată un exemplu de când ceva nu merge bine în baza noastră de cod CSS și, ca rezultat, toate mesajele sunt redate cu același fundal.

Culoarea de fundal a mesajului este greșită
Culoarea de fundal a mesajului greșită (Vezi versiunea mare)

Dacă comparați această captură de ecran cu cea originală, veți observa că ultimul mesaj are un fundal alb, în ​​timp ce ar trebui să fie albastru deschis. Să vedem cum raportează Galen această problemă:

Captură de ecran cu mesaj de eroare
Captură de ecran cu mesaj de eroare (Vezi versiunea mare)

Pentru obiectul evidențiat, afișează color #e1e8f5 on “messenger.message-3” is 0% but it should be greater than 60% . Pentru a fi sincer, acest mesaj de eroare nu pare chiar atât de clar, dar deoarece această verificare a fost generată dintr-o regulă personalizată, putem oricând să căutăm numele său original într-o ramură de raport:

Raportarea eșecului testului
Raportarea eșecului testului (Vedeți versiunea mare)

Dacă derulați în sus, veți vedea că declarația inițială este &third_message should be styled as own message . Acesta este un alt beneficiu al utilizării expresiilor personalizate: vă ajută să înțelegeți eșecul și să descrieți frumos toate validările generate.

Problemă de poziționare

Iată un alt exemplu de situație în care aspectul merge prost din cauza alinierii incorecte a unui element. În următoarea captură de ecran, puteți vedea că ultimul mesaj este poziționat în partea stângă a ferestrei de vizualizare a mesajelor, în loc de dreapta.

Poziția greșită a mesajului
Poziția greșită a mesajului (Vezi versiunea mare)

Să ne uităm din nou la captura de ecran cu mesajul de eroare:

Poziția greșită a mesajului
Poziția greșită a mesajului (Vezi versiunea mare)

Captura de ecran evidențiază containerul de mesaje și ultimul element de mesaj. Împreună cu asta, arată următorul mesaj de eroare: “messenger.message-3” is 285px right which is not in range of 22 to 28px . S-ar putea să nu fie clar pentru un dezvoltator web de ce este așteptată o marjă de 22 până la 28 de pixeli în partea dreaptă. Din nou, va trebui să căutați o declarație de validare în ramura de raport:

Poziția greșită a mesajului
Poziția greșită a mesajului (Vezi versiunea mare)

Declarația inițială pentru acea verificare este &third_message should be located at the right inside messenger with ~ 25px margin . Asta are mult mai mult sens. Mai mult, alți ingineri front-end vor înțelege acest raport de testare, chiar dacă nu au scris testele.

Ghid de testare a aspectului

Având în vedere toate aceste experimente diferite, am decis să oficializez toate învățarea în linii directoare generale de testare a aspectului. Iată o listă de verificare rapidă cu pașii de urmat pentru a vă ușura rutina de testare.

  • Identificați modele de aspect în design.
  • Generalizați declarațiile de validare. Încercați să condensați majoritatea validărilor în propoziții simple.
  • Componentați! Este întotdeauna mai bine să mutați testele elementelor repetate în componente dedicate.
  • Folosiți nume semnificative pentru secțiuni, reguli și obiecte.
  • Evitați pixelii. Încercați să înlocuiți valorile pixelilor (fie valori exacte sau intervale) cu variabile semnificative.
  • Ajustați codul site-ului dvs. pentru a facilita testarea. Acest lucru vă va ajuta să structurați și să vă mențineți atât codul de producție, cât și codul de testare.

Criterii de acceptare pentru salvare

Adesea primesc întrebări de genul „Deci cât de detaliat ar trebui să fie un test de aspect? Și ce ar trebui să testăm în mod specific?” Un răspuns general este greu de dat. Problema este că atunci când acoperirea testului este mică, scapi de erori. Pe de altă parte, dacă aveți teste prea detaliate, este posibil să obțineți o mulțime de rezultate false pozitive, iar în viitor s-ar putea să vă pierdeți în întreținerea testelor. Deci, există un compromis. Dar mi-am dat seama de un ghid general pentru mine. Dacă împărțiți munca în povești mai mici de utilizator, atunci devine mai ușor să structurați designul unei pagini sub forma unor criterii de acceptare. În cele din urmă, s-ar putea să puneți chiar aceste criterii de acceptare chiar în codul dvs. de testare. De exemplu, unele dintre aceste instrucțiuni ar putea fi definite sub formă de reguli personalizate, așa cum se arată în toate exemplele de cod anterioare. Un bun exemplu de criterii de acceptare ar fi ceva de genul acesta:

  • Ferestrele pop-up trebuie să fie centrate vertical și orizontal pe ecran.
  • Ar trebui să aibă o lățime de 400 de pixeli.
  • Butoanele trebuie aliniate orizontal.
  • Și așa mai departe

Odată ce descrieți designul în propoziții simple, devine mai ușor să le convertiți în declarații reutilizabile și să vă organizați codul de testare.

Concluzie

După cum puteți vedea, un astfel de exercițiu vă ajută să structurați un design și să descoperiți modele generale de aspect care pot fi partajate între mai multe componente ale paginii. Chiar dacă pagina este complexă și constă dintr-o mulțime de elemente, puteți găsi întotdeauna o modalitate de a le grupa în expresiile dvs. de aspect. Cu această abordare, testarea aspectului devine mai mult un instrument pentru dezvoltarea bazată pe teste, ajutându-vă să proiectați, să implementați și să furnizați software în mod incremental, ceea ce este util în special într-un mediu agil.

Resurse

  • Galen Framework (site-ul oficial)
  • Galen Framework, GitHub
  • Galen Extras (biblioteca), GitHub
  • Galen Bootstrap, GitHub
  • „Tutoriale Galen Framework”, YouTube