Koszyk (0)
Fundacja CODE:ME · 26 sierpnia 2025

Playwright czy Cypress: co wybrać do automatyzacji testów w 2025 roku?

Często się zastanawiamy: jak złapać każdy błąd w aplikacji? Testy end-to-end sprawdzają wszystko od kliknięcia w UI aż po zapytania do backendu. Dla JavaScriptu dwa narzędzia są dziś najczęściej wybierane do tego celu: Playwright i Cypress i dzisiaj się im przyjrzymy.

playwright czy cypress

Dwa najpopularniejsze narzędzia do testów E2E pisanych w JavaScripcie to: Playwright od Microsoftu i Cypress rozwijany przez społeczność oraz firmę Cypress.io. Oba są popularne, aktywnie rozwijane i wspierane przez swoje społeczności. Oba działają w środowisku JavaScript i pozwalają pisać testy, które symulują działania użytkownika. Chociaż mają podobieństwa, to głębiej różnią się podejściem, architekturą i możliwościami. Te różnice warto dobrze rozumieć przed wybraniem konkretnego narzędzia do swojego projektu. W 2025 na start wybralibyśmy Playwright, a dlaczego? Zapraszamy do lektury artykułu!

Architektura i sposób działania

Zacznijmy od podstaw. Cypress i Playwright różnią się fundamentalnie w podejściu do testowania. Różnice zaczynają się od tego, jak testy są uruchamiane.

Cypress

Cypress wstrzykuje kod testów bezpośrednio do przeglądarki, w której działa testowana aplikacja. Kod testów Cypress działa w tym samym kontekście co testowana aplikacja, jest wstrzykiwany bezpośrednio do przeglądarki jako dodatkowy skrypt. W praktyce oznacza to, że

  •  test ma pełny dostęp do DOM aplikacji, może reagować na zdarzenia, modyfikować styl, przerywać wykonywanie kodu – jak DevTools.
  • z drugiej strony nie może kontrolować przeglądarki jako takiej – nie otworzy nowej karty, nie zmieni ustawień systemowych, nie przechwyci plików do pobrania.

Mówiąc prościej, to oznacza, że test i aplikacja „żyją” w tym samym środowisku. Mają wspólny kontekst DOM, wspólną sesję JavaScript i wspólny czas życia. Dzięki temu Cypress może w łatwy sposób podglądać zmienne, sprawdzać DOM w czasie rzeczywistym, a debugowanie jest bardzo wygodne: widzimy aplikację i test jednocześnie, możemy cofać kroki, analizować błędy wizualnie. To właśnie ta cecha sprawiła, że Cypress szybko zdobył popularność w zespołach frontendowych.

Playwright

Playwright działa zupełnie inaczej. Testy uruchamiane są poza przeglądarką, jako osobny proces Node.js (lub innego języka: Python, Java, .NET). Test nie jest częścią aplikacji, a jest „pilotem”, który z zewnątrz steruje przeglądarką

Jak to z zewnątrz? Dzięk temu, że robi to przez poprzez API. Działa na poziomie procesów przeglądarki, nie w ramach strony. To oznacza:

  • testy mają pełną kontrolę nad przeglądarką: mogą otwierać nowe karty, okna, emulować urządzenia, ustawiać język systemu, przechwytywać ruch sieciowy,
  • komunikacja z aplikacją odbywa się przez API, nie przez bezpośredni dostęp do DOM (choć interakcje z DOM-em są możliwe).

To podejście pozwala Playwrightowi robić rzeczy, których Cypress nie potrafi: otwierać nowe zakładki, testować pop’upy, zarządzać wieloma sesjami jednocześnie, przechwytywać i modyfikować ruch sieciowy, ujmować w teście odpowiedzi z zewnętrznych źródeł, a także dokładnie emulować różne środowiska użytkownika (np. Safari na iOS).

Z tego powodu Playwright świetnie nadaje się do testowania bardziej złożonych scenariuszy: wielosesyjnych, wielookienkowych, wymagających konfiguracji środowiska.

 

Obsługa przeglądarek

Obsługa przeglądarek czyli kto testuje więcej, kto realnie wspiera Safari?

W testach E2E kluczowe jest, na jakich silnikach uruchomimy nasze skrypty. Bez wsparcia dla Safari, nie sprawdzimy zachowania na iOS. 

Cypress domyślnie wspiera Chromium (Chrome, Edge). Wersja Firefox jest eksperymentalna i czasem wymaga dodatkowej konfiguracji. WebKit (czyli silnik Safari) działa z ograniczeniami lub wcale. W praktyce oznacza to, że w Cypressie sprawdzimy zachowanie aplikacji głównie w przeglądarkach opartych na Chromium.

Playwright idzie dalej. W jednym pakiecie dostajemy trzy silniki:

  • Chromium (Chrome, Edge)
  • Firefox
  • WebKit (Safari na macOS i iOS)

Instalacja wszystkich sterowników trwa chwilę, ale podstawowa instalacja Playright wygląda o tak komendą:

npx playwright install

Potem w konfiguracji playwright.config.js decydujemy, które projekty włączyć:

module.exports = {
  projects: [
    { name: 'chromium', use: { browserName: 'chromium' } },
    { name: 'firefox',  use: { browserName: 'firefox' } },
    { name: 'webkit',   use: { browserName: 'webkit' } },
  ],
};

Dzięki temu uruchomimy testy w Safari bez dodatkowych hacków. Playwright pozwala też emulować (czyli “udawać”) urządzenia mobilne, ustawiać język systemu czy geo lokalizację – wszystko w tej samej sesji. Czym to konkret pomaga? W realnym projekcie często pojawiają się błędy na mobilnych Safari. Playwright wychwytuje je od razu. W Cypressie musielibyśmy sięgnąć po zewnętrzne narzędzia lub ominąć testy na WebKit (np. później wykonać je jako fazę testów manualnych).

 

API testowe i DSL

Przejdziemy teraz do tego, co najbardziej wpływa na czytelność i wygodę pisania testów – czyli składni i sposobu definiowania kroków.

Cypress

W Cypressie testy piszemy łańcuchowo, bez async/await. Każda komenda trafia do kolejki, a framework sam dba o oczekiwanie i retry. Wygląda to tak:

cy.visit('/login')
cy.get('input[name="username"]').type('user1')
cy.get('input[name="password"]').type('pass123')
cy.get('button[type="submit"]').click()
cy.url().should('include', '/dashboard')

Co nam daje Cypress?

Automatyczne czekanie: każda komenda jest ponawiana do chwili, gdy element się pojawi lub do limitu czasu (domyślnie 4 s).

Czytelność: kod przypomina instrukcję obsługi. Nie mieszamy obietnic ani callbacków.

Assercje w linii: metoda should pozwala wprost po akcji sprawdzić stan strony.

Playwright

W Playwright działamy w stylu async/await. Test uruchamia proces Node.js i steruje przeglądarką przez API. Przykład:

const browser = await playwright.chromium.launch()
const page = await browser.newPage()

await page.goto('/login')
await page.fill('input[name="username"]', 'user1')
await page.fill('input[name="password"]', 'pass123')
await page.click('button[type="submit"]')

await expect(page).toHaveURL(/\/dashboard/)

await browser.close()

Jawne oczekiwanie: choć Playwright auto-czeka na elementy, każdy krok to obietnica, którą wywołujemy await.

Elastyczne asercje: expect(page).toHaveURL() czy toHaveText() dają więcej kontroli nad timeoutami i retry.

Timeouty i retrie: ustawia się je globalnie lub przy każdej metodzie, np. await page.click(selector, { timeout: 5000 }).

Selekcja elementów także różni się u obu narzędzi. Cypress korzysta z klasycznych selektorów CSS (XPath możliwy przez plugin). Playwright wprowadza obiekt Locator, który łączy różne strategie:

const loginButton = page.locator('button', { hasText: 'Log in' })
await loginButton.click()

 

Wygląda to tak, że twórcy Playwright odbyli lekcję bolączek testerów z innych frameworków i znaleźli rozwiązanie. Dzięki Locator łatwiej diagnozować problemy – w narzędziach deweloperskich Playwright podświetla dokładnie ten element, który próbuje znaleźć.

Natomiast w przypadku przechwytywania ruchu sieciowego, nie znajdziemy już znacznych różnic. Oba w praktyce dają te same możliwości jak przechwycić żądanie, zminieć odpowiedź (stub/mock, czy kontrolować status, nagłówki i body. To co w Cypress spotkamy jako cy.intercept() znajdziemy również w innej składni, ale z podobną funkcjonalnością jako page.route()w Playwright. 

Równoległość, skalowanie i izolacja

Gdy testów przybywa, chcemy je uruchamiać jednocześnie i w czystych środowiskach. Oba narzędzia izolują testy: każdy plik startuje w oddzielnym kontekście, z wyczyszczonymi ciasteczkami i localStorage. W Cypress izolacja jest domyślna. Flaga –parallel rozdziela testy na wiele maszyn, ale wymaga Dashboard Service lub własnego CI. Dashboard zbiera wyniki i przydziela zadania. Playwright natomiast sam skaluje testy przez liczbę workerów wbudowaną w CLI. Domyślnie workerów jest tyle, ile rdzeni CPU. Każdy worker to wątek z własnym kontekstem przeglądarki. Workery nie współdzielą ciasteczek ani storage. Ustawiamy liczbę workerów przez workers w pliku playwright.config.js.

Dlaczego na początku padło, że w 2025 zaczęlibyśmy od Playwright?

Wracając do początkowego stwierdzania, oczywiście w fundacji CODE:ME prowadzimy kurs Playwrighta. Nie polecamy go tylko dlatego, że mamy kurs, wręcz przeciwnie, organizujemy kurs, bo uważamy, że to dobry start w testach E2E. Testerzy sami cenią Playwright, a jego popularność wśród inżynierów testów rośnie obecnie szybciej niż Cypressa. W ofertach pracy coraz częściej pojawia się wymóg znajomości Playwrighta. Pozycja Cypressa pozostaje stabilna, ale nowe projekty częściej sięgają po Playwrighta niż Cypressa, co będzie powodowało, że ten drugi zacznie tracić użytkowników. Playwright daje jasny model testów i prostą emulację środowisk mobilnych. Dlatego my zaczynamy od Playwrighta!

Sprawdź szczegóły kursu!


Powrót do bloga