w Praktyce
7 godz. 1 min · Angular · Full-stack i Programowanie
Mateusz KuleszaSenior Software Developer, Konsultant, TrenerPodstawą produktywnej pracy z angularem jest możliwość zagwarantowania że wszystko działa bez potrzeby wielokrotnego “przeklikiwania” poszczególnych ekranów. W pierwszej części kursu omawiam więc temat testów automatycznych.Już po obejrzeniu pierwszych lekcji zobaczysz dlaczego warto testować kod i jak dzięki narzędziom dostarczonym z angularem jest to proste. Zobaczysz jak testowanie automatyczne pozwoli zaoszczędzić Ci wiele godzin spędzonych na szukaniu błędów.
Za jakość aplikacji odpowiada nie tylko to czy działa ona poprawnie, ale w dużej mierze decyduje o tym dobry interfejs użytkownika oraz UX, czyli user experience. Dwie kolejne sekcje kursu poświęcone są właśnie dobremu UI oraz UX. Omawiam typowe problemy w oparciu o zasady i wskazówki specyfikacji Google Material Design - jednej z najbardziej szczegółowych specyfikacji UX. Wszystkie przykłady UI zarówno w wariantach desktopowych jak i mobilnych omówione są na przykładzie Angulara oraz obszernej biblioteki komponentów Angular Material. Zobaczysz nie tylko jak korzystając z gotowych komponentów błyskawicznie budować nowe funkcjonalności, ale przy okazji omówimy wiele praktycznych wskazówek oraz dobrych praktyk UX które warto wykorzystać w Twoich aplikacjach.
W ramach budowania interfejsów skupimy się na najmniejszych szczegółach takich jak prawidłowe zachowanie linków, przycisków oraz wskaźników przechodząc stopniowo do coraz większych elementów aplikacji takich jak nawigacja, układ strony, paski nawigacyjne czy okna dialogowe. Przy każdym etapie czeka Cię masa wskazówek, przykładów i rozwiązań typowych problemów user experience.
Jednak UX to nie tylko wygląd i zachowanie pojedynczych elementów. W ostatnich sekcjach kursu dowiesz się jak projektować bardziej złożone interakcje z użytkownikiem. Zobaczysz wieloetapowe formularze kreatora oraz dowiesz się jak zarządzać stanem aplikacji oraz różnymi źródłami danych. Pokaże Ci jak zbudować samodzielnie sortowane, filtrowane i stronicowane źródła danych oraz połączyć je z różnymi komponentami UI takimi jak listy czy datagrid.
Na koniec kursu zobaczysz jak możemy różne gotowe elementy UI połączyć w przepływ ekranów budując ścieżkę użytkownika. Zobaczysz jak prawidłowo zaprojektowane komponenty wraz z dobrze zaplanowanym UX pozwalają być niesamowicie produktywnym jednocześnie nie poświęcając jakości czy dobrej architektury aplikacji.
Jest to kurs dla osób które już pracowały z angularem i chciałyby wyjść poza pojedyncze techniki oraz poznać proces projektowania aplikacji w praktyce z uwzględnieniem najlepszych praktyk programistycznych oraz user experience. Zarówno w wariancie webowym jak i projektując pod urządzenia mobilne.
Angular 6, 7, 8+
We wcześniejszych lekcjach utworzyliśmy tutaj przykładowe testy dla komponentu
wyrenderowaliśmy komponent i sprawdziliśmy czy przy zmianach
danych w tym komponencie i po wykryciu zmiany czy te zmiany właśnie są
tutaj aktualizowane w szablonie w htmlu nie mniej cały czas te
testy jakby są jednostronne my testujemy to co komponent
przekazuje użytkownikowi ale nie testujemy tego jak on reaguje na
zdarzenia na akcje użytkownika i właśnie tym zajmiemy się w tej
lekcji powiedzmy że nasz komponent będzie miał tutaj jakiś button
z opcją edit czyli przełączenie w tryb edycji
i chciałem przetestować czy właśnie jak użytkownik kliknie w ten button
czy przełączymy się w tryb edycji a dokładnie przetestować sam przycisk
czyli jakby nie wciśnięcie od razu włącza tryb edycji tylko
czy wciśnięcie powoduje uruchomienie konkretnej funkcjonalności
a czy ta funkconalność uruchamia tryb edycji no to już uruchomimy sobie
w kolejnym teście po to żeby te nasze testy były jak najbardziej precyzyjne
żeby były testami jednostkowymi żeby ten test jakby zbyt wiele swoim
zasięgiem nie obejmował czyli dam tutaj jakiś kolejny test it should
powiedzmy switch to
edit mode when edit
button is clicked i teraz
jak przetestować dokładnie no właśnie taką sytuację czyli
jak wykryć że przycisk został wciśnięty albo inaczej mówiąc jak
sprawdzić czy wciśnięcie przycisku wywołuje oczekiwaną
jakąś reakcję czyli powiedzmy że nasz komponent nasz
komponent miałby funkcje powiedzmy edit i
wywołanie tej funkcji powinno przełączyć tryb edycji ale my nie chcemy sprawdzić tutaj czy
wywołanie funkcji powoduje efekt chcemy sprawdzić czy wciśnięcie tego
przycisku wywoła tą funkcję i teraz
w jasmine możemy w bardzo fajny sposób sprawdzić czy
właśnie funkcja została wywołana i w tym celu użyjemy szpiega
czyli tutaj jest spy spy on albo
spy on property to są funkcje które możemy zaimportować sobie z jasmine'a
są tu już zaimportowane ze wszystkimi funkcjami jasmine
i spy on pozwala nam wyrzucić obiekt czy na przykład nasz komponent w
ramach tego obiektu określić jakąś metodę będzie to na przykład metoda edit
która jeszcze nie istnieje okej edit
i tu bardzo fajna rzecz bo on tutaj sprawdza typy automatycznie czyli
jak widzisz type script sprawdza czy jak taki klucz jak edit w ogóle istnieje
na naszym komponencie na naszej klasie jeśli nie to jest to błąd więc możemy tutaj w komponencie
dopisać sobie nową metodę będzie to edit i
na razie ta metoda nie będzie nic robiła po prostu zostawimy sobie ją w ten sposób chcę tylko sprawdzić czy
nasz przycisk wywoła tą metodę czyli tutaj stworzę sobie
zmienną edit spy i szpieg działa
w ten sposób że jeśli wskażę mu obiekt i wskażę mu którąś
metodę to on tak naprawdę podmienia tą metodę i
zastępuje ją taką właśnie swoją metodą metodą szpiegują
metoda szpieguja pozwala wykryć czy ktoś uruchomił
kod jakiś na tej metodzie i teraz fajne rzeczy
bo ja mogę ten szpieg rozszerzyć mogę tu na przykład powiedzieć na przykład żeby
przy wywołaniu tej funkcji próbie wywołaniu tej funkcji tak naprawdę wywołać
fałszywą funkcję mogę podmienić tą funkcję tutaj na widzisz zupełnie
inną funkcję jakąś testową mogę oczywiście wykonać oryginalną
funkcje przepuścić tego wywołującego przez szpiega do
oryginalnej funkcji jeśli tego potrzebuje jeśli chcę zwrócić jakieś
przykładowe fałszywe wartości do testów nie muszę tutaj mockować nie
muszę fałszować całej funkcji mogę od razu powiedzieć żeby zwróciła jedną konkretną
wartość albo przekazać sekwencje wartości tak że jak każde
kolejny wywołanie tej naszej funkcji szpiega która symuluje oryginalną
funkcje spowoduje że ten kod który wywoła tą funkcję dostanie
każdą z tych wartości oczywiście możemy też wrócić z powrotem do
zachowania potem jak sobie poszalejemy z tymi opcjami możemy
też zasymulować w funkcję która zwraca błąd tak czy możemy przetestować co się
dzieje kiedy ktoś poda nieprawidłowe parametry albo właśnie już zasymulować
że zostały podane nieprawidłowe parametry zasymulować błąd
i zobaczyć jak komponent na to zareaguje ja tu zostanę z zwykłą taką
edit spy pokażę tylko jeszcze tutaj taką fajną rzecz bo jak widzisz mamy
calls i most recent call czyli jakby szpieg zbiera zapisuje
historię wszystkich wywołań wie dokładnie kto go wywołał i
możemy sobie zrobić expect i sprawdzić czy nasz szpieg
został faktycznie wywołany i to ma różne fajne metody takie jak na
przykład to have been called czyli sprawdzić czy szpieg został wywołany został wywołany
przed innym szpiegiem czyli możemy ustalić kolejność wywoływania funkcji
i zapewnić że one faktycznie wywołają się w odpowiedniej kolejności możemy ilość wykonań
zmierzyć czy ktoś za dużo razy nie uruchomił tej funkcji ten komponent albo za mało możemy
też sprawdzić czy funkcja została wykonana z jakimś specyficznym parametrem
albo zwróciła błąd tutaj też mamy taką możliwość ja się zatrzymam
na jej podstawowej opcji czyli sprawdzamy czy ta funkcja została wykonana i
teraz tu nam brakuje pewnej rzeczy bo ja podstawiam szpiega i
sprawdzam czy został szpieg wykonany czy sprawdzam czy funkcja została
uruchomiona brakuje nam tylko symulacji faktycznego
kliknięcia w ten przycisk więc pierwsze co to zrobimy to
ja sobie tutaj znajdę przycisk czyli const input z tym button to będzie
oczywiście jak wiesz fixture debug element query by css
button polecam tobie nie używać zbyt ogólnych tutaj
selektorów tu będzie się zmieniał i nie chcesz później za
każdym razem jak dodasz nowy przycisk zmieniać wszystkich pozostałych więc od razu dodam sobie tutaj jakąś klasę
nazwę ją edit button powiedzmy
i będę szukał tej po tej klasie edit button i
teraz żeby zasymulować kliknięcie to jak widzisz mamy błąd bo szpieg
nie został tutaj uruchomiony zasymulujemy kliknięcie w
przycisk zobaczymy czy kliknięcie w przycisk wywoła funkcję oczywiście to się na razie nie stanie czyli
tak button i tutaj jak pamiętasz była taka fajna funkcja trigger
event handler nie mogę sobie zdarzenia tutaj ja chcę zsumować click
czyli napiszę sobie po prostu tutaj click i bardzo ważna rzecz zdarzenie
pamiętaj że tworzy zawsze obiekt typu eventy każde każde zdarzenie i obiekt
event zawiera dodatkowe informacje na przykład gdybyśmy musieli sprawdzić którym przyciskiem myszy
ktoś kliknął albo w jaki element został kliknięty tak
złapał te wszystkie informacje o eventach tutaj możemy przekazać także
fałszywe informacje fałszywe zdarzenie można podstawić nasz button
nie musi nic wiedzieć na temat zdarzenia nie musi wiedzieć który przycisk myszy był wciśnięty
czy control był wciśnięty czy alt te wszystkie dodatkowe informacje nam nie potrzebne więc tutaj też
nie będę tutaj mockował żadnych dodatkowych informacji i zobaczmy teraz
znajdujemy sobie szpiega znajdujemy przycisk
klikamy w przycisk i sprawdzamy czy przycisk wywołał tego szpiega i oczywiście
nie bo tutaj jak widzisz nasz button jest do niczego przypięty i mamy cały czas informacje
że nasz szpieg nie został wykonany jeśli natomiast czyli jeśli dodamy
tą usługę klik i naklika wywołam właśnie
tą naszą metodę edit z komponentu edit
tutaj zapiszę zapiszę ten plik jak widzisz
mam pełen sukces w ten sposób możemy przetestować podstawić właściwie
metodę po sobie szpiega zamiast jakiejś metody naszego komponentu znaleźć
element wywołać akcje na htmlu i zobaczyć czy ta akcja faktycznie
prawidłowo wykonała zmiany prawidłowo wykona funkcję na
naszym komponencie i tutaj
jeszcze według opisu naszego testu kliknijcie powinno
przełączyć na tryb tutaj na edit czyli jeszcze w komponencie
naszym tutaj pozwolę sobie dodać jeszcze tryb edit ustawimy
go na false domyślnie akurat się tak samo widzę zgadza
edit mode powiedzmy i
edit ustawię edit mode
na true w ten sposób i teraz
w testach chciałbym też to sprawdzić czyli sprawdzimy expect komponent
edit mode po prostu tu equal
true okej
zobaczmy co na to testy i tutaj widzisz to się nam nie
zmieniło zobaczmy jeszcze tak edit klikam na edit i
to powinno zmienić nam edit mode na true
teraz można zastanowić się czemu to nie zadziałało mianowicie fakt tu
nie znajduje przycisk klikam został przycisk wciśnięty
funkcja nie została wykonana a nasz edit mode nie równa się true pamiętaj
o tym że jak uruchamiasz szpiega to szpieg jakby zamienia oryginalną funkcję
na szpiega jeśli chcesz aby oryginalna funkcja była mimo to wykonana to musisz pamiętać
o tym tutaj żeby dodać właśnie którąś z tych opcji call true akurat
po prostu wykona oryginalną funkcję jeśli funkcja oryginalna
wykonuje jakieś efekty których byś nie chciał i nie są ci potrzebne przeszkadzają twoim tekście no
to możesz podmienić szpiega i podmienić na inną funkcję z call fake zrobimy z call through
i teraz jak widzisz wszystko poszło elegancko czyli jak szpiegujesz
tutaj pamiętaj czy chcesz właśnie tylko szpiegować czy ktoś próbował uruchomić funkcję
czy chcesz szpiegować i dodatkowo tą funkcję możesz wykonać możesz
też zasymulować tutaj zwracanie konkretnego wyniku czyli
można na przykład zrobić żeby tutaj return value
true powiedzmy i tu sprawdzić z called with
true tylko znowu to
zasymulujemy wykonanie funkcji ale oryginalny funkcji nie wykona więc
jak wrócę tutaj do naszej poprzedniej wersji kiedy my przepuszczamy oryginalną funkcję
żeby się wykonała sprawdzamy czy ta funkcja została czy szpieg został wykonany ale
także sprawdzamy czy ta funkcja odniosła efekt w testach już aplikacji polecam
nie rozbudowywać za bardzo takich testów taki test możemy już właśnie rozbić na
dwa w pierwszym teście byśmy sprawdzali po prostu czy kliknięcie
w przycisk wykonuje funkcje a w drugim teście
byśmy sprawdzali czy wywołanie funkcji zmienia mode czyli to powinny
być de facto dwa osobne testy ja na razie zostawię to w ten sposób okej
to tyle jeśli chodzi o testowaniu interaktywności i oczywiście tu możesz poustawiać
dowolne inne zdarzenia i dowolne inne szczegóły tego zdarzenia żeby
symulować bardziej zaawansowane interakcje nie tylko klikanie myszą na przykład
tu integracja z klawiaturą czy na przykład inne bardziej zaawansowane zdarzenia
myszy i nie tylko ale o tym powiemy sobie w już w kolejnej lekcji
gdzie potestujemy sobie elementy formularza i potestujemy też troszeczkę bardziej
zaawansowane interakcje niż po prostu kliknięcie tak więc
do zobaczenia w kolejnej lekcji