Kompleksowy przewodnik po Cypress, potężnym frameworku do testowania end-to-end, obejmujący instalację, pisanie testów, debugowanie, integrację CI/CD i najlepsze praktyki.
Cypress: Ostateczny przewodnik po testowaniu end-to-end dla aplikacji internetowych
W dzisiejszym, szybko rozwijającym się krajobrazie tworzenia stron internetowych, zapewnienie jakości i niezawodności aplikacji internetowych ma zasadnicze znaczenie. Testowanie end-to-end (E2E) odgrywa kluczową rolę w weryfikacji, że wszystkie komponenty aplikacji działają razem płynnie z perspektywy użytkownika. Cypress wyłonił się jako wiodący framework testowania E2E, oferując przyjazne dla programistów środowisko, potężne funkcje i doskonałą wydajność. Ten kompleksowy przewodnik przeprowadzi Cię przez wszystko, co musisz wiedzieć, aby rozpocząć pracę z Cypress i skutecznie testować swoje aplikacje internetowe.
Co to jest Cypress?
Cypress to narzędzie do testowania front-end nowej generacji, stworzone dla nowoczesnej sieci. W przeciwieństwie do tradycyjnych frameworków testowych, które uruchamiają testy w przeglądarce, Cypress działa bezpośrednio w przeglądarce, dając Ci niezrównaną kontrolę i widoczność zachowania Twojej aplikacji. Został zaprojektowany tak, aby był szybki, niezawodny i łatwy w użyciu, co czyni go popularnym wyborem wśród programistów i inżynierów QA na całym świecie. Cypress jest napisany w języku JavaScript i wykonuje się w przeglądarce, co czyni go bardzo wydajnym i oferuje niezrównany dostęp do wnętrzności aplikacji.
Kluczowe korzyści z używania Cypress
- Przyjazny dla programistów: Cypress zapewnia czysty i intuicyjny interfejs API, ułatwiając pisanie i debugowanie testów.
- Podróż w czasie: Cypress robi migawki stanu Twojej aplikacji podczas każdego polecenia testowego, pozwalając Ci cofnąć się w czasie i zobaczyć dokładnie, co się wydarzyło w dowolnym momencie.
- Przeładowania w czasie rzeczywistym: Cypress automatycznie przeładowuje się po wprowadzeniu zmian w testach, zapewniając natychmiastową informację zwrotną.
- Automatyczne oczekiwanie: Cypress automatycznie czeka, aż elementy staną się widoczne lub interaktywne przed wykonaniem akcji, eliminując potrzebę jawnych oczekiwań.
- Kontrola sieci: Cypress pozwala na stubbing żądań i odpowiedzi sieciowych, umożliwiając symulowanie różnych scenariuszy i testowanie obsługi błędów w Twojej aplikacji.
- Możliwość debugowania: Cypress zapewnia doskonałe narzędzia do debugowania, w tym potężny debugger i szczegółowe komunikaty o błędach.
- Testowanie między przeglądarkami: Cypress obsługuje wiele przeglądarek, w tym Chrome, Firefox, Edge i Electron.
- Testowanie bezgłowe: Uruchom testy w trybie bezgłowym, aby uzyskać szybsze wykonywanie w środowiskach CI/CD.
- Wbudowane asercje: Cypress zapewnia bogaty zestaw wbudowanych asercji do weryfikacji oczekiwanego zachowania Twojej aplikacji.
Instalacja i konfiguracja
Rozpoczęcie pracy z Cypress jest proste. Oto jak go zainstalować:
- Wymagania wstępne: Upewnij się, że masz zainstalowane Node.js i npm (Node Package Manager) w swoim systemie. Możesz je pobrać z oficjalnej strony internetowej Node.js.
- Zainstaluj Cypress: Otwórz swój terminal lub wiersz poleceń, przejdź do katalogu projektu i uruchom następujące polecenie:
- Otwórz Cypress: Po zakończeniu instalacji możesz otworzyć Cypress Test Runner, uruchamiając:
npm install cypress --save-dev
npx cypress open
To polecenie uruchomi Cypress Test Runner, który zapewnia graficzny interfejs do uruchamiania i debugowania testów.
Pisanie pierwszego testu Cypress
Stwórzmy prosty test, aby sprawdzić, czy strona główna witryny ładuje się poprawnie. Utwórz nowy plik o nazwie `example.cy.js` w katalogu `cypress/e2e` swojego projektu.
// cypress/e2e/example.cy.js
describe('Mój pierwszy test', () => {
it('Odwiedza Kitchen Sink', () => {
cy.visit('https://example.cypress.io')
cy.contains('type').click()
cy.url().should('include', '/commands/actions')
cy.get('.action-email')
.type('fake@email.com')
.should('have.value', 'fake@email.com')
})
})
Przeanalizujmy ten test:
- `describe()`: Definiuje zestaw testów, czyli zbiór powiązanych testów.
- `it()`: Definiuje pojedynczy przypadek testowy w zestawie testów.
- `cy.visit()`: Przechodzi do określonego adresu URL.
- `cy.contains()`: Znajduje element zawierający określony tekst.
- `.click()`: Klika wybrany element.
- `cy.url()`: Pobiera aktualny adres URL strony.
- `.should()`: Dokonuje asercji dotyczącej stanu aplikacji.
- `cy.get()`: Wybiera element za pomocą selektora CSS.
- `.type()`: Wpisuje tekst do wybranego elementu.
- `.should('have.value', 'fake@email.com')`: Asercja, że wartość elementu jest równa 'fake@email.com'.
Uruchom ten test w Cypress Test Runner, aby zobaczyć go w akcji. Powinieneś zobaczyć, jak przeglądarka przechodzi do strony internetowej Cypress Kitchen Sink, klika link „type” i weryfikuje adres URL.
Polecenia Cypress
Cypress udostępnia szeroki zakres poleceń do interakcji z Twoją aplikacją. Oto niektóre z najczęściej używanych poleceń:
- `cy.visit(url)`: Przechodzi do określonego adresu URL.
- `cy.get(selector)`: Wybiera element za pomocą selektora CSS.
- `cy.contains(content)`: Wybiera element zawierający określony tekst.
- `cy.click()`: Klika wybrany element.
- `cy.type(text)`: Wpisuje tekst do wybranego elementu.
- `cy.clear()`: Czyści zawartość elementu input lub textarea.
- `cy.submit()`: Przesyła formularz.
- `cy.check()`: Zaznacza pole wyboru lub przycisk radiowy.
- `cy.uncheck()`: Odznacza pole wyboru.
- `cy.select(value)`: Wybiera opcję z listy rozwijanej.
- `cy.scrollTo(position)`: Przewija stronę do określonej pozycji.
- `cy.trigger(event)`: Uruchamia zdarzenie DOM w wybranym elemencie.
- `cy.request(url, options)`: Wysyła żądanie HTTP do określonego adresu URL.
- `cy.intercept(route, handler)`: Przechwytuje żądania HTTP pasujące do określonej trasy.
- `cy.wait(time)`: Czeka przez określony czas.
- `cy.reload()`: Przeładowuje bieżącą stronę.
- `cy.go(direction)`: Przechodzi do poprzedniej lub następnej strony w historii przeglądarki.
- `cy.url()`: Pobiera aktualny adres URL strony.
- `cy.title()`: Pobiera tytuł strony.
- `cy.window()`: Pobiera obiekt window.
- `cy.document()`: Pobiera obiekt document.
- `cy.viewport(width, height)`: Ustawia rozmiar okna przeglądarki.
To tylko kilka z wielu poleceń dostępnych w Cypress. Zapoznaj się z dokumentacją Cypress, aby uzyskać pełną listę poleceń i ich opcji.
Asercje w Cypress
Asercje służą do weryfikacji oczekiwanego zachowania Twojej aplikacji. Cypress udostępnia bogaty zestaw wbudowanych asercji, których możesz użyć do sprawdzenia stanu elementów, adresu URL, tytułu i innych. Asercje są łączone po poleceniach Cypress za pomocą metody `.should()`.
Oto kilka typowych przykładów asercji:
- `.should('be.visible')`: Asercja, że element jest widoczny.
- `.should('not.be.visible')`: Asercja, że element nie jest widoczny.
- `.should('be.enabled')`: Asercja, że element jest włączony.
- `.should('be.disabled')`: Asercja, że element jest wyłączony.
- `.should('have.text', 'expected text')`: Asercja, że element ma określony tekst.
- `.should('contain', 'expected text')`: Asercja, że element zawiera określony tekst.
- `.should('have.value', 'expected value')`: Asercja, że element ma określoną wartość.
- `.should('have.class', 'expected class')`: Asercja, że element ma określoną klasę.
- `.should('have.attr', 'attribute name', 'expected value')`: Asercja, że element ma określony atrybut i wartość.
- `.should('have.css', 'css property', 'expected value')`: Asercja, że element ma określoną właściwość CSS i wartość.
- `.should('have.length', expected length)`: Asercja, że element ma określoną długość (np. liczbę elementów na liście).
Możesz także tworzyć niestandardowe asercje, aby dopasować je do swoich specyficznych potrzeb.
Najlepsze praktyki dotyczące pisania testów Cypress
Przestrzeganie najlepszych praktyk może pomóc w pisaniu bardziej niezawodnych i wydajnych testów Cypress, łatwiejszych w utrzymaniu. Oto kilka zaleceń:
- Pisz jasne i zwięzłe testy: Każdy test powinien koncentrować się na określonej funkcjonalności lub scenariuszu. Unikaj pisania zbyt złożonych testów, które są trudne do zrozumienia i utrzymania.
- Używaj znaczących nazw testów: Nadawaj swoim testom opisowe nazwy, które jasno wskazują, co testują.
- Unikaj kodowania na sztywno wartości: Używaj zmiennych lub plików konfiguracyjnych do przechowywania wartości, które mogą się zmieniać w czasie.
- Używaj niestandardowych poleceń: Twórz niestandardowe polecenia, aby enkapsulować logikę wielokrotnego użytku i uczynić testy bardziej czytelnymi.
- Izoluj testy: Każdy test powinien być niezależny od innych testów. Unikaj polegania na stanie aplikacji z poprzednich testów.
- Sprzątaj po testach: Zresetuj stan aplikacji po każdym teście, aby upewnić się, że kolejne testy zaczynają się od czystego stanu.
- Używaj atrybutów danych: Używaj atrybutów danych (np. `data-testid`) do wybierania elementów w testach. Atrybuty danych są mniej narażone na zmiany niż klasy CSS lub identyfikatory, co sprawia, że testy są bardziej odporne na zmiany w interfejsie użytkownika.
- Unikaj jawnych oczekiwań: Cypress automatycznie czeka, aż elementy staną się widoczne lub interaktywne. Unikaj używania jawnych oczekiwań (np. `cy.wait()`) chyba że jest to absolutnie konieczne.
- Testuj przepływy użytkowników: Skoncentruj się na testowaniu przepływów użytkowników, a nie poszczególnych komponentów. Pomoże Ci to upewnić się, że Twoja aplikacja działa poprawnie z perspektywy użytkownika.
- Uruchamiaj testy regularnie: Zintegruj testy Cypress z potokiem CI/CD i uruchamiaj je regularnie, aby wychwytywać błędy na wczesnym etapie procesu tworzenia.
Zaawansowane techniki Cypress
Stubbing i Mocking
Cypress pozwala na stubbing żądań i odpowiedzi sieciowych, umożliwiając symulowanie różnych scenariuszy i testowanie obsługi błędów w Twojej aplikacji. Jest to szczególnie przydatne do testowania funkcji, które opierają się na zewnętrznych interfejsach API lub usługach.
Aby stubbować żądanie sieciowe, możesz użyć polecenia `cy.intercept()`. Na przykład poniższy kod stubbuje żądanie GET do `/api/users` i zwraca mockową odpowiedź:
cy.intercept('GET', '/api/users', {
statusCode: 200,
body: [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Doe' }
]
}).as('getUsers')
Następnie możesz poczekać na przechwycone żądanie za pomocą `cy.wait('@getUsers')` i zweryfikować, czy Twoja aplikacja poprawnie obsługuje mockową odpowiedź.
Praca z pamięcią lokalną i plikami cookie
Cypress udostępnia polecenia do interakcji z pamięcią lokalną i plikami cookie. Możesz użyć tych poleceń do ustawiania, pobierania i czyszczenia pamięci lokalnej i plików cookie w swoich testach.
Aby ustawić element pamięci lokalnej, możesz użyć polecenia `cy.window()`, aby uzyskać dostęp do obiektu window, a następnie użyć metody `localStorage.setItem()`. Na przykład:
cy.window().then((win) => {
win.localStorage.setItem('myKey', 'myValue')
})
Aby pobrać element pamięci lokalnej, możesz użyć polecenia `cy.window()`, a następnie użyć metody `localStorage.getItem()`. Na przykład:
cy.window().then((win) => {
const value = win.localStorage.getItem('myKey')
expect(value).to.equal('myValue')
})
Aby ustawić plik cookie, możesz użyć polecenia `cy.setCookie()`. Na przykład:
cy.setCookie('myCookie', 'myCookieValue')
Aby pobrać plik cookie, możesz użyć polecenia `cy.getCookie()`. Na przykład:
cy.getCookie('myCookie').should('have.property', 'value', 'myCookieValue')
Obsługa przesyłania plików
Cypress udostępnia wtyczkę o nazwie `cypress-file-upload`, która upraszcza przesyłanie plików w testach. Aby zainstalować wtyczkę, uruchom następujące polecenie:
npm install -D cypress-file-upload
Następnie dodaj następującą linię do pliku `cypress/support/commands.js`:
import 'cypress-file-upload';
Następnie możesz użyć polecenia `cy.uploadFile()` do przesłania pliku. Na przykład:
cy.get('input[type="file"]').attachFile('example.txt')
Praca z IFrames
Testowanie IFrames może być trudne, ale Cypress zapewnia sposób interakcji z nimi. Możesz użyć polecenia `cy.frameLoaded()` do oczekiwania na załadowanie IFrame, a następnie użyć polecenia `cy.iframe()`, aby pobrać obiekt document IFrame.
cy.frameLoaded('#myIframe')
cy.iframe('#myIframe').find('button').click()
Cypress i ciągła integracja/ciągłe wdrażanie (CI/CD)
Integracja Cypress z potokiem CI/CD jest niezbędna do zapewnienia jakości Twojej aplikacji. Możesz uruchamiać testy Cypress w trybie bezgłowym w swoim środowisku CI/CD. Oto jak:
- Zainstaluj Cypress: Upewnij się, że Cypress jest zainstalowany jako zależność w Twoim projekcie.
- Skonfiguruj CI/CD: Skonfiguruj swój potok CI/CD tak, aby uruchamiał testy Cypress po każdej kompilacji.
- Uruchom Cypress w trybie bezgłowym: Użyj polecenia `cypress run`, aby uruchomić testy Cypress w trybie bezgłowym.
Przykładowa konfiguracja CI/CD (używająca GitHub Actions):
name: Cypress Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
cypress-run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
run: npm install
- name: Cypress run
uses: cypress-io/github-action@v5
with:
start: npm start
wait-on: 'http://localhost:3000'
Ta konfiguracja uruchomi testy Cypress za każdym razem, gdy kod zostanie przesłany do gałęzi `main` lub zostanie utworzone żądanie ściągnięcia względem gałęzi `main`. Akcja `cypress-io/github-action` upraszcza proces uruchamiania testów Cypress w GitHub Actions.
Debugowanie testów Cypress
Cypress udostępnia doskonałe narzędzia do debugowania, które pomogą Ci zidentyfikować i naprawić problemy w testach. Oto kilka wskazówek dotyczących debugowania testów Cypress:
- Używaj Cypress Test Runner: Cypress Test Runner zapewnia wizualny interfejs do uruchamiania i debugowania testów. Możesz przechodzić przez swoje testy polecenie po poleceniu, sprawdzać stan aplikacji i wyświetlać szczegółowe komunikaty o błędach.
- Używaj polecenia `cy.pause()`: Polecenie `cy.pause()` wstrzymuje wykonywanie testu i pozwala sprawdzić stan aplikacji w narzędziach deweloperskich przeglądarki.
- Używaj polecenia `cy.debug()`: Polecenie `cy.debug()` drukuje wybrany element do konsoli, co pozwala sprawdzić jego właściwości i atrybuty.
- Używaj narzędzi deweloperskich przeglądarki: Narzędzia deweloperskie przeglądarki dostarczają bogactwa informacji o Twojej aplikacji, w tym DOM, żądaniach sieciowych i dziennikach konsoli.
- Czytaj uważnie komunikaty o błędach: Cypress udostępnia szczegółowe komunikaty o błędach, które mogą pomóc Ci zidentyfikować przyczynę błędu. Zwróć uwagę na komunikat o błędzie i ślad stosu.
Cypress vs. inne frameworki testowe
Chociaż Cypress jest potężnym frameworkiem testowania end-to-end, ważne jest, aby zrozumieć, jak wypada w porównaniu z innymi popularnymi opcjami. Oto krótki przegląd:
- Selenium: Selenium jest szeroko stosowanym frameworkiem do testowania automatyzacji. Chociaż elastyczny i obsługujący wiele języków, może być skomplikowany w konfiguracji i utrzymaniu. Cypress oferuje prostsze i bardziej przyjazne dla programistów doświadczenie, szczególnie w przypadku aplikacji opartych na JavaScript.
- Puppeteer: Puppeteer to biblioteka Node, która zapewnia interfejs API wysokiego poziomu do sterowania bezgłowym Chrome lub Chromium. Jest doskonały do scrapingu i automatyzacji zadań przeglądarki, ale może wymagać bardziej ręcznej konfiguracji w porównaniu z Cypress do testowania end-to-end.
- Playwright: Playwright to kolejny framework automatyzacji między przeglądarkami, opracowany przez firmę Microsoft. Jest podobny do Puppeteer, ale oferuje szersze wsparcie dla przeglądarek. Cypress ma unikalny debugger podróżujący w czasie i bardziej zintegrowane doświadczenie testowania.
Wybór frameworka zależy od specyficznych potrzeb i wymagań Twojego projektu. Cypress to doskonały wybór dla nowoczesnych aplikacji internetowych, które wymagają szybkiego, niezawodnego i przyjaznego dla programistów testowania end-to-end.
Przykłady Cypress w działaniu w świecie rzeczywistym
Przeanalizujmy kilka przykładów z życia wziętych, jak Cypress może być używany do testowania różnych typów aplikacji internetowych:
Testowanie aplikacji e-commerce
Możesz użyć Cypress do przetestowania różnych przepływów użytkowników w aplikacji e-commerce, takich jak:
- Wyszukiwanie produktów
- Dodawanie produktów do koszyka
- Realizacja transakcji i składanie zamówienia
- Zarządzanie ustawieniami konta
Oto przykład testu Cypress, który weryfikuje, że użytkownik może pomyślnie dodać produkt do swojego koszyka:
it('Dodaje produkt do koszyka', () => {
cy.visit('/products')
cy.get('.product-card').first().find('button').click()
cy.get('.cart-count').should('have.text', '1')
})
Testowanie aplikacji mediów społecznościowych
Możesz użyć Cypress do testowania interakcji użytkownika w aplikacji mediów społecznościowych, takich jak:
- Tworzenie nowego postu
- Polubienie postu
- Komentowanie posta
- Obserwowanie innych użytkowników
Oto przykład testu Cypress, który weryfikuje, że użytkownik może pomyślnie utworzyć nowy post:
it('Tworzy nowy post', () => {
cy.visit('/profile')
cy.get('#new-post-textarea').type('Hello, world!')
cy.get('#submit-post-button').click()
cy.get('.post').first().should('contain', 'Hello, world!')
})
Testowanie aplikacji bankowej
W przypadku aplikacji bankowych Cypress może być używany do testowania krytycznych funkcji, takich jak:
- Bezpieczne logowanie
- Sprawdzanie sald kont
- Przelewy środków
- Zarządzanie odbiorcami
Test weryfikujący przelew środków może wyglądać następująco (z odpowiednim stubbingiem dla bezpieczeństwa):
it('Przelewa środki pomyślnie', () => {
cy.visit('/transfer')
cy.get('#recipient-account').type('1234567890')
cy.get('#amount').type('100')
cy.intercept('POST', '/api/transfer', { statusCode: 200, body: { success: true } }).as('transfer')
cy.get('#transfer-button').click()
cy.wait('@transfer')
cy.get('.success-message').should('be.visible')
})
Wnioski
Cypress to potężny i wszechstronny framework testowania end-to-end, który może pomóc Ci zapewnić jakość i niezawodność Twoich aplikacji internetowych. Jego przyjazny dla programistów interfejs API, potężne funkcje i doskonała wydajność sprawiają, że jest to popularny wybór wśród programistów i inżynierów QA na całym świecie. Postępując zgodnie z najlepszymi praktykami opisanymi w tym przewodniku, możesz pisać skuteczne testy Cypress, które pomogą Ci wychwytywać błędy na wczesnym etapie procesu tworzenia i dostarczać wysokiej jakości oprogramowanie swoim użytkownikom.
Wraz z dalszym rozwojem aplikacji internetowych, znaczenie testowania end-to-end będzie tylko rosło. Przyjęcie Cypress i zintegrowanie go z przepływem pracy programistycznej umożliwi Ci budowanie bardziej solidnych, niezawodnych i przyjaznych dla użytkownika środowisk internetowych.