👨🏫 Porady
Czym jest Mockowanie danych?
W tym artykule przedstawie Ci ogólny koncept mockowania.
Skupie się tutaj na bardzo prostym przykładzie i ogólnym podejściu😉
Rzuć okiem na nasz darmowy webinar o mockowaniu danych w Playwright😉 Więcej o wydarzeniu: 🔗https://jaktestowac.pl/mockowanie/
Czym jest mockowanie?
Mockowanie w oprogramowaniu oznacza udawanie (symulowanie) jakiegoś elementu, którego potrzebujemy do działania systemu.
Możemy mockować też dane, które normalnie pochodziłyby z prawdziwej aplikacji lub back-endu. To pomaga nam w testowaniu naszej strony, w przypadkach gdy:
- przygotowanie prawdziwych danych jest kosztowne
- nie mamy dostępu do prawdziwych danych
Tyle z ogólnej teorii😉
Poniżej krok po kroku przeprowadzę Cię przez uproszczony przykład. Zapoznam Cię z uproszczonym kontekst, projektowaniem testów, wyzwaniami i rozwiązaniami😉
Przykład
Kontekst - testowana strona
Załóżmy, że:
- mamy do przetestowania stronę z artykułami i komentarzami
- wyświetlane dane pochodzą z back-endu
- na front-endzie jest dużo logiki, formatowania i walidacji
- prezentacja artykułów i komentarzy jest bardzo ważna z punktu widzenia biznesowego - klientowi bardzo zależy, aby ta funkcjonalność działała poprawnie
Strona wygląda w ten sposób:
Co możemy przetestować?
Na stronie możemy przetestować:
- czy artykuł wyświetla się poprawnie*
- czy komentarze wyświetlają się poprawnie*
- czy brak komentarzy jest poprawnie* prezentowany
- czy artykuł/komentarz z różnymi wartościami poszczególnych pól wyświetla się poprawnie* (czyli np. testy wartości brzegowych - pusty tytuł, tytuł z jednym znakiem, tytuł z maksymalną liczbą znaków etc.)
- itp.
* - poprawnie, czyli zgodnie z wymaganiami naszego klienta
Projektujemy pierwsze testy
Na pierwszy test wybierzemy sobie happy path - czyli test poprawnego artykułu z jednym komentarzem. Aby wykonać taki test potrzebujemy przygotować dane testowe (albo spełnić warunki wstępne - preconditions). W tym przypadku musimy:
- posiadać użytkownika
- użytkownik musi stworzyć poprawny artykuł
- użytkownik musi stworzyć poprawny komentarz
Po wykonaniu tych kroków (przygotowaniu danych) możemy przejść pod wskazany adres i przetestować, czy artykuł i komentarz wyświetlane są poprawnie.
Dane testowe możemy przygotować przed testem, albo możemy mieć je predefiniowane w bazie danych. Oba podejścia są poprawne w zależności od podejścia, projektu i kontekstu😉
Na razie to brzmi nieźle! Niewiele pracy: jedynie kilka kroków i mamy test gotowy🥳
Jednak przyjrzyjmy się kolejnym przypadkom.
Potrzeba
Mając przetestowany happy path, pozostały nam pozostałe przypadki:
- czy brak komentarzy jest poprawnie* prezentowany
- czy artykuł/komentarz z różnymi wartościami poszczególnych pól wyświetla się poprawnie* (czyli np. testy wartości brzegowych - pusty tytuł, tytuł z jednym znakiem, tytuł z maksymalną liczbą znaków etc.)
- itp.
Jakie tu się pojawia wyzwanie?
Do każdego testu musimy przygotować odpowiednie dane.
Możemy to próbować robić jak w przypadku pozytywnym albo przez manipulację danych w bazie danych. Dla niektórych przypadków (pusty tytuł czy treść artykułu) może to być czasochłonne, skomplikowane lub w niektórych przypadkach nawet niemożliwe*.
Dlatego zobaczmy jakie mamy jeszcze inne opcje. Zacznijmy od szybkiej analizy wyświetlanej strony, a dokładniej - prezentowanych danych.
*wyjaśnienie czym są niemożliwe przypadki opisuję na końcu wpisu
Skąd pochodzą dane wyświetlane na UI?
Dane wyświetlane na GUI pochodzą z back-endu. W naszej aplikacji są przesyłane w formacie JSON i można je podejrzeć w DevTools:
Następnie dane otrzymane z back-endu są odpowiednio przetwarzane i prezentowane na UI.
Pomysł
Co jeśli moglibyśmy zmienić dane jakie zwraca nam back-end?
Obecnie komunikacja wygląda w ten sposób:
Jakie mamy opcje, aby zmienić dane jakie otrzymujemy w odpowiedzi?
Nawiązując do schematu - aby zamienić
dane_A
na dane_B
?Opcja 1
Możemy spróbować stworzyć symulator (fake), który będzie “udawał” testowany back-end.
Plusy:
✅ duże możliwości związane z symulowaniem różnych odpowiedzi
Minusy:
❌ bardzo duży koszt przygotowania
❌ czasem skomplikowana konfiguracja
❌ aktualizacje rozwiązania do zmian w prawdziwym back-endzie
Opcja 2
Możemy spróbować przechwycić odpowiedź, która przychodzi z back-endu.
Następnie możemy wprowadzić w zmiany w danych i odesłać je do front-endu:
Plusy:
✅ duże możliwości w przygotowaniu odpowiedzi
✅ łatwośc i szybkość przygotowania
Minusy:
❌ w niektórych bardziej skomplikowanych testach może nie wystarczyć (np. testy mikroserwisów)
Podsumowanie naszych opcji
Opisane wyżej działania noszą nazwę mockowania😉
Framework Playwright posiada kilka mechanizmów, które pozwalają na mockowanie danych, a dokładniej przechwycenie ich, modyfikację i przesłanie ich do front-endu (czyli powyżej opisana Opcja 2).
Możesz nauczyć się jak zaimplementować mechanizm mockowania na praktycznych przykładach oraz jakie ma wady i zalety w naszym kursie o Playwright:
🔗https://jaktestowac.pl/playwright
W nowatorskim Programie Automatyzacji z Playwright pokazujemy jak rozpocząć naukę testów automatycznych i stworzyć własny framework do automatyzacji.
Mockowanie w testach automatycznych
Dzięki mechanizmowi mockowania możemy upewnić się, że nasz front-end działa poprawnie z różnymi danymi bez konieczności tworzenia zestawu danych po stronie back-endu.
Przykładowy test automatyczny w Playwright Test.
Oto kod testu, w którym weryfikujemy wyświetlenie tytułu testowanego artykułu:
test("should display article title", async ({ page }) => { // Act: await page.goto('http://localhost:3000/article.html?id=59'); // Assert: await expect(page.getByTestId('article-title')).toBeInViewport(); });
Rozwiązanie z mockowaniem danych
Zobacz jak w teście automatycznym możemy podmienić zawartość odpowiedzi z API i tym samym zmienić wartość wyświetlaną na front-end.
Możemy to najprościej zrobić za pomocą następującej konstrukcji:
test("should display article title", async ({ page }) => { // Arrange: await page.route("*/**/api/articles/*", async (route) => { const response = await route.fetch(); const json = await response.json(); json["title"] = ""; await route.fulfill({ response, json }); }); // Act: await page.goto("http://localhost:3000/article.html?id=1"); // Assert: await expect(page.getByTestId("article-title")).toBeInViewport(); });
W powyższym przykładzie przed przejściem do testowanego zasobu dodaliśmy kod umożliwiający podmianę odpowiedzi przychodzących z back-endu.
Omówmy kod związany ściśle z mockowaniem:
await page.route('*/**/api/articles/*', async route => { const response = await route.fetch(); const json = await response.json(); json['title'] = ''; await route.fulfill({ response, json }); });
Najpierw deklarujemy przechwytywanie odpowiedzi pochodzących z
/api/articles
await page.route('*/**/api/articles/*', async route => {
Przypisujemy odpowiedź i jej zawartość do poszczególnych zmiennych.
const response = await route.fetch(); const json = await response.json();
W zawartości odpowiedzi ustawiamy pole
title
na wartość ''
, czyli pusty napis.json['title'] = '';
Następnie wypełniamy odpowiedź z back-endu naszymi zmodyfikowanymi danymi i puszczamy ją do front-endu.
await route.fulfill({ response, json });
Wynik zastosowania kodu z mockowaniem
Jak taki artykuł będzie się prezentował na UI?
Sprawdźmy!😀
Artykułu z pustym tytułem:
Kolejne przykłady z użyciem mockowania
Artykułu z pustą treścią:
Artykułu bez komentarzy:
Pełny kod tego typu testów, prezentację na żywo oraz wprowadzenie do konceptu mockowania zobaczysz na webinarze 🔗https://jaktestowac.pl/mockowanie/
Podsumowanie
Mockowanie może być kluczem do zapewnienia stabilności i efektywności testów UI oraz wydajnego sprawdzania, jak front-end zachowuje się w różnych scenariuszach😉
Zalety mockowania danych w testach automatycznych:
✅ Szybkość i niezależność - mockowanie pozwala na przeprowadzenie testów bez potrzeby łączenia z rzeczywistym systemem lub bazą danych. To sprawia, że testy są znacznie szybsze i niezależne od infrastruktury zewnętrznej
✅ Powtarzalność - wykorzystane dane pozostają stałe i można je łatwo kontrolować, co zapewnia powtarzalność testów niezależnie od stanu rzeczywistych danych w systemie
✅ Testowanie skrajnych przypadków - mockowanie pozwala na testowanie różnych scenariuszy. Szczególnie tych, które w rzeczywistości mogą być trudne do wykonania (przez specyficzne dane testowe)
✅ Izolacja - mockowanie danych izoluje testy od innych części systemu, co pomaga w identyfikacji i rozwiązywaniu problemów z mniejszymi skutkami ubocznymi
✅ Niezawodność - testy nie są zależne od zmian w rzeczywistych danych, a dane w mockach pozostają stałe
Wady mockowania danych w testach automatycznych:
❌ Brak testowania integracji - testy bazujące na mockowaniu nie sprawdzają, czy różne części systemu poprawnie się integrują
❌ Większy koszt utrzymania - może być pracochłonne, szczególnie w przypadku bardziej skomplikowanych systemów i danych
❌ Ryzyko błędów w mockach - błędy w danych mogą prowadzić do fałszywie wyników względem tych, które otrzymamy w realnym systemie
Ostateczny wybór pomiędzy mockowaniem danych a korzystaniem z rzeczywistych danych w testach zależy od konkretnego przypadku użycia i celu testów😉
W niektórych przypadkach warto skorzystać z mocków, aby usprawnić i przyśpieszyć swoje testy.
W innych warunkach lepszym podejściem może być użycie rzeczywistych danych.
Ważne jest, abyśmy trafnie ocenili, które podejście jest bardziej odpowiednie w danym kontekście😉
Polecam rozpisać plusy i minusy dla Twojego konkretnego przypadku oraz przedyskutować w zespole w jakich przypadkach testy z mockowaniem danych przyniosą najwięcej wartości.
Dodatkowe materiały
- Webinar: Playwright w akcji – testy GUI bez backendu (ale z mockowaniem danych) - wszystkie informacje i linki znajdziesz na naszej stronie: 🔗https://jaktestowac.pl/mockowanie/
- Oficjalna dokumentacja 🔗https://playwright.dev/docs/mock
- Nowatorski Program o automatyzacji testów z Playwright: 🔗https://jaktestowac.pl/playwright
Bonus: o co chodzi z niewykonalnymi przypadkami testowymi
Mockowanie może pozwolić nam na stworzenie danych, które za pomocą dostępnej komunikacji z systemem może być niewykonalne.
Pierwszym przykładem, może być dostarczanie danych przez zewnętrzny serwis nad którym nie mamy kontroli.
Może to wystąpić, gdy nasza aplikacja lub system korzysta z danych udostępnianych przez inny serwis lub API. W takim przypadku nie mamy wpływu na dostępność ani zawartość danych pochodzących z zewnętrznego źródła.
Może to prowadzić do trudności w przeprowadzeniu testów, ponieważ nie jesteśmy w stanie przewidzieć ani kontrolować, jakie dane otrzymamy od tego zewnętrznego serwisu w różnych momentach.
W takich sytuacjach mockowanie staje się rozwiązaniem.
Możemy stworzyć kontrolowane i przewidywalne środowisko testowe. W nim możemy użyć spodziewanych danych, załadowanych za pomocą mechanizmu mockowania.
Wynikiem będzie izolacja testów naszej aplikacji od zewnętrznych serwisów. Pozwala to też lepiej skupić się na testowaniu logiki naszej aplikacji.
Drugim przykładem mogą być testy niestabilności lub niedostępności serwisów.
Mockowanie pozwala na tworzenie scenariuszach, które mogą być trudne do odtworzenia w realnych warunkach. Przykładowo błędne zachowania, wolno działający lub czasowo niedostępny zewnętrzny serwis😉
Powodzenia w mockowaniu!
Zaprezentowane przykłady to tylko wierzchołek góry lodowej możliwości związanych z mockowaniem. Kolejnymi krokami mogą być: pełne mockowanie backendu, wycinanie nadmiarowego ruchu sieciowego czy testowanie wyizolowanych komponentów strony.
Daj mi znać, jakie Ty masz doświadczenia z mockowaniem i czy stosujesz lub widzisz przestrzeń na tego typu testy u siebie w projekcie?🤔