3 listopada 2024 11 min. czytania

Playwright vs. Cypress - porównanie frameworków do testowania E2E

Szczegółowe porównanie dwóch popularnych frameworków do testowania E2E: Playwright i Cypress. Które z funkcji są porównywalne i który z nich oferuje więcej?

Zaktualizowano: 3 listopada 2024
Złoto-niebieska maska teatralna na czarnym tle
Zdjęcie autorstwa Erdei Richárd

Ostatnio przeniosłem moją stronę na nowy stos technologiczny. Porzuciłem moją starą stronę opartą na Gatsbym i stworzyłem nowy projekt wykorzystując Next.js. Był to spory wysiłek sam w sobie. Zastanawiałem się, czy jest to dobry moment, aby przepisać testy. Testy E2E są abstrakcyjne, więc po migracji musiałbym je dostosować w małym stopniu (albo wcale). Jednakże, zamiast zmieniać rzeczy stopniowo - jak normalny człowiek - zmieniłem wszystko jednocześnie, włączając testy. Zajęło mi to sporo czasu, ale skończyłem mając dwa zestawy testów E2E - w Cypress'ie i Playwright'cie. Postanowiłem, że wykorzystam tę okazję i porównam te dwa frameworki.

Playwright

Playwright to współczesna biblioteka do testowania rozwijana przez Microsoft i wydana w 2020 roku. Zespół. który początkowo pracował nad innym narzędziem do automatyzacji, Puppeteer'em, stworzył Playwright'a. "Chwila, moment, czy Puppeteer nie jest od Google?". Jest, ale ten zespół przeniósł się z Google do Microsoftu. Także jest to kolejne narzędzie od Microsoftu do twojego stosu technologicznego, gdybyś jeszcze nie miał ich wystarczająco wiele.

Playwright składa się z dwóch części:

  • Playwright Library, która udostępnia zunifikowane API do uruchamiania i interakcji z przeglądarkami.
  • Playwright Test, który dostarcza to API wraz z test runnerem, którym możesz w pełni zarządzać.

Pomimo, że Playwright istnieje na rynku krócej niż Cypress, to zgromadził już ponad 66k gwiazdek na GitHub'ie (w porównaniu do 47 tysięcy Cypress'a). Myślę, że istnieje dobry powód stojący za tą popularnością. Playwright oferuję pełny parytet funkcji z Cypress'em, a nawet więcej.

Cypress

Cypress, framework do testowania E2E aplikacji internetowych, został pierwszy raz wydany we wrześniu 2017 roku. Od czasu wydania zdobył znaczącą popularność wśród społeczności deweloperów, gromadząc ponad 40 000 gwiazdek na GitHub'ie. Framework ten jest rozwijany i utrzymywany przez doświadczonych deweloperów i inżynierów, włączając Gleba Bahamutova. Wielokrotnie wpadałem na jego posty dotyczące testowania - dobre rzeczy. Cypress jest nadal głównym wyborem dla wielu deweloperów szukających frameworka E2E.

Playwright vs. Cypress

Przejdźmy do mięsa tego posta - porównania. Stworzyłem tabelę wyróżniającą wiele funkcjonalności, których możesz się spodziewać po współczesnym narzędziu do testowania E2E. Tabela może być przydatna per se, ale przyjrzę się każdej funkcjonalności z osobna i dodam kontekst. Zacznę od "więcej", gdzie Playwright oferuje ekstra funkcjonalności, a później przejdę do parytetu funkcji.

FunkcjonalnośćPlaywrightCypress
Język programowaniaJS/TSJS/TS
Inne językiWspieraneNie wspierane
ParalelizacjaDarmowaPłatna
PrzeglądarkiWsparcie dla wieluWsparcie dla wielu
Inne test runneryWspieraneNie wspierane
Wiele kartWspieraneNie wspierane
Generacja koduWspieraneNie wspierane
DesignHeadlessGUI
WydajnośćSzybszaWolniejsza
<iframe>WspieraneWspierane
Interakcje z dialogamiWspieraneWspierane
Plugin do VSCOficjalnySpołeczności
SkładniaPrzypominająca ES6Przypominająca jQuery
Interakcje z elementamiWspieraneWspierane
Auto-waitWspieraneWspierane
Shadow DOMWspieraneWspierane
Testowanie APIWspieraneWspierane
DokumentacjaDobraDobra

Języki programowania

Playwright wspiera TypeScripta "prosto z pudełka". Możesz go zainstalować i od razu pisać testy zabezpieczone typami. JavaScript też jest oczywiście wspierany. Jeżeli używasz Cypress'a, to w domyśle piszesz testy używając języka JavaScript. Jednakże możesz używać Cypress'a wraz z TypeScriptem, gdy dostarczysz odpowiednią konfigurację.

Inne języki

Poza JavaScriptem, Playwright wspiera inne języki programowania, takie jak Python, C# lub Java. Dla mnie nie ma to większego znaczenia, bo i tak tworzę tę stronę w ekosystemie JavaScript. Ale wyobrażam sobie, że wykorzystywanie jednego frameworka do testowania przez cały zespół - front-end i back-end - może być plusem. Będąc przy temacie - poważnie rozważałem, czy powinienem zakwalifikować wsparcie dla Javy jako plus (JavaScript deweloper srający na Javę - o ironio). Cypress nie wspiera (i prawdopodobnie tak pozostanie) innych języków programowania.

Paralelizacja

W domyśle, Playwright uruchamia pliki testowe równolegle. Odpala kilka procesów, które działają jednocześnie. Testy w pojedynczym pliku są uruchamiane po kolei, ale możesz nawet zrównoleglić testy w jednym pliku. Paralelizacja jest płatną funkcjonalnością w usłudze Cypress Cloud.

Przeglądarki

Paralelizacja pomaga w testach wielu przeglądarek. Playwright wprowadza koncept "projektów", gdze każdy z nich może służyć jako odrębna przeglądarka, włączając Safari.

Definiowanie projektów w PlaywrightTS
1projects: [
2 {
3 name: 'chromium',
4 use: { ...devices['Desktop Chrome'] }
5 },
6 {
7 name: 'firefox',
8 use: { ...devices['Desktop Firefox'] }
9 },
10 {
11 name: 'webkit',
12 use: { ...devices['Desktop Safari'] }
13 },
14 {
15 name: 'Mobile Chrome',
16 use: { ...devices['Pixel 5'] }
17 },
18 {
19 name: 'Mobile Safari',
20 use: { ...devices['iPhone 12'] }
21 }
22]

Współczesny Internet Explorer może wprowadzać egzotyczne problemy, więc istotne jest, aby go wspierać. Playwright umożliwia bardzo łatwą, globalną konfigurację różnych projektów. Z drugiej strony, Cypress sprawia trochę kłopotów. Poniżej jest fragment mojej akcji GitHub, która uruchamia wiele przeglądarek.

GitHub action uruchamiająca wiele przeglądarek w CypressYAML
1e2e-test-chrome:
2 runs-on: ubuntu-latest
3 strategy:
4 matrix:
5 node: [16]
6 needs: build
7 steps:
8 - name: Checkout commit
9 uses: actions/checkout@v3
10 - name: Use Node ${{ matrix.node }}
11 uses: actions/setup-node@v3
12 with:
13 node-version: ${{ matrix.node }}
14 cache: npm
15 - name: Install dependencies
16 run: npm ci --legacy-peer-deps
17 - name: Restore Cypress binary
18 uses: actions/cache@v3
19 id: cache-cypress
20 with:
21 path: ~/.cache/Cypress
22 key: cypress-binary-${{ hashFiles('**/package-lock.json') }}
23 restore-keys: |
24 cypress-binary-
25 - name: Download build artifacts
26 uses: actions/download-artifact@v3
27 with:
28 name: build-output
29 - name: Run Cypress
30 uses: cypress-io/github-action@v4
31 with:
32 start: npm run serve
33 wait-on: 'http://localhost:8000'
34 browser: chrome
35 install: false
36 e2e-tests-firefox:
37 runs-on: ubuntu-latest
38 strategy:
39 matrix:
40 node: [16]
41 needs: build
42 steps:
43 - name: Checkout commit
44 uses: actions/checkout@v3
45 - name: Use Node ${{ matrix.node }}
46 uses: actions/setup-node@v3
47 with:
48 node-version: ${{ matrix.node }}
49 cache: npm
50 - name: Install dependencies
51 run: npm ci --legacy-peer-deps
52 - name: Restore Cypress binary
53 uses: actions/cache@v3
54 id: cache-cypress
55 with:
56 path: ~/.cache/Cypress
57 key: cypress-binary-${{ hashFiles('**/package-lock.json') }}
58 restore-keys: |
59 cypress-binary-
60 - name: Download build artifacts
61 uses: actions/download-artifact@v3
62 with:
63 name: build-output
64 - name: Run Cypress
65 uses: cypress-io/github-action@v4
66 with:
67 start: npm run serve
68 wait-on: 'http://localhost:8000'
69 browser: firefox
70 headed: true
71 install: false

Nie ma tu Safari, ponieważ Cypress przez długi czas nie wspierał Safari. Dopiero niedawno otrzymał eksperymentalne wsparcie dla Webkit'a (silnik Safari).

Inne test runnery

Playwright Test to dedykowany test runner dla tego frameworka. Jednakże, dodając kilka lini kodu, możesz podpiąć Playwright'a do innych, istniejących runnerów, takich jak Jest, Mocha czy AVA. Cypress nie wspiera zewnętrznych test runnerów.

Wiele kart

Playwright wykorzystuje BrowserContext, który umożliwia operowanie wieloma, niezależnymi sesjami przeglądarek. Możesz w łatwy sposób pisać testy, które wchodzą w interakcję z wieloma kartami. Cypress uruchamiany jest wewnątrz przeglądarki, dlatego nie wspiera wielu kart.

Generacja kodu

Nie nazwałbym tego najistotniejszą funkcjonalnością, ale jest fajna. Playwright pozwala generować kod. Rozpoczynasz nagrywanie, klikasz w swojej aplikacji i, dla przykładu, Playwright generuje dla ciebie odpowiednie lokatory (jest to sposób na odnalezienie elementu na stronie, podobny do JavaScriptowych selektorów). Raczej nie wygeneruje ci produkcyjnego kodu, ale jest to dobry punkt startowy. Cypress nie oferuje analogicznej funkcjonalności.

Wydajność

Z drugiej strony, wydajność jest istotna dla większości ludzi. Playwright bezpośrednio wchodzi w interakcję z przeglądarką wykorzystując protokół Chrome dev tools, co przekłada się na lepszą wydajność. Wykorzystałem mój zestaw bliźniaczych testów i przetestowałem wydajność. Testowałem wykorzystując UI i przeglądarkę Chromium w obu frameworkach. Aby uniknąć odstających wyników, każdy z testów uruchomiłem wielokrotnie i wziąłem średni czas. Dla Cypress'a, jest to całkowity czas, a dla Playwright'a wziąłem czas najdłuższego testu, ponieważ są one uruchamiane równolegle.

TestyPlaywrightCypress
Internacjonalizacja~1.425s~4.5s
Dostępność~2.1s~5.5s
Subskrypcja~870ms~4.25s
Nawigacja~1.2s~4s

Oczywiście zależy to od wielu czynników, ale możemy przyjąć, że Playwright jest z grubsza 3-4 razy szybszy niż Cypress.

Wsparcie dla iframe

Strona w Playwright wystawia aktualny frame tree poprzez odpowiednie metody. Masz dostęp do elementów iframe prosto po wyjęciu z cyfrowego pudełka. Cypress także wspiera elementy iframe, ale wymaga dodatkowego pluginu.

Okna dialogowe

Podobna historia dotyczy natywnych, przeglądarkowych okien dialogowych. Playwright automatycznie je pomija, ale możesz zarejestrować handler i je łatwo zaakceptować. Cypress także może je obsłużyć wykorzystując eventy, ale kod wtedy zależy od rodzaju okna dialogowego.

Plugin do VSC

Oba frameowrki oferują wspierające pluginy do edytora Visual Studio Code. Microsoft rozwija oficjalny plugin do Playwright'a. Używając Cypress'a, musisz się zadowolić pluginami od społeczności.

Składnia

Preferencje składniowe są subiektywne, więc ciężko wskazać tutaj zwycięzcę. Playwright oferuje składnię podobną do współczesnego, asynchronicznego JavaScriptu ES6, z wieloma słowami kluczowymi async i await. Testy Cypress'a przypominają składnią jQuery, z łańcuchami metod. Poniżej prezentuję test E2E napisany dla obu frameworków.

Test subskrypcji w PlaywrightTS
1import { test, expect } from './fixtures'
2
3test.describe('Subscription tests', () => {
4 test('checks the successful flow', async ({ page, settingsPage }) => {
5 const { section } = await settingsPage.getDictionary('en')
6 const formURL = await settingsPage.getFormURL('en')
7
8 await page.route(formURL, (route) =>
9 route.fulfill({
10 status: 200,
11 contentType: 'application/json',
12 body: JSON.stringify({ status: 'success' })
13 })
14 )
15 await page.goto(settingsPage.link.home)
16
17 const input = page.getByLabel(section.newsletter.email)
18 const button = page.getByRole('button', { name: section.newsletter.button })
19
20 await expect(input).toHaveAttribute('required')
21 await expect(input).toHaveAttribute('type', 'email')
22 await expect(input).toHaveAttribute('autocomplete', 'off')
23
24 await input.fill(settingsPage.example.email)
25 await button.scrollIntoViewIfNeeded()
26 await button.click()
27
28 await expect(
29 page.getByText(section.newsletter.success.heading)
30 ).toBeVisible()
31 })
32
33 // More test cases
34})
Test subskrypcji w CypressJS
1/// <reference types="Cypress" />
2import { icon } from '../fixtures/theme.json'
3import { form, user } from '../fixtures/subscription.json'
4
5describe('Subscription tests', () => {
6 beforeEach(() => {
7 cy.visit('/blog/hello-world/')
8 cy.findByTestId(icon).should('exist')
9 cy.findByPlaceholderText(form.email)
10 .as('email')
11 .should('have.prop', 'type', 'email')
12 .and('have.prop', 'required')
13 cy.findByRole('button', { name: form.button }).as('button')
14 })
15
16 it('Tests success flow', () => {
17 cy.intercept(form.url, (req) => {
18 expect(req.body).to.include('email_address')
19 expect(req.body).to.include(user.email)
20 req.reply({
21 statusCode: 200,
22 body: {
23 status: 'success'
24 }
25 })
26 })
27 cy.get('@email').type(user.email, { delay: 50 })
28 cy.get('@button').click()
29 cy.findByText(form.success, { exact: false }).should('be.visible')
30 })
31
32 // More test cases
33})

Design

W tej sekcji, odnoszę się do ogólnego projektu frameworka. Playwright zaprojektowany jest "bez głowy" - graficzny interfejs użytkownika to tylko dodatek. Nie musisz nic konfigurować, żeby uruchomić Playwright'a na serwerze CI. Istnieje flaga, aby uruchomić go w trybie GUI.

🔴 🟡 🟢
npx playwright test --ui

Cypress jest zaprojektowany w myśl przeciwnej filozofii. Graficzny interfejs jest w centrum doświadczenia. Możesz dostosować konfigurację, aby uruchomić Cypress'a na serwerze CI.

Interakcja z elementami

Zarówno Playwright jak i Cypress oferują dobre API do interakcji z elementami DOM. Playwright wprowadza lokatory. Jest to sposób, aby w dowolnym momencie znaleźć elementy na stronie. Każdy kto kiedykolwiek używał Testing Library, będzie się tu czuł jak w domu.

Interakcja z elementami w PlaywrightTS
1await page.getByRole('button', { name: 'Submit' }).click()

W Cypress'ie, do łapania za elementy służy funkcja get. Istnieje też sposób, aby dodawać znaczące nazwy do elementów wykorzystując aliasy.

Interakcja z elementami w CypressJS
1cy.get('button[type=submit]').as('submitBtn')
2
3cy.get('@submitBtn').click()

Auto-wait

Odnosząc się do poprzedniej sekcji, oba frameworki automatycznie zaczekają na te elementy (w przeciwieństwie do Selenium). Funkcja ta pomaga w testowaniu współczesnych, dynamicznych interfejsów użytkownika, gdzie komponenty są często dołączane i odłączane od DOM-u. Dzięki temu, testy mają tendencję do bycia mniej "flaky".

Mem w którym mama ignoruje tonące dziecko. Playwright jest wybrany. Cypress tonie. Selenium utonął już dawno temu.

Shadow DOM

Będąc przy komponentach, lokatory Playwright'a domyślnie będą działały z elementami w shadow DOM. Jest to konieczne, jeżeli twoja aplikacja wykorzystuje te natywne, niestandardowe komponenty. Cypress także może wchodzić w interakcję z tymi elementami "cieniowego" DOM-u. Jednakże, w tym celu, musisz wywoływać dodatkową metodę.

Testowanie API

Poza testowaniem interfejsów użytkownika, oba frameworki umożliwiają testowanie interfejsów API. Playwright może uzyskać dostęp do twojego REST API. Jest to pomocne, jeżeli chcesz przetestować serwer API albo przygotować odpowiedź serwera przez odwiedzeniem aplikacji. Cypress także dostarcza dobre doświadczenie jeżeli chodzi o testowanie API.

Dokumentacja

Oba frameworki posiadają dogłębną i szeroką dokumentację techniczną. Podczas pracy z nimi, rzadko czułem potrzebę zaglądania do innych źródeł. Ciężko wskazać konkretny powód, ale preferuję dokumentację Cypress'a. Może to przez estetykę? I nie zrozum mnie źle - Playwright ma dobrą dokumentację. Szybko zacząłem i przepisałem moje testy z jej wykorzystaniem. Ale ma ona twardą konkurencję - dokumentacja Cypress'a jest po prostu bardzo dobra.

Podsumowanie

Nie będzie tu żadnych zwrotów akcji, bo już na początku napisałem, że przepisałem moje testy do Playwright'a. Dlatego znasz już mój wybór. Mam nadzieję, że po przeczytaniu tego posta znasz także powody stojące za tą decyzją. Playwright oferuje pełny parytet funkcjonalności względem Cypress'a i dodatkowe funkcjonalności, jak paralelizacja czy wsparcie dla wielu kart, które są dla mnie przydatne. Jednakże, po napisaniu tego wszystkiego, nadal uważam, że Cypress to bardzo dobry wybór. Jego popularność to nie przypadek. A co z tobą - który z frameworków wybierasz?

Newsletter, który rozpala ciekawość💡

Subskrybuj mój newsletter, aby otrzymywać comiesięczną dawkę:

  • Nowości, przykładów, inspiracji ze świata front-end, programowania i designu
  • Teorii naukowych i sceptycyzmu
  • Moich ulubionych źródeł, idei, narzędzi i innych interesujących linków
Nie jestem nigeryjskim księciem, aby oferować ci okazje. Nie wysyłam spamu. Anuluj kiedy chcesz.

Pozostań ciekawy. Przeczytaj więcej

Połowa winyla na białym tle1 września 20227 min. czytania

Dostępne animacje w React

Czyli jak nie kręcić swoimi użytkownikami (jak winylem). Niektóre animacje mogą powodować problemy u użytkoników. Zadbamy o nich i sprawimy, że nieistotne animacje będą opcjonalne.

Czytaj wpis
Zdjęcie zmiennych CSS w edytorze Visual Studio Code14 września 20227 min. czytania

Konwertowanie tokenów projektowych na zmienne CSS z Node.js

Konwertowanie tokenów projektowych jest procesem podatnym na błędy - przekonałem się o tym na własnej skórze. Dlatego stworzyłem prosty skrypt dla środowiska Node.js, który pomoże mi z tym zadaniem.

Czytaj wpis
Pięć metalowych kół zębatych na czarnym tle23 września 202210 min. czytania

Gatsby z Netlify CMS

W tym wpisie przyjrzymy się bliżej Netlify CMS. Jest to przykład CMSa nowego typu, który jest oparty o Git. Zintegrujemy go z przykładowym projektem Gatsby.

Czytaj wpis