Gotowe do CI testy e2e dla Angulara z Cypressem i TypeScriptem w mniej niż 60 minut
Ten artykuł ma na celu opisanie, jak można skonfigurować testy end-to-end dla Angulara z Cypressem i TypeScriptem. Napiszesz swoje pierwsze testy e2e i przygotujesz je do uruchomienia na CircleCI jako system ciągłej integracji z każdą aktualizacją Twojego repozytorium.
Testy end-to-end (w skrócie e2e) to rodzaj testów oprogramowania, które walidują system oprogramowania wraz z jego integracją z zewnętrznymi interfejsami. Celem testów end-to-end jest przećwiczenie kompletnego scenariusza podobnego do produkcyjnego.
Źródło: https://www.guru99.com/end-to-end-testing.html.
Overview
- What is Cypress?
- Prerequisites
- Setting up Cypress
- Writing Some Tests
- Setting up Continuous Integration
- Conclusion and References
I have a frontend development background in Microsoft’s .NET & WPF i pamiętam czasy, kiedy ocenialiśmy kosztowne frameworki, aby napisać testy end-to-end dla naszych projektów. Po wielu ocenach i tygodniach, a nawet miesiącach niestandardowego kodu kleju i rozwoju infrastruktury testowej na wierzchu istniejących narzędzi, w końcu udało nam się uzyskać kilka działających testów e2e. Były one kruche, często zawodziły z powodu ręcznych poprawek, które musieliśmy wykonać lub problemów z nieszczelnymi runnerami w ciągłym potoku integracji.
Kilka lat później z Angularem i Protractorem jako domyślnym dla testów e2e, nadal bazowaliśmy na obiektach stron, Selenium Web Driver i testy nadal były raczej zawodne. Nie były potrzebne drogie komercyjne frameworki i niestandardowa infrastruktura. Ale czy pisanie testów e2e było przyjemne? Nie.
Jednakże mamy teraz rok 2020 i nadszedł czas, aby pojawili się nowi bohaterowie. 🚀
Czym jest Cypress?
Cypress obiecuje szybkie, łatwe i niezawodne testowanie wszystkiego, co działa w przeglądarce. Nie jest on oparty na Selenium Web Driver, który używa połączeń sieciowych do interakcji z przeglądarką. Zamiast tego Cypress jest narzędziem do uruchamiania testów, które działa wewnątrz przeglądarki obok aplikacji internetowej i dlatego ma nad nią bezpośrednią kontrolę.
Bez wchodzenia we wszystkie szczegóły, to nie tylko sprawia, że Cypress jest szybszy i bardziej niezawodny, ale także otwiera drzwi dla wielu innych interesujących funkcji, takich jak
- debugowanie podróży w czasie,
- łatwe migawki i nagrywanie,
- automatyczne oczekiwanie.
Na szczycie wszystkich funkcji, Cypress ma doświadczenie dewelopera (DX), które jest prawie bezkonkurencyjne. Czy kiedykolwiek widziałeś wiadomość w dziennikach błędów nieudanej budowy, która mówi dokładnie, co zrobiłeś źle, wskazuje ci właściwe zależności, które należy dodać, a także odsyła do strony z dokumentacją wyjaśniającą opisującą problem? Tak właśnie wygląda Cypress. Jest on zbudowany przez deweloperów dla deweloperów.
Następnie zainstalujemy Cypress dla świeżego projektu Angulara utworzonego za pomocą CLI. Napiszemy kilka testów e2e i zakończymy je uruchomieniem przez automatyczny system budowania. Wszystkie te kroki nie powinny zająć więcej niż 60 minut. Staramy się, aby kroki były jak najkrótsze, wykorzystując istniejące narzędzia, takie jak Angular Schematics, biblioteki i wspólne szablony.
Wymagania wstępne
Ten przewodnik zakłada, że posiadasz standardowy projekt aplikacji Angular 9. Jeśli nie, możesz go utworzyć tak, jak zrobiłbyś to normalnie za pomocą Angular CLI. Jeśli nie masz zainstalowanego CLI globalnie, możesz skorzystać z polecenia npx
, które zainstaluje je tymczasowo w locie:
npx @angular/cli new <app-name>
Konfigurowanie Cypressa
Aby jak najszybciej skonfigurować Cypressa wraz z TypeScriptem, korzystamy z istniejącego schematu opracowanego przez BrieBug.
W korzeniu Twojego projektu Angular możesz otworzyć terminal i wpisać następujące polecenie:
ng add @briebug/cypress-schematic --addCypressTestScripts
Jeśli CLI nie jest zainstalowane globalnie, polecenie ng
może nie być dostępne bezpośrednio. Można wymusić użycie lokalnego ng
z poziomu package.json
:
npm run ng -- add @briebug/cypress-schematic # In case 'ng' could not be found
Możemy bezpiecznie usunąć Protractor, ponieważ zostanie on całkowicie zastąpiony. Podczas instalacji zostało pobranych kilka binarek, ponieważ Cypress jest dostarczany z Electron-bundled UI jako interaktywny test runner.
Używając flagi --addCypressTestScripts
zostały dodane dwa poręczne skrypty npm, aby uczynić pracę z Cypressem bardziej komfortową. Jeden do uruchamiania testów e2e bez głowy, a drugi skrypt uruchamiający testy za pomocą Cypress UI runnera:
// package.json scripts "cy:run": "cypress run", "cy:open": "cypress open"
Gdybyś miał uruchomić jeden z tych skryptów samodzielnie, test zakończyłby się niepowodzeniem, ponieważ próbowałby kierować się do http://localhost:4200, gdzie w tej chwili nic nie jest obsługiwane. Aby to naprawić, musimy otworzyć drugi terminal i obsłużyć naszą aplikację Angular wcześniej za pomocą npm start
.
Na szczęście schemat dostosował polecenie e2e
tak, że jest to wykonywane automatycznie przez konstruktora CLI. Możemy obsłużyć aplikację i uruchomić test e2e za pomocą następującej komendy:
npm run e2e
Cypress wykryje, że uruchomiliśmy go po raz pierwszy. Sprawdza jego instalację i dodaje kilka początkowych plików przykładowych. Po otwarciu UI możemy zobaczyć test, który został już dla nas stworzony.
Wybranie testu spowoduje jego uruchomienie. Początkowo test się nie powiedzie, ponieważ nie przetestowaliśmy czegoś poprawnie. Naprawimy to teraz.
Writing Some Tests
Jako pierwszy krok, zgodnie z najlepszymi praktykami Cypress, ustawiamy nasz globalny baseUrl, aby nie musieć go powielać przy każdym wykonaniu testu. W tym celu dodajemy do konfiguracji cypress.json
:
// cypress.json{ "baseUrl": "http://localhost:4200"}
Potem piszemy nasz pierwszy test dymny, który sprawdza tylko czy domyślny tytuł aplikacji jest ustawiony na stronie startowej Angulara. Dlatego też zmieniamy treść spec.ts
na następującą:
// spec.tsit('smoke test', () => { cy.visit('/'); cy.contains('cypress-e2e-testing-angular app is running!');});
Test rozpoczyna się od routingu do naszego baseUrl i przechodzi przez zapytanie do dowolnego elementu, który zawiera tekst cypress-e2e-testing-angular app is running!.
Testowanie przepływów użytkownika
Testy te powinny już działać, ale napiszmy kilka bardziej interaktywnych. Ponieważ testy e2e są z natury wolniejsze niż testy jednostkowe, jest całkowicie w porządku mieć testy e2e, które modelują cały przepływ użytkownika dla danej funkcji.
Na przykład, chcemy sprawdzić czy niektóre cechy strony startowej są poprawne: Nasza strona powinna domyślnie zawierać tytuł i tekst ng generate
w terminalu, ale gdy użytkownicy klikną przycisk Angular Material, chcemy się upewnić, że w widoku terminala poniżej wyświetlane jest właściwe polecenie ng add
.
Możesz zastąpić zawartość swojego pliku testowego tym:
// spec.tsdescribe('When Angular starting page is loaded', () => { beforeEach(() => { cy.visit('/'); }); it('has app title, shows proper command by default and reacts on command changes', () => { cy.contains('cypress-e2e-testing-angular'); cy.contains('.terminal', 'ng generate component xyz'); cy.contains('Angular Material').click(); cy.contains('.terminal', 'ng add @angular/material'); });});
Zrefaktoryzowaliśmy nasz zestaw testów, dodając blok describe
, aby przechwycić wszystkie testy, które są uruchamiane, gdy ładowana jest strona startowa. Ponieważ za każdym razem odwiedzamy baseUrl, przenieśliśmy to do wywołania beforeEach
. Na koniec połączyliśmy podstawowe testy dymu z testem widoku terminala na stronie startowej.
Ważne jest, aby wiedzieć, że nie należy przechowywać wyników zapytań Cypressa w zmiennych, ale zamiast tego pracować z domknięciami. Ponadto, elementy wybieraliśmy za pomocą klas CSS i zawartości tekstowej, co może być zbyt kruche. Zalecane jest używanie atrybutów data-
do wybierania elementów.
Cypress ma wiele wspaniałych funkcji i możliwości. Nie będziemy opisywać ich wszystkich, ponieważ naszym celem jest skupienie się na pierwszym punkcie wyjścia. Oficjalna dokumentacja jest naprawdę dobra i obejmuje wszystko na temat interakcji z elementami.
Jeśli ponownie uruchomisz ten zestaw testów, powinieneś zobaczyć, jak UI klika w każdym scenariuszu i wszystkie trzy testy powinny tym razem przejść. ✔✔✔
Ustawianie ciągłej integracji
Teraz, gdy nasze testy działają lokalnie, uruchommy mały potok CI (continuous integration). Dobrym sposobem na przygotowanie się do tego, jest stworzenie skryptów npm i połączenie ich tak, aby system kompilacji mógł użyć pojedynczego skryptu jako punktu wejścia. Stosując tę metodę, można wypróbować kroki CI lokalnie, przed ich uruchomieniem w sieci. Ponadto skrypty npm są raczej niezależne od rzeczywistego systemu budowania.
Na CI musimy uruchomić nasz serwer w tle i poczekać, aż spakuje on naszą aplikację, co może chwilę potrwać. Następnie musimy uruchomić Cypress test runner, przejść przez testy i zamknąć serwer po ich zakończeniu. Na szczęście możemy to wszystko zrobić za pomocą jednego narzędzia o nazwie start-server-and-test, jak opisano w dokumentach Cypress:
npm install --save-dev start-server-and-test
Po zainstalowaniu tego, używamy Angular serve, który jest obecnie za npm start
i łączymy go z poleceniem headless cy:run
:
// package.json scripts "start": "ng serve", "cy:run": "cypress run", "e2e:ci": "start-server-and-test start http://localhost:4200 cy:run"
Z pewnością można by użyć production build lub zbudować wcześniej i serwować aplikację za pomocą dowolnego serwera http. Dla zwięzłości, zostawię te usprawnienia dla Ciebie.
Circle CI
Dla naszego przykładu, wybraliśmy CircleCI ponieważ bardzo dobrze integruje się z GitHubem, jest tam powszechnie używany i ma darmowy plan. Możesz użyć dowolnego innego systemu CI jak Jenkins lub GitLab (z którymi mam największe doświadczenie). Po zalogowaniu się do CircleCI i połączeniu z naszym kontem GitHub, można wybrać repozytorium i stworzyć nowy projekt poprzez ich dashboard.
Aby skonfigurować pipeline, można by napisać config.yml
wybierając szablon i dostosowując go do swoich potrzeb i ewentualnie uruchomić skrypt e2e. Na szczęście Cypress posiada gotowe do użycia konfiguracje (zwane Orbs) dla CircleCI, które zawierają już instalację zależności, cache’owanie i tak dalej. Zanim będziemy mogli z nich skorzystać, musimy odwiedzić Ustawienia Organizacji, aby włączyć runnery stron trzecich.
# circleci/config.ymlversion: 2.1orbs: # This Orb includes the following: # - checkout current repository # - npm install with caching # - start the server # - wait for the server to respond # - run Cypress tests # - store videos and screenshots as artifacts on CircleCI cypress: cypress-io/cypress@1workflows: build: jobs: - cypress/run: start: npm start wait-on: 'http://localhost:4200' store_artifacts: true
Potok ma tylko jedno zadanie: Uruchom wszystkie testy e2e. Sprawdza bieżącą gałąź, instaluje wszystkie zależności, w tym cache, uruchamia serwer aplikacji i uruchamia nasze testy. Dodatkowo, filmy (nagrane domyślnie) i zrzuty ekranu (w przypadku niepowodzenia testów) są przesyłane jako artefakty CircleCI do dalszej inspekcji.*
Podsumowanie
Kroki w tym przewodniku są raczej minimalne. Możesz wykorzystać swój istniejący projekt Angulara, możesz zmienić konfigurację swoich pakietów testowych Cypress i napisać wiele bardziej znaczących testów. Co więcej, możesz zdefiniować skrypty npm dla różnych scenariuszy i środowisk i oczywiście cały Twój potok budowania może być rozszerzony o linting, testy jednostkowe, budowanie, a nawet wdrażanie Twojej aplikacji. Niemniej jednak powinien to być pierwszy krok, który pokazuje, jak szybko można skonfigurować zautomatyzowane testy end-to-end w dzisiejszych czasach.
Poczekaj, aż napiszesz prawdziwe testy Cypress dla swojej aplikacji. Będziesz się dobrze bawił!
Mam nadzieję, że i Ty znajdziesz jakąś wartość w tym artykule. Jeśli masz jakieś pytania lub uwagi, po prostu daj mi znać. Twoje opinie są bardzo mile widziane!
Źródła dla tego przewodnika można znaleźć na GitHub:
MrCube42 / cypress-e2e-testing-angular
Przykładowa aplikacja Angular 9 wykorzystująca Cypress do testowania end-to-end.
CypressE2eTestingAngular
Ten projekt został wygenerowany przy użyciu Angular CLI w wersji 9.0.6.
Serwer deweloperski
Uruchom ng serve
dla serwera dev. Przejdź do http://localhost:4200/
. Aplikacja zostanie automatycznie przeładowana, jeśli zmienisz którykolwiek z plików źródłowych.
Kodowanie rusztowania
Uruchom ng generate component component-name
, aby wygenerować nowy komponent. Możesz również użyć ng generate directive|pipe|service|class|guard|interface|enum|module
.
Buduj
Run ng build
, aby zbudować projekt. Zbudowane artefakty będą przechowywane w katalogu dist/
. Użyj flagi --prod
do kompilacji produkcyjnej.
Running unit tests
Run ng test
, aby wykonać testy jednostkowe przez Karmę.
Running end-to-end tests
Run npm run e2e
, aby wykonać testy end-to-end przez Cypress.
Dalsza pomoc
Aby uzyskać więcej pomocy na temat Angular CLI użyj ng help
lub sprawdź Angular CLI README.
.
Leave a Reply