Visualception
VisualCeption - testy regresji wyglądu Twojej strony z wykorzystaniem docker-console

Czy zdarza się Wam, że przeglądając stronę nie jesteście pewni czy dana czcionka miała 12 czy 13 pikseli, a może ten obrazek był troszeczkę bardziej w lewo? Jeżeli wygląd na Waszej stronie to sprawa priorytetowa, to może warto pomyśleć nad automatycznym sprawdzaniem tego aspektu Waszego projektu. Rozwiązaniem, na które warto zwrócić uwagę jest VisualCeption. W tym artykule pokażemy Wam, jak można w łatwy sposób uruchomić ten dodatek na projekcie zbudowanym z docker-console. Tak jak poprzednio, nasze przykłady będą bazowały na projekcie, który znacie już z wcześniejszych wpisów.

Jak to działa?

VisualCeption, przy pierwszym uruchomieniu, wykonuje “wzorcowy” zrzut ekranu danej strony lub listy elementów, jakie podaliśmy w teście. Następnie przy kolejnym uruchomieniu testu tworzone są nowe (aktualne) zrzuty ekranu i porównywane są one z wcześniejszą wersją (dlatego przy pierwszym uruchomieniu testu zawsze zwróci on wynik pozytywny, gdyż nie będzie posiadał plików bazowych z którymi mógłby porównać obecny stan strony). Wynikiem takiego porównania jest procentowa różnica pomiędzy dwoma obrazami i zwrócony przez test plik zaznaczający gdzie dane różnice wystąpiły. Teraz może się to wydać nie do końca oczywiste, ale mam nadzieję, że gdy dotrzecie do końca artykułu wszystko będzie już jasne. Dlatego bez większej zwłoki przejdźmy do konfiguracji.

Nowy zestaw testów

Ponieważ ten typ testów wykonuje się dość wolno, to wydaje się nam, że rozsądniej będzie założyć nowy suite, aby nie spowalniać pozostałych testów oraz zachować lepszą kontrolę nad nimi. W tym celu w naszej konsoli (znajdując się w katalogu z projektem) wpisujemy:

dcon codecept generate:suite visual

Po uruchomieniu tej komendy w naszym projekcie automatycznie wygenerują się pliki niezbędne do uruchomienia testów w nowym suite (najprawdopodobniej będziemy chcieli zmienić uprawnienia/właściciela plików ponieważ wygenerują się pliki roota)

Zaznaczenie_931.png

Instalacja

Jeżeli wejdziemy na link do projektu (https://github.com/Codeception/VisualCeption) zauważymy, że konieczne jest dodanie VisualCeption do pliku composer.json. Jednak jeżeli korzystasz z aplikacji docker-console możesz pominąć ten krok. Upewnij się jedynie, że na swoim komputerze masz zainstalowany Imagick (https://www.imagemagick.org/script/index.php), który wykorzystywany jest do porównywania zrzutów ekranu. Teraz pora odblokować moduł w pliku visual.suite.yml. Musimy tu uwzględnić także Webdrivera (ponieważ jest on wykorzystywany do obsługi przeglądarki) tak więc Wasz plik konfiguracyjny powinien wyglądać podobnie jak ten zaprezentowany poniżej.

Zaznaczenie_930.png

W konfiguracji VisualCeption możemy ustawić następujące parametry:

  • referenceImageDir - VisualCeption przechowuje wcześniejsze zrzuty ekranu, aby mieć z czym porównywać obecny stan strony, domyślnie w tests/_data tworzony jest nowy katalog o nazwie 'VisualCeption'
  • currentImageDir - przy każdym kolejnym wykonaniu testu tworzone są zrzuty ekranu, które porównywane są z bazowymi, domyślnie znajdują się one w tests/_output/debug/visual/
  • maximumDeviation - podczas porównywania zrzutów ekranu wyliczana jest procentowa różnica pomiędzy obrazkami i w tym właśnie parametrze podajemy jak duża wartość jest akceptowalna (nie powinna zwrócić błędu). Domyślnie jest to wartość 0, czyli każda, nawet najmniejsza zmiana zwróci błąd testu
  • saveCurrentImageIfFailure - jeżeli tą wartość ustawimy na true, to w przypadku wystąpienia niepowodzenia w teście obecny stan ekranu zostanie zapisany w pliku z przedrostkiem "current."
  • report - domyślnie opcja ta jest ustawiona na false, jednak kiedy ją odblokujemy, wystąpienie niepowodzenia w teście wygeneruje nam raport HTML w pliku tests/_output/vcresult.html. (Jego wygląd zaprezentujemy później.)
  • module - ustawienie to określa jaki moduł jest odpowiedzialny za interakcję z przeglądarką. Domyślnie jest to WebDriver.

Chrome vs Firefox

Jak wcześniej mogliście zauważyć, podczas wykonywania testów z wykorzystaniem Webdrivera używaliśmy przeglądarki Chrome. Jednak w tym wypadku twórcy modułu VisualCeption zalecają używanie przeglądarki Firefox, ponieważ Chrome nie pozwala na zrobienie zrzutu ekranu całej stronie, a jedynie ogranicza się do części widzianej na ekranie. Na ten moment Firefox również działa w ten sposób, więc informacja ta odnosi się do Selenium 2. Domyślnie jest wykonywany zrzut widocznej strony, ale dla Firefoxa istnieje możliwość, jak to zostanie zaprezentowane w późniejszym przykładzie, zrobienia screena całego elementu nawet wówczas, kiedy jest on większy niż ekran użytkownika. 

Wykorzystajmy to zalecenie do przedstawienia jak używać Firefoxa w naszych testach. Dodatkowo, taka konfiguracja pokaże pełne możliwości tego modułu, ale oczywiście możecie poeksperymentować z innymi wersjami Selenium oraz przeglądarek.

Jeżeli w naszym projekcie chcemy jako domyślnej przeglądarki używać Firefoxa, musimy w tym celu inaczej skonfigurować nasze środowisko. Po pierwsze, w pliku dc_settings.py, znajdującym się w katalogu docker_console, powinniśmy zmienić obraz Selenium jaki jest używany w testach.

Zaznaczenie_929.png
 Linijkę 'selenium_image': ('selenium/standalone-chrome', None), należy zamienić na 'selenium_image': ('selenium/standalone-firefox:2.53.1', None), (o tym jak skonfigurować projekt tak, żeby móc używać kilku obrazów selenium, napiszemy w innym artykule.)

Teraz, kiedy mamy już dostępny obraz Selenium z Firefoxem, musimy jeszcze zmienić przeglądarkę w plikach konfiguracyjnych zestawów testów, które korzystają z Webdrivera. W naszym przypadku będzie to visual.suite.yml oraz js_capable.suite.yml

W tym wypadku Wasze testy będą uruchamiane z wykorzystaniem przeglądarki Firefox. Po takiej zmianie koniecznie sprawdź, czy wcześniej napisane testy dalej poprawnie działają, gdyż może okazać się, że zmiana wymaga również poprawienia kodu testów (na nasze szczęście w przykładowym projekcie wszystko uruchomiło się bez problemów).

Użycie w testach

Użycie tego modułu w testach jest bardzo proste, ponieważ jego główne działania opierają się o dwie dodatkowe funkcje:

  • seeVisualChanges, która zwraca błąd, jeśli nie zostanie znaleziona żadna różnica na stronie
  • dontSeeVisualChanges - zwracany jest błąd, jeżeli na stronie są widoczne jakieś zmiany

Obydwie z tych funkcji możemy używać z różnymi parametrami, aby lepiej określić to, co chcemy na danej stronie sprawdzać.

Dlatego też, jeżeli chcemy sprawdzić czy zmian nie ma na stronie widocznej na ekranie użytkownika to napiszemy test podobny do tego :

 public function page(VisualTester $I) {
 	$I->wantTo('Test - compare homepage');
 	$I->amOnPage('/');
 	$I->dontSeeVisualChanges("homepage");
 }

W którym to parametr “homepage” będzie unikalną nazwą dla screena stworzonego w tym pliku, dzięki któremu VisualCeption będzie wiedział, jakie pliki należy ze sobą porównywać. Po wykonaniu testu otrzymamy screen podobny do tego przedstawionego poniżej:

 

Jeżeli natomiast chcemy wykonać zrzut całej strony, nasz test powinien wyglądać podobnie jak ten poniżej:

public function fullPage(VisualTester $I) {
 	$I->wantTo('Test - compare homepage full page');
 	$I->amOnPage('/');
 	$I->dontSeeVisualChanges("homepage-all", '#page');
 }

Został tu dodany drugi parametr, którym jest CSS selektor '#page’ będący kontenerem zawierającym całą treść na tej stronie. Różnice w obszarze, jaki będzie porównywany podczas testu, zauważymy kiedy sprawdzimy jaki zrzut ekranu został wykonany tym razem. 

Jest to, tak jak już wspominałem wcześniej, sposób na zrobienie zrzutu ekranu elementu który jest większy niż wielkość okna przeglądarki (działa to poprawnie dla przeglądarki Firefox i Selenium 2 - w pozostałych wypadkach screen będzie wyglądał podobnie jak ten powyżej).
 

Równie dobrze w ten sposób możemy śledzić zmiany w mniejszych elementach strony np. na nagłówku lub stopce.

Kolejną możliwością, jaką daje nam VisualCeption jest wykluczanie elementów, których nie chcemy śledzić na stronie. Jest to dość pomocna funkcja, jeżeli chcemy sprawdzać wygląd jakiejś strony na której pokazuje się np. losowo wybrany obrazek, który przy każdym załadowaniu strony będzie inny. Dlatego też jeżeli nasz test będzie wyglądał jak ten poniżej, na screenie nie znajdzie się blok do logowania.
 

public function notFullPage(VisualTester $I) {
 	$I->wantTo('Test - compare homepage not full page');
 	$I->amOnPage('/');
 	$I->dontSeeVisualChanges("homepage-not-all", "#page", "#block-user-login");
 }

Ostatnim parametrem, jaki możemy dodać do naszego testu jest (którego domyślna wartość została już wcześniej ustawiona w konfiguracji), jego czułość na wystąpienie zmian na stronie. Możemy tutaj zwiększyć lub zmniejszyć procentowy wskaźnik różnic na stronie, który spowoduje wystąpienie błędu podczas wykonywania testu. Takie nadpisanie konfiguracji może być pomocne kiedy np. zawsze chcemy sprawdzać, czy na stronie nic się nie zmieniło, ale na jednej z nich mamy niewielki zmienny element który jest częścią całości i nie chcemy go całkowicie wykluczać z testu. Przykładem takiego elementu może być licznik odwiedzin na stronie, który za każdym razem pokaże inną wartość, ale nie musi być z tego powodu całkowicie wykluczony. Test przedstawiony poniżej powinien zwrócić błąd dopiero wówczas kiedy zmiany obejmą więcej niż 5% strony. 

 public function deviation(VisualTester $I) {
 	$I->wantTo('Test - compare homepage deviation');
 	$I->amOnPage('/');
 	$I->dontSeeVisualChanges("homepage-deviation", "#page", "#block-user-login", 5);
 }

Raporty

Teraz, kiedy mamy już napisane kilka testów sprawdzających nam wizualne zmiany na głównej stronie, możemy przejść do uruchomienia tych testów tak, żeby wzorcowe zrzuty ekranu mogły zostać wykonane. Testy uruchamiamy tak jak wszystkie pozostałe - poleceniem ‘dcon test’ lub gdy interesuje nas tylko ten zestaw testów, poleceniem ‘dcon test visual’.

Kiedy bazowe zrzuty się wykonały, możemy zmienić coś na naszej stronie aby na własne oczy przekonać się czy nasze testy naprawdę działają. Ja ustawię inny tytuł strony i wówczas uruchomię testy ponownie. Pierwsze trzy testy zakończyły się niepowodzeniem, jednak ostatni test pomimo zmiany tytułu na stronie nie zwrócił błędu (z powodu nadpisanego ustawienia czułości testu - procentowa zmiana na stronie była zbyt mała, aby wywołać błąd).

Oczywiście to, jakie testy zwróciły błąd - tak, jak w przypadku innych testów - możemy sprawdzić w pliku raport.html. Dostarcza nam on informacji, które testy zakończyły się niepowodzeniem oraz jaka była procentowa różnica porównywanych stron.

Przy tego typu testach taka informacja może nie być wystarczająca. Dlatego też dostępny mamy również plik vcresult.html, w którym znajdziemy pod nazwą każdego zakończonego niepowodzeniem testu 3 obrazki. Pierwszy obraz przedstawia różnice, jakie zostały znalezione podczas porównania, zaznaczając różniące się piksele na czerwono. Następne dwa obrazy to kolejno spodziewany i aktualny rezultat. 

Pliki projektu

Przykłady opisane w tym artykule możesz uruchomić u siebie, również poprzez pobranie ich bezpośrednio z repozytorium projektu i zmianę brancha na visualception.
Repozytorium projektu:
https://github.com/DropticaExamples/docker-console-project-example 
Zrzut bazy danych:
https://www.dropbox.com/s/r0o3u9gjp3dccd4/database.sql.tar.gz?dl=0 
Pliki projektu:
https://www.dropbox.com/s/hl506wciwj60fds/files.tar.gz?dl=0

 
Podsumowanie

Mam nadzieję, że tym wpisem zachęciłem Was do poeksperymentowania z możliwościami wykorzystania VisualCeption podczas automatyzowania testów na Waszych projektach. Moduł ten jest niezwykle pomocny, jeżeli nasz projekt jest bardzo czuły na zmianę wyglądu strony. Wiadomo nie od dziś, że człowiek sprawdzając wygląd strony może mieć gorszy dzień i nie zauważyć jakiejś z pozoru nieznacznej zmiany. Testy automatyczne za każdym razem będą śledzić zmiany co do piksela. Przy wprowadzaniu takich testów należy jednak pamiętać również o tym, że są one dość wolne (w porównaniu do innych typów testów) oraz “pamięciożerne”. 

Jeżeli spodobały się Wam testy Codeception, to koniecznie śledźcie naszego bloga, gdyż zapewne nie jest to nasz ostatni wpis w tej tematyce. 
 

Porozmawiajmy o Twoich projektach

Napisz do nas!