Biblioteki do testów end to end: Playwright vs Cypress w realnych scenariuszach CI

0
51
3.7/5 - (3 votes)

Nawigacja:

Od czego startujesz: jaki masz cel i kontekst projektu?

Jakiego rodzaju ścieżki chcesz pokryć testami end to end?

Bez jasnego celu żadne narzędzie do testów end to end w CI nie będzie „dobre”. Zanim zestawisz Playwright vs Cypress, warto zadać sobie kilka niewygodnych pytań. Co chcesz osiągnąć: szybki feedback dla deweloperów, pełną regresję przed wydaniem, czy pilnowanie tylko kilku krytycznych ścieżek? Czy Twoje testy mają chronić przed oczywistymi regresjami, czy też odtwarzać pełne, złożone procesy biznesowe z wieloma krokami i integracjami?

Jeśli celem jest happy path – kilka scenariuszy typu „logowanie, zakup, płatność” – ciężar spada bardziej na prostotę i szybkość konfiguracji w CI. Przy pełnej regresji (dziesiątki lub setki scenariuszy) ważniejsze staje się skalowanie, równoległe uruchamianie i narzędzia do debugowania flaków. Wtedy różnice między Playwright i Cypress w pipeline’ach CI stają się bardzo wyraźne.

Zastanów się: czy testy E2E mają być częścią codziennego feedbacku na każdej gałęzi, czy raczej bramką jakości na release branch? Jeśli planujesz pełny zestaw testów na każdym pushu, czas wykonania i parallelism są krytyczne. Jeśli stawiasz na nocne buildy z dłuższymi zestawami, ważniejsze będą odporność na flaki i wygodne debugowanie problemów po czasie.

Rodzaj aplikacji: SPA, microfrontends, SSR, legacy

Techniczny charakter aplikacji mocno wpływa na to, jak cierpliwe musi być narzędzie testowe i jak trudne będą selektory. SPA w stylu React/Angular/Vue z dynamicznym DOM, lazy loadingiem i skeletonami wymaga dobrego auto-wait oraz świadomego podejścia do selektorów semantycznych (role, tekst, data-testid). Playwright mocno inwestuje w locatory i autowait, Cypress z kolei oferuje prostą, znajomą składnię dla świata frontendu JS/TS.

Przy SSR (Next.js, Nuxt, Nest + templaty) często pojawia się potrzeba testów w różnych stanach autoryzacji oraz pracy z cookies, nagłówkami i cache. W microfrontendach i legacy (np. jQuery, wielkie JSP/Thymeleaf) problemem bywa brak spójnych identyfikatorów. Zadaj sobie pytanie: jak wiele kontroli nad HTML i atrybutami testowymi ma zespół? Jeśli możesz wprowadzać data-testid, oba narzędzia będą szczęśliwe. Jeśli nie – Playwright z mocniejszym podejściem do role/accessible-name może ułatwić utrzymanie.

Przy microfrontendach istotna jest też współpraca kilku zespołów. Cypress często bywa wybierany, gdy front-endowcy chcą mieć testy blisko kodu w tym samym repo i pisać je w znanym ekosystemie. Playwright, dzięki wsparciu wielu języków (JS/TS, Python, Java, .NET), lepiej integruje się w środowisku, gdzie QA lub backend też piszą testy E2E.

Skala zespołu, repo i model release’ów

Czy prowadzisz kameralny projekt z 3–5 deweloperami, czy pracujesz w monorepo z kilkunastoma zespołami i osobną infrastrukturą CI? Skala decyduje o tym, jak bolesne będą wąskie gardła pipeline’u. W małym repo pipeline z kilkoma minutami testów E2E przejdzie bez bólu. W monorepo, gdzie każdy merge uruchamia testy wielu aplikacji, każda minuta ma cenę.

Przy monorepo i wielozespołowej współpracy docenisz:

  • możliwość łatwego dzielenia zestawów testów na joby CI,
  • proste raportowanie i agregację wyników w jednym miejscu,
  • deterministyczne uruchamianie (brak ukrytych zależności między testami).

Playwright z domyślną izolacją kontekstu przeglądarki na test najczęściej lepiej znosi duże pakiety testów. Cypress, jeśli jest dobrze napisany (brak współdzielonego stanu, świadome „resetowanie” między testami), również sobie poradzi. Pytanie do Ciebie: czy masz w zespole kogoś, kto przypilnuje dyscypliny testowej i porządku w strukturze speców?

Ograniczenia infrastruktury CI: SaaS, on‑prem, Docker, Kubernetes

Playwright i Cypress w realnych scenariuszach CI różnią się głównie tym, jak łatwo je uruchomić w kontenerach i jak radzą sobie z instalacją przeglądarek. Jeśli używasz GitHub Actions, GitLab CI SaaS, CircleCI, Bitbucket Pipelines – najprościej będzie skorzystać z gotowych obrazów Docker:

  • Playwright: oficjalne obrazy z wbudowanymi przeglądarkami (mcr.microsoft.com/playwright),
  • Cypress: oficjalne obrazy cypress/included z odpowiadającą wersją Cypress i Chrome.

W on‑prem z własnym Jenkinsem, Azure DevOps Server czy TeamCity dojdziesz szybko do pytania: czy instalujemy przeglądarki na agentach, czy pakujemy wszystko w Dockerze? Playwright zwykle promuje podejście „all-in-one” w kontenerze; Cypress ma dłuższą historię w świecie Node/Chrome i sporo gotowych workflowów. Jeśli Twoje CI nie ma dobrego wsparcia dla Docker/Kubernetes, prostota instalacji może przeważyć szalę.

Co już próbowałeś i jakie masz blizny po poprzednich narzędziach?

Jeśli przychodzisz z Selenium, Puppeteera albo „braku E2E”, Twoje oczekiwania mogą być zupełnie inne niż zespołu, który żyje z Cypress od lat. Zastanów się:

  • czy twoje poprzednie testy cierpiały na flaki związane z czekaniem na elementy i sieć,
  • czy debugowanie w CI było koszmarem (brak zrzutów, brak wideo),
  • czy główny ból to czas wykonania, czy niestabilność.

Playwright stawia na stabilność, deterministyczne autowait i narzędzia jak Trace Viewer. Cypress inwestuje w developer experience, świetnego runnera lokalnego i integrację z ekosystemem front-endowym. Jeśli bolą cię flaki i nieprzewidywalność – Playwright często daje większe poczucie kontroli. Jeżeli najbardziej zależy ci, by każdy frontendowiec mógł w 10 minut napisać pierwsze testy i odpalić je lokalnie z podglądem – Cypress nadal jest bardzo wygodny.

Programista przy biurku testuje aplikację na laptopie i monitorze
Źródło: Pexels | Autor: Jakub Zerdzicki

Krótkie portrety narzędzi: filozofia Playwright i Cypress

Filozofia Playwright: multi‑browser, stabilność i izolacja

Playwright powstał jako odpowiedź na bolączki testów przeglądarkowych: brak spójności między browserami, flaki wynikające z asynchroniczności i trudność w diagnozowaniu błędów. Jego główne założenia to:

  • multi‑browser z jednego API – Chromium, Firefox, WebKit w headless i headed,
  • multi‑language – JavaScript/TypeScript, Python, Java, .NET,
  • silny model izolacji – kontekst przeglądarki per test, sandboxowanie stanu,
  • agresywne auto-wait – czekanie na element, animacje, sieć i stabilność DOM.

Playwright w realnych scenariuszach CI wypada szczególnie dobrze, gdy potrzebujesz macierzy: różne przeglądarki, różne systemy, różne wersje Node. Jedno repo testów może obsłużyć wszystkie warianty. Pytanie: czy naprawdę musisz testować w wielu przeglądarkach, czy to wymaganie „z przyzwyczajenia”? Jeśli tak, Playwright z natywnym wsparciem dla WebKit i Firefoxa ma przewagę nad Cypress, który koncentruje się głównie na Chromium/Chrome, eksperymentalnie wspiera WebKit/Firefox i nie zawsze jest tak spójny.

Filozofia Cypress: developer experience i bliskość frontendu

Cypress z kolei został zaprojektowany jako narzędzie dla front-endowców. Najważniejsze idee:

  • interaktywny runner – czas rzeczywisty, timetravel w UI, łatwe podglądanie DOM,
  • testy w tej samej karcie przeglądarki – brak klasycznego WebDrivera, szybka interakcja,
  • silna integracja z JS/TS – znajome API, pluginy, ekosystem npm,
  • prosty startnpx cypress open, zapis testu, kliknięcie scenariusza.

Cypress jest atrakcyjny, gdy chcesz, aby każdy deweloper frontendu naturalnie dodał kilka scenariuszy E2E do swojej funkcjonalności. Runner pozwala „poczuć” test: przewijasz, oglądasz screenshoty każdego kroku, debugujesz w przeglądarce. W CI możesz później odpalić te same testy w trybie headless. Jeśli twój zespół żyje w Node, Vite, Webpacku, Next.js – Cypress jest „domowy”.

Architektura: test w tej samej karcie vs kontroler zewnętrzny

Kluczowa różnica: Cypress uruchamia testy w tej samej karcie przeglądarki, która renderuje aplikację. Playwright działa jak zewnętrzny kontroler, który steruje przeglądarką przez protokół, a testy żyją w osobnym procesie. Co to oznacza praktycznie?

W Cypress:

  • łatwo podglądać stan aplikacji, globalne obiekty, Redux store przez cy.window(),
  • trudniej testować aplikacje z kilkoma domenami (przekierowania, SSO),
  • część ograniczeń wynika z sandboxu i bezpieczeństwa przeglądarki (CORS, iframy).

W Playwright:

  • masz pełną kontrolę nad kilkoma kontekstami przeglądarki i kilkoma stronami jednocześnie,
  • dużo łatwiej testować scenariusze „multi‑tab” i integracje z zewnętrznymi domenami,
  • odseparowany proces testu sprzyja stabilności i łatwiej rozdziela odpowiedzialności.

Jeśli masz złożone logowania SSO, OAuth, przekierowania między subdomenami, Playwright zwykle wygrywa. Jeżeli natomiast kluczowy jest komfort debugowania stanu aplikacji „od środka”, Cypress może być przyjemniejszy.

Obsługiwane przeglądarki, headless, mobilne emulacje

Playwright natywnie wspiera:

  • Chromium (w tym Chrome, Edge),
  • Firefox,
  • WebKit (silnik Safari),
  • profilowanie urządzeń mobilnych (emulacja rozdzielczości, user agent, touch events).

Cypress koncentruje się na:

  • Chrome/Chromium,
  • Edge i niektóre inne przeglądarki Chromium,
  • eksperymentalne wsparcie WebKit/Firefox (nie tak dojrzałe),
  • podstawową emulację viewportu (inna szerokość/wysokość, ale bez pełnego profilu mobile).

W realnych scenariuszach CI: jeśli musisz udokumentować wsparcie dla Safari lub testujesz krytyczne aplikacje biznesowe używane na iPadach, Playwright będzie bardziej wiarygodny. Do typowych aplikacji B2B używanych w Chrome/Edge różnica maleje i częściej liczy się DX i pipeline niż wachlarz browserów.

Dopasowanie do zespołu i kultury pracy

Jakiego zespołu dotyczy wybór Playwright vs Cypress w CI?

  • Zespół frontendowy, JS/TS‑centryczny – znajomy ekosystem, silne IDE, łatwość startu: często Cypress.
  • Zespół mieszany, QA + backend + frontend – potrzeba wielu języków, testów krzyżowych: często Playwright.
  • Organizacja z silnym naciskiem na przeglądarki i mobile‑web – multi‑browser, trace’y: częściej Playwright.
  • Organizacja, gdzie najważniejsza jest adopcja przez programistów frontendu – intuicyjny runner: często Cypress.

Pytanie do Ciebie: czy w Twoim zespole jest kultura „każdy pisze testy E2E”, czy raczej „QA utrzymuje zestaw E2E”? W pierwszym przypadku developer experience Cypress może dać większy zwrot. W drugim – elastyczność i stabilność Playwrighta w CI może mieć wyższą wartość.

Nowoczesne laboratorium z komputerami i zaawansowanymi maszynami badawczymi
Źródło: Pexels | Autor: Tima Miroshnichenko

Model pisania testów: API, selektory, stabilność kroków

Selektory i locatory: odporność na zmiany UI

Selektory to fundament stabilnych testów end to end w CI. Playwright wprowadza pojęcie locatorów, które opakowują selektory i zapewniają autowait. Przykładowo:

const loginButton = page.getByRole('button', { name: 'Zaloguj' });
await loginButton.click();

Locator nie „łapie” elementu raz na początku, tylko „na żądanie”, ze wszystkimi mechanizmami czekania. Cypress tradycyjnie używa metody łańcuchowej:

cy.contains('button', 'Zaloguj').click();

Oba podejścia pozwalają pisać odporne na zmiany layoutu testy, jeśli wykorzystasz semantykę (role, tekst, data-testid). Playwright w naturalny sposób zachęca do lokatorów domyślnych (getByRole, getByText), które są bliżej dostępności i mniej związane z klasami CSS. Cypress daje dużą swobodę – możesz używać cy.get('[data-testid=login-button]'), ale równie dobrze cy.get('.btn-primary'), co często kusi do krótkoterminowych skrótów.

Zadaj sobie pytanie: czy jesteś w stanie narzucić w projekcie standard data-testid lub selektorów opartych o role? Jeżeli tak – w obu narzędziach testy będą bardziej stabilne. Jeśli nie – podejście Playwrighta do locatorów może pomóc uniknąć wielu subtelnych błędów.

Automatyczne czekanie vs ręczna kontrola nad asynchronicznością

Strategie czekania w CI: jak unikać sleepów i flaky testów

Automatyczne czekanie to miejsce, w którym filozofie Playwrighta i Cypressa szczególnie się rozjeżdżają, a w CI różnice wychodzą jak na dłoni. Pytanie kontrolne: ile masz w testach „na sztywno” wpisanych timeoutów i waitów?

Playwright agresywnie czeka na stabilny stan DOM, sieć i animacje. Większość akcji (click, fill, press) ma wbudowane autowait. To kusi, żeby „zapomnieć” o asynchroniczności – i to zwykle jest okej. Typowy schemat:

await page.getByRole('button', { name: 'Zaloguj' }).click();
await expect(page.getByText('Witaj, Jan')).toBeVisible();

W Cypressie trzeba świadomie podjąć decyzję, gdzie polegasz na retry mechanizmach (cy.get, cy.contains), a gdzie dokładasz własne warunki. Klasyczne:

cy.contains('button', 'Zaloguj').click();
cy.contains('Witaj, Jan').should('be.visible');

Problem zaczyna się, gdy wchodzi websocket, eventy push, powolne backendy. W Playwright zazwyczaj lepiej zadziała oczekiwanie na zmianę w UI lub sieć niż ręczny waitForTimeout. W Cypress często pojawia się pokusa:

cy.wait(5000); // "bo inaczej nie przechodzi"

Jeśli łapiesz się na takich konstrukcjach, zastanów się: czy możesz skorzystać z warunków domenowych (tekst, zmiana URL, request zakończony 200)? W obu frameworkach stabilność w CI rośnie, gdy:

  • czekasz na konkretny efekt biznesowy, nie na czas (np. „widoczny numer zamówienia” zamiast 3 sekund),
  • stubujesz najbardziej nieprzewidywalne requesty (third‑party, zewnętrzne integracje),
  • rozbijasz długie „scenki” na mniejsze testy z jasno zdefiniowanym punktem końca.

W Playwright naturalne jest użycie page.waitForURL, page.waitForResponse, w Cypress – cy.intercept i aliasy. Jeśli w CI widzisz flaki „z powodu czasu”, pierwsze pytanie: czy czekasz na złą rzecz?

Praca z siecią: intercepty, mocki i izolacja backendu

Większość realnych pipeline’ów CI nie odpala testów na „prawdziwej” produkcyjnej infrastrukturze. Zwykle masz środowisko testowe, API mockowane częściowo lub w całości. Jak to obsługują Playwright i Cypress?

Playwright daje niski poziom kontroli nad requestami: możesz przechwycić, zmienić, zablokować. Przykład częściowego mocka:

await page.route('**/api/profile', async route => {
  const json = { name: 'Jan Tester', role: 'admin' };
  await route.fulfill({ json });
});

To podejście dobrze się skaluje w CI, gdy masz jasno zdefiniowane scenariusze: nie potrzebujesz, żeby cały backend działał, wystarczy kilka kluczowych endpointów zachowujących się „wiarygodnie”. Jeżeli masz już testy integracyjne na poziomie API, w E2E możesz zlekceważyć część przypadków brzegowych i skupić się na happy path.

W Cypress standardem jest cy.intercept:

cy.intercept('GET', '/api/profile', { 
  name: 'Jan Tester', 
  role: 'admin' 
}).as('getProfile');

Ten mechanizm jest bardzo blisko świata frontendu: deweloperzy łatwo podmieniają odpowiedzi i kontrolują kolejność zdarzeń. W CI możesz:

  • całkowicie odciąć się od niestabilnych usług zewnętrznych,
  • dostarczyć szybkie, deterministyczne odpowiedzi,
  • precyzyjnie sterować błędami (np. 500, timeout) bez zmiany backendu.

Jaką masz dziś politykę mockowania w E2E? Jeśli „łączymy się, z czym się da, a jak padnie – trudno”, przenosisz niestabilność środowiska prosto do CI. Tam, gdzie pipeline ma być sygnałem jakości, a nie „ruletką”, lepiej świadomie ustalić: które scenariusze idą na żywym API, a które na mockach.

Testy równoległe i sharding: skracanie czasu wykonania

Gdy testów E2E jest kilkanaście – narzędzie nie ma większego znaczenia. Przy setkach scenariuszy różnice między Playwrightem a Cypress w CI mocno wpływają na czas builda. Jak bardzo zależy ci, by pipeline zamknął się w 10, a nie 40 minutach?

Playwright ma wbudowany runner z natywnym wsparciem dla równoległości i shardingu. Konfigurujesz liczbę workerów (workers) i, jeśli trzeba, dzielisz zestaw testów między maszyny:

npx playwright test --workers=4
npx playwright test --shard=1/3

W CI możesz więc:

  • uruchomić wiele jobów Playwright równolegle (np. po jednej przeglądarce na job),
  • dzielić testy na „kawałki” bez utraty raportowania i trace’ów,
  • eskalować w górę tylko wtedy, gdy rośnie liczba scenariuszy.

Cypress w wersji open source ma równoległość „ręczną” – sam musisz podzielić zestaw testów między joby (np. na poziomie folderów, plików). Pełniejszy parallel z automatycznym rozkładaniem testów oferuje Cypress Cloud (dawniej Dashboard) – ale to już komponent SaaS. W wielu organizacjach pytanie brzmi: czy możemy korzystać z usług w chmurze, czy musimy trzymać się on‑prem?

W praktyce:

  • jeśli masz silny zespół DevOps i lubisz mieć kontrolę – Playwright z natywnym shardingiem łatwo wpasujesz w istniejący cluster CI,
  • jeśli wolisz „wygodnie niż nisko‑poziomowo” – ekosystem Cypress + chmurowy dashboard może szybciej dać efekt „testy skończone w 5 minut”.

Debugowanie w CI: screenshoty, nagrania, trace’y

Tu często rozstrzyga się realna użyteczność testów E2E. Bo co z tego, że pipeline jest czerwony, jeśli nikt nie ma czasu ani narzędzi, żeby zrozumieć, co się stało? Jak dziś debugujesz pojedyncze nieprzechodzące scenariusze?

Playwright oferuje Trace Viewer, screenshoty i nagrania wideo jako część „standardowego” zestawu. W CI możesz skonfigurować:

  • nagrywanie trace’ów tylko dla testów, które padły,
  • zrzuty ekranu w momencie błędu,
  • logowanie requestów/response’ów jako część trace’a.

Trace Viewer daje „film” z testu, ale interaktywny: podglądasz DOM, konsolę, sieć, screenshoty, krok po kroku. Przy flakach to często wystarczy, by zobaczyć, że np. overlay loadera jeszcze się nie schował, a test już klika.

Cypress z kolei ma zrzuty ekranu i nagrania wideo z runów headless. Jeśli użyjesz Cypress Cloud, dostajesz dodatkowo historyczne dane, porównania prędkości, flake detection. Nawet w wersji self‑hosted wideo bywa wystarczające: widzisz, że modal nie zdążył się otworzyć albo element jest poza viewportem.

Kluczowo: czy zespół ma nawyk podpinania artefaktów z CI do ticketów/błędów? Samo uruchomienie Playwrighta lub Cypressa z domyślnymi ustawieniami rzadko wystarczy. Warto skonfigurować pipeline tak, by:

  • artefakty (trace’y, zrzuty, wideo) były łatwo dostępne bez „kopania się” po logach,
  • link do konkretnego runu był automatycznie dopinany do PR lub zgłoszenia w Jirze,
  • nie zapychać storage’u – trzymać artefakty tylko z ostatnich X buildów albo z nieudanych runów.

Integracja z pipeline’ami: GitHub Actions, GitLab CI, Jenkins

Playwright i Cypress można odpalić w niemal każdym systemie CI, ale ścieżka „happy path” jest nieco inna. Podstawowe pytanie: jakie narzędzie CI dominuje w twojej organizacji?

Playwright dostarcza gotowe przykłady i oficjalne action dla GitHub Actions. Typowa konfiguracja to:

jobs:
  e2e-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - name: Install Playwright browsers
        run: npx playwright install --with-deps
      - name: Run tests
        run: npx playwright test

W GitLab CI czy Jenkinsie logika jest podobna: instalacja zależności, pobranie binarek przeglądarek, odpalenie testów. Playwright dobrze znosi konteneryzację; możesz mieć dedykowany obraz Docker z już zainstalowanymi browserami, co skraca czas joba.

Cypress z GitHub Actions czy GitLab CI też działa gładko, często z użyciem oficjalnych lub community‑owych obrazów Dockera. Wiele zespołów stosuje podejście:

  • budujemy aplikację w jednym jobie,
  • odpalamy ją w tle (np. npm start + wait-on),
  • na koniec w oddzielnym kroku uruchamiamy cypress run.

Jeśli masz mikroserwisy i złożony system startu środowiska, zastanów się: czy E2E odpalasz na „pełnym stacku”, czy na skrojonej instancji pod testy? W obu narzędziach plusem jest możliwość:

  • użycia tego samego obrazu Docker lokalnie i w CI,
  • trzymania konfiguracji środowisk (adresy, feature flagi) we wspólnych zmiennych CI,
  • eskalowania równoległości przez zwiększanie liczby kontenerów, a nie modyfikację testów.

Strategie selekcji testów: smoke, regresja, krytyczne ścieżki

Niezależnie od narzędzia, pełne E2E w każdym buildzie szybko doprowadzą pipeline do ściany. Pytanie: co chcesz zablokować na poziomie PR, a co może pójść w nightly?

Playwright pozwala łatwo tagować testy (np. przez projekty, definicje w configu czy adnotacje w kodzie) i odpalać tylko część zestawu:

test('scenariusz krytyczny @smoke', async ({ page }) => {
  // ...
});

Później w CI:

npx playwright test --grep @smoke

W Cypress podobny efekt uzyskasz przez pluginy do tagowania testów lub konwencję plików/folderów (np. wszystkie smoke’i w cypress/e2e/smoke). Możesz też używać it.only przy pracy lokalnej, ale w CI trzeba pilnować, by takie konstrukcje nie trafiły do maina.

Typowa strategia w większych zespołach:

  • na PR – krótka paczka smoke (1–3 krytyczne ścieżki: logowanie, zakup, kluczowy flow B2B),
  • na merge do main – rozszerzona regresja (wszystkie E2E, ewentualnie tylko Chrome),
  • nightly – pełna macierz (różne przeglądarki, języki, feature flagi).

Jak obecnie dzielisz testy E2E? Jeżeli wszystko odpala się zawsze „na raz”, migracja do tagów / zestawów często daje większy efekt niż zmiana samego narzędzia.

Utrzymanie testów w czasie: refactoring, page objecty, „helpery”

Sam wybór Playwright vs Cypress nie rozwiąże problemu „testy gniją po pół roku”. Pytanie, które warto sobie zadać: kto jest właścicielem refactoringu testów i kiedy go robicie?

Playwright zachęca do podejścia z page objectami lub modelami domenowymi, bo i tak piszesz kod w pełnoprawnym języku (TS/JS, Python, Java). Łatwo wydzielić:

class LoginPage {
  constructor(private page: Page) {}

  async login(email: string, password: string) {
    await this.page.getByLabel('Email').fill(email);
    await this.page.getByLabel('Hasło').fill(password);
    await this.page.getByRole('button', { name: 'Zaloguj' }).click();
  }
}

Wtedy w testach CI używasz spójnego API:

const loginPage = new LoginPage(page);
await loginPage.login('user@example.com', 'sekret');

W Cypress podobną strukturę da się osiągnąć przez Page Objects, komendy niestandardowe (Cypress.Commands.add) lub pliki helperów. Częsty anty‑wzorzec: kopiowanie tych samych sekwencji kroków po wielu specach. Gdy UI się zmienia, trzeba poprawiać 15 testów zamiast jednego helpera.

Jeżeli teraz największy ból to „każda zmiana layoutu psuje połowę E2E”, zamiast zmieniać narzędzie, zaplanuj:

  • silniejsze ustrukturyzowanie testów (page object / domain object),
  • standard selektorów (role, data-testid),
  • „dzień porządków” w sprintach, gdy refaktorujecie nie tylko kod aplikacji, ale i testy.

Współpraca QA–dev: kto pisze które testy?

Playwright i Cypress trochę inaczej rozkładają akcenty między QA a developerami. Zadaj sobie pytanie: czy chcesz, by QA byli bardziej techniczni, czy raczej, by devowie przejęli więcej odpowiedzialności za E2E?

Model współpracy a wybór narzędzia

Zastanów się: kto dziś najczęściej dotyka testów E2E – QA, devowie, czy pół‑na‑pół? Od tego w dużej mierze zależy, czy łatwiej „wejdzie” Playwright, czy Cypress.

Jeśli devowie są przyzwyczajeni do TypeScriptu, pracują w VS Code i mają już solidny zestaw unitów/integrationów, Playwright zwykle naturalnie się w to wpasowuje. Ten sam stack, te same narzędzia, te same wzorce (DI, page objecty, modularne helpery). Programiści chętniej dopisują E2E, bo nie czują, że wchodzą w „świat QA”.

Jeżeli z kolei masz silny zespół QA z backgroundem bardziej testerskim niż programistycznym, łatwość startu w Cypressie bywa dużą zaletą. Dashboard, czytelne logi w przeglądarce, „magiczne” cy.get() i auto‑wait – to obniża próg wejścia. Część zespołów traktuje Cypressa jako przejście z klasycznych narzędzi klikanych (Selenium IDE, testy manualne) w stronę kodu.

Dobrze jest świadomie zdecydować:

  • kto tworzy nowe scenariusze (QA, dev, para QA+dev),
  • kto utrzymuje i refaktoryzuje wspólną „warstwę infrastruktury” testów,
  • kiedy test może „przejść” z odpowiedzialności QA do dev (np. gdy dotyczy głównie logiki biznesowej).

Zadanie kontrolne: czy umiesz na tablicy narysować, jak wygląda przepływ odpowiedzialności za test E2E od pomysłu do utrzymania w CI? Jeśli nie – narzędzie jest drugorzędne, bo w praktyce i tak pojawi się chaos.

Onboarding zespołu: jak wdrożyć Playwright/Cypress w istniejące CI

Przy zmianie narzędzia albo pierwszym wdrożeniu na dużym projekcie kluczem jest mały, dobrze zdefiniowany krok. Zamiast „piszemy zestaw 50 testów”, lepiej zadać sobie pytanie: jaki pierwszy, konkretny efekt chcesz zobaczyć za 2 tygodnie?

Przykładowy plan startu z Playwrightem w projekcie z GitHub Actions:

  1. Wybrać 1–2 krytyczne ścieżki (np. logowanie, podstawowy zakup).
  2. Napisać je lokalnie z użyciem trace viewer, ustalić standard selektorów.
  3. Podpiąć npx playwright test --grep @smoke do istniejącego joba builda, ale bez „blokowania” PR (na początku jako job informacyjny).
  4. Dodać publikację trace’ów jako artefakty, nauczyć zespół, jak je otwierać.

Dopiero jak zespół „przestanie się bać czerwonego joba”, opłaca się przełączyć smoke’i w tryb wymagany dla PR. Analogicznie z Cypress: pierwszy krok to 1–2 scenariusze odpalane w headlessie w CI, z wideo jako artefaktem.

Dobre pytanie na retro: czy ktoś w ostatnim sprincie korzystał z nagrań/trace’ów z CI? Jeśli nie, co blokuje? Często to nie brak funkcji narzędzia, tylko brak nawyku i procesu (np. link z CI nie trafia do ticketów).

Testy E2E a architektura aplikacji: mocki, kontrakty, warstwy

Playwright i Cypress umożliwiają różne podejścia do komunikacji z backendem. Zanim wybierzesz „pełne E2E po prawdziwym API” lub „mockujemy wszystko”, zadaj sobie pytanie: co chcesz zweryfikować tym konkretnym zestawem testów?

Typowe warianty:

  • pełny stack – prawdziwe API, prawdziwa baza, ewentualnie sandbox środowisk zewnętrznych; maksymalnie realistyczne, ale wolne i kruche,
  • API realne, integracje zewnętrzne stubowane – kompromis dla systemów SaaS, gdzie nie chcesz „strzelać” do produkcyjnych integracji na każdym PR,
  • front z mockowanym API – testy skupione na zachowaniu UI, często szybsze i stabilniejsze; backend weryfikujesz osobno testami kontraktowymi i integracyjnymi.

Playwright daje rozbudowane możliwości przechwytywania requestów i serwowania własnych odpowiedzi (np. page.route()). To pozwala tworzyć hybrydę: część scenariuszy odpala się „na żywo”, a część z mockami, ale wszystko w jednym runnerze i z jednym raportowaniem.

Cypress ma podobny model (cy.intercept()), jednak w praktyce wiele zespołów idzie w mocne mockowanie w testach E2E. Efekt uboczny: UI jest pokryty testami, ale realne problemy integracyjne wychodzą dopiero na stagingu lub produkcji.

Dobrym kompromisem jest rozdzielenie w CI:

  • smoke’i – prawdziwe API, minimalny zestaw, ale wysoka wiarygodność,
  • większa paczka testów UI – z mockami tam, gdzie backend jest trudny do kontrolowania lub wolny,
  • oddzielne testy kontraktowe dla API – np. Pact, REST Assured, testy w Postman/Newman, które walidują spójność kontraktów.

Zapytaj siebie: czy twoje E2E są dziś bardziej testami UI, czy testami systemowymi? Odpowiedź mocno podpowie, jak ustawić balans między Playwrightem a Cypressowym stylem testów.

Bezpieczeństwo, dostęp do danych i compliance w CI

W środowiskach regulowanych (finanse, medycyna, sektor publiczny) często kluczowe pytanie nie brzmi „które narzędzie lepsze?”, tylko: czy nasze dane mogą opuszczać infrastrukturę?

Playwright jako „gołe” narzędzie nie wysyła nic na zewnątrz – wszystkie trace’y, nagrania i logi lądują tam, gdzie je skonfigurujesz. Jeśli CI stoi on‑prem, zachowujesz pełną kontrolę. Dobrze się to komponuje z wymaganiami typu ISO, SOC2, wrażliwe dane klientów.

W przypadku Cypressa decyzja dotyczy głównie tego, czy korzystasz z Cypress Cloud. To wygodny dashboard, ale oznacza transfer metadanych testów (czas, status, logi; potencjalnie także screenshoty i nagrania) do usługi SaaS. W wielu organizacjach trzeba tu wciągnąć do rozmowy dział bezpieczeństwa lub compliance.

Praktyczne kroki, które pomagają uniknąć napięć:

  • jasno zdefiniować, jakie dane trafiają do artefaktów (maskowanie loginów, danych klientów, numerów zamówień),
  • skonfigurować anonimizację danych testowych już na poziomie seedów bazy lub fixture’ów,
  • mieć procedurę czyszczenia artefaktów z CI po określonym czasie (retention policy).

Jeśli masz dylemat „Cypress Cloud czy on‑prem?”, zadaj sobie proste pytanie: czy w ostatnich miesiącach audyt bezpieczeństwa kiedykolwiek czepiał się naszych logów, screenshotów lub backupów? Jeśli tak – bliżej ci do modelu, w którym Playwright i samodzielnie hostowany raport/artefakty będą spokojniejszym wyborem.

Wydajność lokalna vs CI: jak uniknąć „działa u mnie”

Jedna z najczęstszych frustracji przy E2E: na maszynie dev/QA wszystko zielone, w CI coś ciągle pada. Zanim zaczniesz dopisywać waity lub „magiczne” retry, zatrzymaj się i zapytaj: czym dokładnie różni się twoje środowisko lokalne od agenta CI?

Najczęstsze różnice:

  • wersje przeglądarek lub sterowników,
  • inne flagi uruchomieniowe (np. w CI zawsze headless, lokalnie często headed),
  • inne dane testowe / brak seedów,
  • różna wydajność (CPU, I/O), co ujawnia problemy z timeoutingiem.

Playwright ma przewagę w tym, że dostarcza własne binarki przeglądarek w przewidywalnych wersjach. Możesz też użyć tego samego obrazu Docker lokalnie i w CI (np. przez devcontainer lub zwykłego Dockera). To mocno redukuje liczbę „magicznych” problemów reproduce‑only‑in‑CI.

Cypress ma gotowe obrazy Dockera z zainstalowanym Chrome/Firefox/Edge, ale część zespołów nadal uruchamia testy lokalnie w „gołych” przeglądarkach. Stąd różnice – szczególnie gdy dochodzą wtyczki przeglądarki, adblockery, inne profile usera.

Dobre praktyki, które pomagają niezależnie od narzędzia:

  • standard: jak odpalamy E2E lokalnie? – jeden, udokumentowany sposób, najlepiej przez Docker / skrypt NPM,
  • konfiguracja CI commitowana do repo (GitHub Actions, GitLab CI, Jenkinsfile), bez „ręcznych” ustawień na serwerach,
  • monitorowanie czasu poszczególnych testów i reagowanie, gdy określone scenariusze zaczynają „puchnąć”.

Jeśli dziś częściej słyszysz „u mnie przechodzi” niż „zobaczmy trace’a z CI”, priorytetem powinno być ujednolicenie środowisk, a nie sama zmiana Playwright ↔ Cypress.

Przejście z jednego narzędzia na drugie: migracja krok po kroku

Zdarza się, że organizacja już ma spory zestaw w Cypressie, a pojawia się potrzeba migracji do Playwrighta – albo odwrotnie. Zanim padnie hasło „przepisujemy wszystko”, zadaj sobie kilka niewygodnych pytań:

  • ile z obecnych testów naprawdę wnosi wartość, a ile to „szum” i duplikaty?
  • czy obecny ból wynika z narzędzia, czy z architektury testów i procesu?
  • czy ktokolwiek aktywnie utrzymuje obecne testy, czy traktujecie je jako „zło konieczne”?

Praktyczna strategia migracji z Cypressa do Playwrighta wygląda często tak:

  1. Zidentyfikować kluczowe scenariusze biznesowe i przepisać je jako pierwsze, w nowym narzędziu.
  2. Ustawić w CI równoległe joby: „stare E2E (Cypress)” i „nowe E2E (Playwright)”.
  3. Monitorować przez kilka sprintów, które testy faktycznie łapią błędy, a które są tylko „szumem”.
  4. Stopniowo wygaszać najmniej wartościowe scenariusze w starym narzędziu, dopisując brakujące pokrycie w nowym.

W drugą stronę, gdy przechodzisz z Playwrighta do Cypressa (np. ze względu na silne przyzwyczajenia QA lub integrację z Cypress Cloud), schemat jest analogiczny. Klucz to nie robić migracji 1:1 – raczej wykorzystać ją jako pretekst do uproszczenia i przemyślenia strategii E2E.

Dobre ćwiczenie na start: gdybyś dziś miał wrzucić do kosza 50% obecnych testów E2E, które byś zostawił? Te zostawione powinny być pierwszym kandydatem do migracji. Reszta to szansa na uporządkowanie długu.

Specyfika testowania w monorepo i wielu aplikacjach frontowych

W organizacjach z monorepo lub wieloma frontami (np. panel klienta, panel admina, aplikacja mobilna w wersji web) narzędzie testowe szybko styka się z problemem organizacyjnym: jak nie utopić się w konfiguracji i duplikacji?

Playwright, dzięki konfigowi w kodzie i „projektom” (projects), dobrze znosi scenariusze typu:

  • w jednym repo masz kilka aplikacji, każda startuje na innym porcie,
  • konfigurujesz w playwright.config kilka projektów – np. customer-web, admin-web, partner-portal,
  • każdy projekt ma inne baseURL, inne logowanie w globalSetup, ale współdzielą część helperów i page objectów.

Możesz wtedy w CI odpalać:

npx playwright test --project=customer-web

albo całą macierz naraz. Do tego dochodzi możliwość dopasowania konfiguracji do poszczególnych pakietów w monorepo (np. przez Turborepo, Nx czy niestandardowe skrypty).

Cypress w monorepo wymaga nieco więcej ręcznego klejenia. Część zespołów tworzy osobne katalogi cypress dla każdej aplikacji (np. apps/customer/cypress, apps/admin/cypress), co rozdziela konfigurację, ale czasem prowadzi do duplikacji helperów. Inne podejście: jedno „główne” cypress z podfolderami per aplikacja i różne konfiguracje startowe, przełączane zmiennymi środowiskowymi.

Jeśli działasz w monorepo, dobrze zadać sobie kilka pytań:

  • czy każda aplikacja ma własne, jasne kryteria „co testujemy E2E”?
  • czy chcesz utrzymywać jedno narzędzie dla wszystkich frontów, czy dopuszczasz mieszany model (np. Cypress dla starszych paneli, Playwright dla nowych)?
  • jak CI ma decydować, które testy odpalić przy danej zmianie (np. tylko te aplikacje, które dotknął PR)?

W praktyce Playwright, dzięki elastycznej konfiguracji projektów, częściej wygrywa w bardziej złożonych monorepo. Cypress nadrabia tam, gdzie priorytetem jest prostota dla pojedynczego zespołu produktowego.

Testy wizualne i dostępności w kontekście E2E

Oba narzędzia coraz częściej wykorzystuje się jako „nośnik” dla dodatkowych kontroli: regresji wizualnej czy testów dostępności. Pytanie brzmi: czy chcesz łapać te problemy już na poziomie E2E, czy masz osobny proces?

Kluczowe Wnioski

  • Zanim porównasz Playwright i Cypress, odpowiedz sobie na pytanie: jaki masz cel testów E2E – szybki feedback na każdym pushu, pełna regresja przed releasem, czy tylko kilka krytycznych ścieżek typu logowanie/zapłata? Od tego zależy, czy kluczowa będzie prostota konfiguracji, czy raczej skalowanie, parallelism i debugowanie flaków.
  • Charakter aplikacji (SPA, SSR, microfrontends, legacy) mocno wpływa na wybór narzędzia: dla dynamicznych SPA kluczowe są dobre locatory i autowait, w legacy i microfrontendach znaczenie ma kontrola nad HTML i data-testid – jeśli nie możesz zmieniać DOM-u, Playwright z mocnym wsparciem dla ról i dostępności często daje przewagę.
  • Model współpracy i skala (mały zespół vs monorepo z wieloma teamami) decydują, jak bardzo odczujesz ograniczenia CI: w dużych repo liczy się łatwe dzielenie testów na joby, raportowanie i izolacja testów; Playwright z domyślną izolacją kontekstu zwykle lepiej znosi duże pakiety, ale przy dobrej dyscyplinie testowej Cypress także się sprawdzi.
  • Zadaj sobie pytanie: jakie masz ograniczenia infrastruktury CI – SaaS z gotowymi workerami czy on‑prem bez wygodnego Dockera? Playwright promuje podejście „all‑in‑one” w kontenerze z wbudowanymi przeglądarkami, Cypress ma długą historię w ekosystemie Node/Chrome i zestaw gotowych obrazów oraz workflowów, co upraszcza start w popularnych CI.