Cypress oferuje interfejs graficzny, który pozwala obserwować wykonywanie testów na żywo. Jest to niezwykle pomocne i umożliwia cofnięcie się do dowolnego etapu pracy, dzięki czemu można dokładnie zobaczyć stan aplikacji i elementy, które były w danej chwili aktywne. Po kliknięciu na konkretny snapshot testu Cypress pokazuje stan aplikacji i pozwala również sprawdzić, co wydarzyło się w danym momencie. Pokazuje także, jak został wykonany request, jaka była jego odpowiedź oraz daje możliwość skorzystania z narzędzi deweloperskich w konkretnym stanie aplikacji. To znacznie ułatwia wykrywanie gdzie i dlaczego test się nie powiódł.

Pic.1 Snapshot requestu do api
Powyższy snapshot Cypress przedstawia:
- Kroki testu widoczne są po lewej stronie, a wybrany etap został podświetlony.
- Szczegóły zapytania HTTP znajdują się w konsoli u dołu: wysłane dane (body), nagłówki (Headers), adres API, odpowiedź serwera (response body).
- Możliwość sprawdzenia stanu aplikacji w wybranym momencie i szczegółowej analizy, co się wydarzyło podczas danego kroku testu.
Podsumowując: Snapshot ten umożliwia pełne zrozumienie przebiegu testu — pokazuje zarówno wykonane kroki, jak i szczegóły zapytania HTTP, co pozwala szybko zidentyfikować źródło ewentualnego błędu.

Pic.2 Snapshot akcji type
Powyższy snapshot Cypress przedstawia:
- akcja komendami cy.clear() i cy.type działania pole coupon_cash_discount - jest czyszczone i do niego wpisywana jest wartość "10".
- W konsoli widzimy listę zdarzeń klawiaturowych, które zostały wywołane podczas wpisywania.
Podsumowując: snapshot pokazuje krok testu polegający na wpisaniu wartości "10" do pola zniżki gotówkowej, wraz z technicznymi szczegółami wpisywania.

Pic.3 Snapshot z błędem
Powyższy snapshot Cypress przedstawia:
- Fragment testu, gdzie następuje wykonanie komendy get z selektorem [qa-minimum_cart_price_type_test].
- W konsoli wyświetla się błąd typu AssertionError: test próbował znaleźć element o tym selektorze, ale go nie znalazł (0 elementów znalezionych).
- Informacja o czasie oczekiwania (timeout) i miejscu rzutu błędu w pliku testowym.
Podsumowując: snapshot pokazuje krok testu próbujący znaleźć element z atrybutem qa-minimum_cart_price_type_test, ale element ten nie istnieje lub nie jest dostępny w DOM, co powoduje błąd testu.
Integracja z narzędziami deweloperskimi
Cypress ściśle współpracuje z wbudowanymi w przeglądarkę narzędziami deweloperskimi (np. Chrome DevTools). Można korzystać z konsoli, debuggerów i inspektorów elementów podczas działania testu, przez co debugowanie jest bardzo intuicyjne i szybkie. Możliwe jest ustawianie breakpointów i śledzenie przepływu testów bezpośrednio w kodzie.

Pic.4 Dostęp do narzędzi developerski nie tylko podczas trwania testu
Na załączonym screenie widać, że gdy w Cypress zaznaczymy konkretny snapshot (czyli konkretny krok testu), możemy "cofnąć się w czasie" i zobaczyć stan aplikacji dokładnie w tym momencie. Dzięki temu można:
- Sprawdzić elementy, które pojawiły się tylko na chwilę, takie jak np. pasek loadera widoczny w ułamek sekundy.
- Dokładnie przeanalizować DOM, właściwości elementów, czy style CSS w tym momencie.
- Użyć konsoli deweloperskiej do debugowania zmiennych, wywołań JS, network requestów i innych aspektów aplikacji w tym konkretnym stanie.
To jest ogromna pomoc przy wykrywaniu problemów, które mogą być ulotne i trudne do złapania "na żywo". Cypress działa więc jak "kamera slow-motion" dla testów automatycznych, pozwalając na precyzyjne śledzenie i analizę zdarzeń w czasie rzeczywistym.
Zaawansowane raportowanie błędów
Cypress generuje czytelne raporty o wykonaniu testów, w tym szczegółowe logi kroków i wyniki asercji. Raporty mogą być rozszerzane o zewnętrzne narzędzia kompatybilne z Mocha (np. teamcity, junit), które usprawniają integrację z procesem CI/CD i pozwalają szybko zlokalizować problemy w automatycznych buildach. My bazujemy przy tym zarówno na raportach z outputu konsoli, jak i na wygenerowanych, bardziej czytelnych raportach Mocha.

Pic.5 Przykład raportu z output-u consoli

Pic.6 Przykład mocha raportu z screenshotem
Automatyczne zrzuty ekranu i nagrania wideo
Przy błędach testowych, Cypress automatycznie wykonuje zrzuty ekranu oraz może rejestrować przebieg testu wideo, co umożliwia jeszcze dokładniejszą analizę nieoczekiwanych zachowań aplikacji i błędów. Jedną z najważniejszych zalet Cypress jest jego domyślne zachowanie, czyli automatyczne tworzenie zrzutu ekranu w momencie, gdy test napotka błąd (failure). Kiedy asercja zawiedzie lub polecenie nie zostanie wykonane poprawnie, Cypress natychmiast zapisuje obraz aplikacji. Dzięki temu deweloper lub tester nie musi ręcznie odtwarzać scenariusza, aby zobaczyć, co poszło nie tak. Zrzut ekranu dostarcza precyzyjnego wizualnego kontekstu błędu i pokazuje, czy element był niewidoczny, czy pojawił się nieoczekiwany modal, czy dane w formularzu były nieprawidłowe.
Wszystkie automatycznie wygenerowane screenshoty są domyślnie zapisywane w folderze cypress/screenshots. Co więcej, są one automatycznie integrowane z większością reporterów, takich jak Mochawesome, gdzie pojawiają się bezpośrednio przy opisie nieudanego testu, co czyni raporty jeszcze bardziej kompletnymi.
Manualne zrzuty ekranu dla celów dowodowych i debugowania
Oprócz automatycznego mechanizmu, Cypress umożliwia deweloperom manualne tworzenie zrzutów ekranu w dowolnym momencie testu za pomocą prostego polecenia cy.screenshot(). Jest to niezwykle przydatne w kilku scenariuszach:
- Dokumentacja kluczowych kroków: można zrobić zrzut ekranu po pomyślnym wypełnieniu skomplikowanego formularza lub przed wykonaniem krytycznej akcji, aby mieć wizualny dowód, że aplikacja zachowała się zgodnie z oczekiwaniami.
- Debugowanie stanów pośrednich: jeśli test jest złożony i chcemy zweryfikować stan aplikacji w połowie jego wykonania, cy.screenshot() pozwala "zamrozić" widok i przeanalizować go później.
- Weryfikacja wizualna: można wykonać zrzut ekranu konkretnego elementu (cy.get('.klasa-elementu').screenshot()), a nie całej strony, co jest przydatne do sprawdzania wyglądu poszczególnych komponentów.
Możliwość nadawania własnych nazw plikom (cy.screenshot('nazwa-pliku')) ułatwia późniejszą identyfikację i organizację zrzutów.
Konfiguracja i integracja screenshotów z raportami
Zachowanie funkcji zrzutów ekranu można dostosować w pliku konfiguracyjnym e2e.js. Możliwe jest m.in. wyłączenie automatycznych screenshotów przy błędach czy zmiana domyślnego folderu zapisu.
Cypress.on('test:after:run', (test, runnable) => {
if (test.state === 'failed') {
const screenshotFileName = `${runnable.parent.title} -- ${test.title} (failed).png`;
addContext({ test }, `screenshots/${Cypress.spec.name}/${screenshotFileName}`);
}
});Pic.7 Oto nasza implementacja i wskazanie nazwy pliku z screenshot
Integracja zrzutów ekranu z raportami testowymi to klucz do efektywnej komunikacji w zespole. Dzięki nim raporty z CI/CD stają się czymś więcej niż tylko suchym tekstem i dostarczają wizualny dowód na występowanie błędów, co pozwala na błyskawiczne zrozumienie problemu bez konieczności uruchamiania całego środowiska deweloperskiego.
Automatyczne nagrywanie testów
Oprócz statycznych zrzutów ekranu Cypress oferuje potężne narzędzie do analizy i debugowania — automatyczne nagrywanie wideo przebiegu testów. Ta funkcja dostarcza pełen, dynamiczny obraz interakcji aplikacji podczas testów, co jest szczególnie pomocne w środowiskach CI/CD.
Nagrywanie wideo można włączyć jako zmienną środowiskową CYPRESS_RECORD, np. w GitLabie, kontrolując tym samym czy nagrania mają być tworzone:
let record = false;
try {
// eslint-disable-next-line no-undef
if (process.env.CYPRESS_RECORD.toLowerCase() === 'true') {
record = true;
}
} catch { }
export default defineConfig({
projectId: "siysts",
viewportWidth: 1200,
viewportHeight: 1000,
port: 1234,
defaultCommandTimeout: 20000,
chromeWebSecurity: true,
video: record,
videoCompression: 12,
watchForFileChanges: false,
reporter: "mochawesome",
scrollBehavior: "center",
Pic.8 Implementacja sterowania zmienną włączania/wyłączania nagrywania w pliku cypress.config.ts
Domyślnie, gdy uruchamiasz testy w trybie headless za pomocą cypress run, Cypress automatycznie nagrywa plik wideo dla każdego pliku testowego (spec file). To nagranie jest kompletnym zapisem wszystkiego, co dzieje się w przeglądarce podczas testu.
Dzięki temu, w przypadku błędu nie tylko otrzymujesz zrzut ekranu z momentu jego wystąpienia, ale także możesz odtworzyć pełną sekwencję działań, które do niego doprowadziły. Pozwala to obserwować dynamiczne zmiany w interfejsie (animacje, loading asynchronicznych danych), kolejność i szybkość wykonywanych akcji oraz pełen kontekst przed wystąpieniem błędu — co często jest kluczowe do zrozumienia jego przyczyny.
Nagrania wideo są domyślnie zapisywane w folderze cypress/videos, co ułatwia ich lokalne odtwarzanie i analizę.
W pliku konfiguracyjnym cypress.config.ts można też kontrolować parametry nagrywania wideo:
- video: false — wyłącza tworzenie nagrań, jeśli nie są potrzebne.
- videoCompression — pozwala ustawić poziom kompresji, co zmniejsza rozmiar plików i oszczędza miejsce w CI.
- videoUploadOnPasses: false — przy korzystaniu z Cypress Cloud umożliwia wysyłanie nagrań jedynie dla testów zakończonych niepowodzeniem, co optymalizuje zużycie zasobów.
Podsumowując, screenshoty i nagrania wideo w Cypress to kluczowe narzędzia, które razem tworzą kompletny wizualny zapis przebiegu testu. Screenshot dostarcza statyczny dowód błędu, podczas gdy wideo oferuje pełen dynamiczny kontekst, pokazując sekwencję zdarzeń, która do niego doprowadziła.
Zapis logów reqestów akcji API
W zaawansowanych testach automatycznych kluczem do sukcesu jest nie tylko weryfikacja poprawności działania aplikacji, ale również zapewnienie solidnych mechanizmów do debugowania. Podczas pracy z API, gdzie komunikacja z serwerem jest niewidoczna dla użytkownika, kluczowe staje się niezawodne rejestrowanie każdej interakcji.
export const handleResponse = (response, shouldFail, method = 'UNKNOWN', url = 'unknown URL', logName = 'generic_api') => {
return cy
.writeFile(
`artifacts/logs/${Cypress.spec.name}/${logName}.log`,
JSON.stringify(response, null, 2) + '\n',
{ flag: 'a+' }
)
.then(() => {
if (shouldFail && response.status >= 400) {
const status = response.status;
const body = response.body || '';
throw new Error(
`API error ${status}:\n` +
`Method: ${method}\n` +
`URL: ${url}\n` +
`Body: ${JSON.stringify(body, null, 2)}`
);
}
return response;
});
};
Pic.9 Kod zapisu logów do pliku
Prezentowana funkcja handleResponse jest doskonałym przykładem profesjonalnego podejścia do testowania API w Cypress. Służy ona jako centralny punkt do obsługi odpowiedzi z serwera, którego zadaniem jest nie tylko weryfikacja, ale przede wszystkim tworzenie szczegółowej dokumentacji (logów) z każdego żądania, co jest nieocenione w codziennej pracy i analizie wyników z procesu CI/CD.
Co dokładnie robi handleResponse?
Ta funkcja, nazwijmy ją "pomocnikiem odpowiedzi API", to zaawansowany i reużywalny fragment kodu do obsługi odpowiedzi z serwera w testach Cypress. Jej zadania można podzielić na dwa główne etapy:
- Zapisuje każdą odpowiedź do pliku:
- Niezależnie od tego, czy żądanie API się powiodło, czy nie, funkcja używa cy.writeFile(), aby zapisać pełną treść odpowiedzi (response) w pliku z logami.
- Ścieżka do pliku jest dynamiczna: artifacts/logs/${Cypress.spec.name}/${logName}.log. Oznacza to, że logi są automatycznie grupowane w folderach nazwanych tak jak plik testowy, co niesamowicie ułatwia ich odnalezienie.
- Używa flagi { flag: 'a+' }, która jest tu kluczowa. Mówi ona Cypress, aby dopisywał logi na końcu pliku, a nie go nadpisywał. Dzięki temu w jednym pliku zbierasz historię wszystkich odpowiedzi API z danego testu.
- Warunkowo przerywa test w razie błędu:
- Funkcja sprawdza dwa warunki: czy flaga shouldFail jest ustawiona na true ORAZ czy status odpowiedzi to błąd (kod 400 lub wyższy).
- Jeśli oba warunki są spełnione, celowo przerywa test (throw new Error(...)), wyświetlając bardzo czytelny i pomocny komunikat o błędzie, zawierający status, metodę, adres URL i treść odpowiedzi.
- Jeśli warunki nie są spełnione (np. odpowiedź jest poprawna lub ustawiliśmy shouldFail na false), funkcja po prostu zwraca oryginalną odpowiedź, pozwalając na dalsze przetwarzanie jej w teście.
Dlaczego i jak jej używamy?
Jej głównym celem jest stworzenie uniwersalnego i niezawodnego mechanizmu logowania oraz obsługi błędów dla wszystkich żądań API. Używamy jej, aby mieć pewność, że żadna odpowiedź z serwera nie umknie naszej uwadze.
W praktyce integrujesz ją z komendami cy.request() lub cy.intercept(). Zamiast obsługiwać każdą odpowiedź indywidualnie, przekazujesz ją do handleResponse, która robi całą "brudną robotę".
Przykład użycia:
cy.request({
method: 'POST',
url: '/api/users',
body: { name: 'Jan Kowalski' }
}).then(response => {
// Przekazujemy odpowiedź do naszego pomocnika
// Chcemy, aby test się nie powiódł w razie błędu API (shouldFail = true)
return handleResponse(response, true, 'POST', '/api/users', 'user_creation');
});
Pic.10 Użycie handleResponse w komendzie
Dodatkowe zalety:
Poza podstawową funkcjonalnością, to rozwiązanie wprowadza kilka profesjonalnych praktyk:
- Zasada DRY (Don't Repeat Yourself): zamiast powielać logikę zapisu do pliku i sprawdzania statusu w każdym teście, masz ją w jednym, centralnym miejscu. To sprawia, że kod jest czystszy, łatwiejszy w utrzymaniu i mniej podatny na błędy.
- Skarb w procesie CI/CD: kiedy testy uruchamiane są automatycznie na serwerze (np. w Jenkinsie czy GitLabie), nie masz dostępu do interfejsu graficznego Cypressa. Te pliki z logami stają się wtedy Twoimi oczami. Jeśli test zakończy się niepowodzeniem, możesz pobrać wygenerowane artefakty (pliki .log) i dokładnie zobaczyć, jaką odpowiedź serwer zwrócił tuż przed błędem.
- Niesamowita elastyczność: parametr shouldFail to znakomite rozwiązanie. Pozwala on testować również negatywne scenariusze. Na przykład, jeśli chcesz sprawdzić, czy API poprawnie zwraca błąd 404 dla nieistniejącego zasobu, wywołujesz funkcję z shouldFail: false. Odpowiedź zostanie zapisana w logu, ale test nie zostanie przerwany, co pozwoli Ci potwierdzić, że aplikacja zachowała się zgodnie z oczekiwaniami.
Podsumowując: handleResponse to reużywalne narzędzie, które automatyzuje dwa kluczowe zadania: zapisuje każdą odpowiedź API do pliku z logami i inteligentnie zarządza błędami. Dzięki niej kod testów staje się czystszy, a debugowanie — zwłaszcza w środowisku CI/CD — o wiele prostsze, ponieważ zawsze mamy dostęp do szczegółowej historii komunikacji z serwerem. Wprowadzenie tej opcji okazało się prawdziwym game-changerem, ponieważ pozwoliło nam wyłapać mnóstwo ukrytych problemów na etapie przygotowywania danych testowych. Dzięki szczegółowym logom, pisanie precyzyjnych asercji stało się znacznie prostsze i bardziej niezawodne.
Autorskie rozwiązanie logowania błędów do MongoDB i wykorzystywanie zebranych przez niego danych
W świecie ciągłej integracji (CI/CD) standardowe raporty z testów, choć przydatne, często okazują się niewystarczające. Pokazują wynik "tu i teraz", ale nie dają wglądu w trendy, nie pozwalają na zaawansowaną analizę i nie adaptują się do specyficznych potrzeb projektu. Prezentowane rozwiązanie to krok dalej: porzucenie gotowych narzędzi na rzecz stworzenia własnego, potężnego mechanizmu do analityki testów Cypress, opartego o bazę danych MongoDB. Zapis logów do zrealizowany został w pliku index.js w /plugins. Oto nasza implementacja zapisu danych do MongoBD.
async function logTestToMongo(spec, test) {
if (!process.env.CYPRESS_JOB_URL) return;
const formattedTitle = test.title[test.title.length - 1];
for (const [index, attempt] of test.attempts.entries()) {
const testEntry = {
file: spec.relative, // Name of the spec file
title: formattedTitle, // Test title
project: process.env.CYPRESS_project || 'Unknown', // Project name from env (Można dodać inne własne zmienne lub zmienne z Gitlab/Github - np id pipeline)
alias: process.env.CYPRESS_alias || 'Unknown', // Environment alias from env
jobUrl: process.env.CYPRESS_JOB_URL || 'N/A', // CI/CD job URL
retryNumber: index + 1, // Retry attempt number (starts from 1)
isFinalRetry: index === test.attempts.length - 1, // Whether it's the last retry attempt
duration: test.duration || 0, // Test duration in milliseconds
status: attempt.state, // Test status
errorMessage: attempt.state === 'failed' && test.displayError ? test.displayError : 'None', // Error message if failed
timestamp: new Date() // Timestamp of the log
};
await saveFailedTestToMongo(testEntry);
}
}// Save failed test info to MongoDB
async function saveFailedTestToMongo(testEntry) {
const client = new MongoClient(MONGO_URI);
try {
await client.connect();
const db = client.db();
const collection = db.collection(COLLECTION_NAME);
await collection.insertOne(testEntry);
} catch (err) {
console.error('❌ Błąd podczas zapisu do Mongo:', err.message);
} finally {
await client.close();Pic.11 Zapis logów do MongoDB
Mechanizm opiera się na dwóch współpracujących ze sobą funkcjach, uruchamianych po każdym teście w środowisku CI/CD.
- logTestToMongo(spec, test) — Kolektor Danych: działa jak precyzyjny rejestrator. Po zakończeniu każdego testu zbiera ona bogaty zestaw informacji, tworząc szczegółowy dokument. Kluczowe zbierane dane to:
- Identyfikacja testu: Nazwa pliku, tytuł testu.
- Kontekst CI/CD: Nazwa projektu, alias środowiska oraz — co najważniejsze — bezpośredni link do zadania (jobUrl) w systemie CI (np. Jenkins, GitLab), z którego test został uruchomiony.
- Analiza prób (Retries): Rejestruje dane dla każdej próby wykonania testu, zapisując jej status (passed/failed), numer próby oraz dokładną treść błędu.
- Metryki: Czas trwania testu oraz dokładny stempel czasowy wykonania.
- saveFailedTestToMongo(testEntry) — Silnik Zapisu: jest prostym, ale niezawodnym narzędziem, które pobiera przygotowany pakiet danych i zapisuje go jako pojedynczy dokument w dedykowanej kolekcji w bazie MongoDB. Zastosowanie bloku try...catch...finally gwarantuje, że połączenie z bazą danych zostanie bezpiecznie zamknięte, nawet w przypadku niepowodzenia zapisu.
Potęga zebranych danych: Jakie możliwości to otwiera?
Gdy wyniki każdego testu i każdej jego próby trafiają jako ustrukturyzowane dokumenty do bazy danych, zyskujemy praktycznie nieograniczone możliwości analityczne.
- Generowanie w pełni spersonalizowanych raportów: jesteś uniezależniony od formatu narzuconego przez zewnętrzne narzędzia. Możesz tworzyć raporty skrojone na miarę, agregując dane według dowolnego kryterium: projektu, konkretnego pliku testowego, przedziału czasowego czy nawet autora ostatnich zmian w kodzie.
- Stworzenie własnego dashboardu analitycznego: to największa zaleta. Podłączając do bazy MongoDB narzędzie do wizualizacji (np. Grafana, Metabase, Tableau lub własną aplikację webową), możesz zbudować centralny dashboard jakości. Taki panel pozwoli na bieżąco odpowiadać na kluczowe pytania:
- Które testy są najbardziej niestabilne (tzw. "flaky tests")?
- Jaka jest historyczna zdawalność testów dla projektu X?
- Czy ostatnie wdrożenie spowalnia działanie testów regresji?
- W której części aplikacji najczęściej pojawiają się błędy?
- Zaawansowana analiza i śledzenie trendów: przechowywanie historii pozwala na analizę długoterminową. Możesz śledzić, jak zmienia się jakość Twojego oprogramowania w czasie, korelować wzrost liczby błędów z konkretnymi wersjami i proaktywnie identyfikować obszary wymagające poprawy, zanim staną się one krytycznym problemem.
- Błyskawiczny dostęp do źródła problemu: dzięki zapisywaniu linku jobUrl w bazie, każdy wpis o błędzie na Twoim dashboardzie może być bezpośrednim odnośnikiem do logów z zadania w CI/CD. To radykalnie skraca czas potrzebny na zdiagnozowanie problemu – od wykresu na dashboardzie do pełnego logu w Jenkinsie w jednym kliknięciu.
Podsumowując, takie podejście przekształca testy automatyczne z prostego mechanizmu "zdał/nie zdał" w bogate źródło danych, które staje się fundamentem do podejmowania świadomych decyzji o jakości i rozwoju produktu.
Błyskawiczne powiadomienia o błędach — Integracja Cypress z Google Chat
W dynamice zwinnego wytwarzania oprogramowania zdarzają się momenty, gdy błyskawiczna reakcja na zdarzenie jest absolutnie kluczowa. Wyobraźmy sobie sytuację, w której cały zespół czeka na krytyczny deploy na środowisko testowe, a proces jest blokowany przez nieudany test. Ciągłe obserwowanie “pipe’a” w systemie CI/CD jest nie tylko kosztowne pod względem czasu i uwagi deweloperów, ale po prostu bezsensowne. Zamiast aktywnie "ciągnąć" informacje, możemy sprawić, by to one "pchały" się do nas. Integracja Cypress z Google Chat za pomocą webhooków to proste i potężne rozwiązanie, które pozwala otrzymywać alerty o błędach w czasie rzeczywistym.
Jak to działa?
Pomysł jest prosty: za każdym razem, gdy test zakończy się niepowodzeniem, Cypress automatycznie uruchomi funkcję, która wyśle spersonalizowaną wiadomość na wskazany kanał w Google Chat. Wiadomość ta może zawierać kluczowe informacje, takie jak nazwa testu, plik, w którym wystąpił błąd, oraz bezpośredni link do logów w systemie CI/CD.
Implementacja w haku after:spec
Najlepszym miejscem do implementacji takiej logiki jest wbudowany w Cypress hak (hook) after:spec, który uruchamia się po zakończeniu całego pliku testowego. Iterując po wynikach, możemy łatwo wyłapać te testy, które zakończyły się statusem failed i wywołać naszą funkcję wysyłającą powiadomienie.
Krok 1: Tworzenie funkcji wysyłającej
Najpierw tworzymy funkcję, która będzie odpowiedzialna za skonstruowanie i wysyłanie wiadomości do Google Chat. Funkcja ta pobiera dane o teście oraz kontekst z CI/CD (zmiennych środowiskowych) i wysyła je do unikalnego adresu URL webhooka.
// Plik: cypress.config.js lub cypress/support/e2e.js
const https = require('https');
// Funkcja wysyłająca powiadomienie do Google Chat
function sendGoogleChatNotification(specFile, testTitle) {
// Przerywamy, jeśli nie ma linku do joba (test uruchamiany lokalnie)
if (!process.env.CYPRESS_JOB_URL) return;
// Adres URL webhooka dla Twojego kanału Google Chat
// PAMIĘTAJ: Przechowuj klucze i sekrety w bezpieczny sposób, np. w zmiennych środowiskowych!
const webhookUrl = new URL('https://chat.googleapis.com/v1/spaces/SPACEXXX/messages?key=SECRETKEYXXX');
// Tworzymy treść wiadomości w formacie Google Chat
const message = JSON.stringify({
text: `🔥 *Test Failed!* 🔥\n📄 File: *${specFile}*\n📝 Test: *${testTitle}* \n🔗 JOB URL: ${process.env.CYPRESS_JOB_URL}\n📁 Project: *${process.env.CYPRESS_project}*`
});
const options = {
hostname: webhookUrl.hostname,
path: webhookUrl.pathname + webhookUrl.search,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(message)
}
};
// Wysyłamy żądanie HTTP
const req = https.request(options);
req.on('error', (error) => {
console.error('Błąd podczas wysyłania powiadomienia:', error);
});
req.write(message);
req.end();
}
Pic.12 Implementacja procesu wysyłania powiadomień do GoogleChat
Krok 2: Wykorzystanie hook’a after:spec
Teraz, w pliku konfiguracyjnym Cypress (cypress.config.js), integrujemy naszą funkcję z hakiem after:spec.
// Plik: cypress.config.js
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// ... inne eventy
// Uruchamiane po każdym pliku testowym
on('after:spec', (spec, results) => {
// Iterujemy po wszystkich testach w danym pliku
results.tests.forEach(test => {
// Sprawdzamy, czy którykolwiek z testów się nie powiódł
if (test.state === 'failed') {
// Pobieramy ostatni (najbardziej szczegółowy) człon tytułu
const formattedTitle = test.title[test.title.length - 1];
sendGoogleChatNotification(spec.relative, formattedTitle);
}
});
});
return config;
},
},
});
Pic.13 Trigger wysyłania powiadomienia w hook’u
Integracja Cypress z komunikatorem takim jak Google Chat to prosty, ale niezwykle efektywny sposób na optymalizację pracy zespołu. Niewielkim kosztem implementacji zyskujemy mechanizm proaktywnego informowania o krytycznych błędach, uwalniając deweloperów od konieczności ręcznego monitorowania procesów CI/CD. Taki system nie tylko przyspiesza reakcję na problemy, ale również buduje kulturę transparentności i pozwala szybciej dostarczać działające oprogramowanie.
Podsumowanie
Debugowanie i szybkie rozwiązywanie problemów w testach automatycznych to kluczowy element efektywnej pracy zespołów tworzących oprogramowanie. Cypress dzięki swoim unikalnym funkcjom, takim jak snapshoty krok po kroku, automatyczne screenshoty i nagrania wideo, umożliwia bardzo precyzyjne śledzenie przebiegu testów oraz dokładną analizę błędów.
Snapshoty pozwalają na cofnięcie się do dowolnego kroku testu i podejrzenie stanu aplikacji, szczegółów zapytań API czy zachowania elementów w czasie rzeczywistym. Integracja z narzędziami developerskimi (np. Chrome DevTools) ułatwia debugowanie poprzez możliwość stawiania breakpointów i wgląd w workflow testu.
Cypress generuje szczegółowe raporty testów, które mogą być wzbogacone o formaty kompatybilne z Mocha czy JUnit, co usprawnia analizę w procesach CI/CD. Automatyczne tworzenie zrzutów ekranu przy błędach oraz nagrania wideo całego przebiegu testów dostarczają niezbędnych materiałów wizualnych dla szybkiego zrozumienia problemów bez konieczności ręcznego odtwarzania scenariuszy.
Przy testach API ważne jest solidne logowanie komunikacji z serwerem. Nasza funkcja handleResponse rejestruje każdą odpowiedź do plików logów, automatycznie zarządza błędami i stanowi centralny punkt analiz podczas debugowania i monitoringu testów, szczególnie w środowiskach CI/CD.
Dodatkowo stosujemy wzorce i narzędzia, takie jak Selector Playground do precyzyjnego wybierania elementów, mockowanie API za pomocą cy.intercept dla izolacji problemów, a także optymalizujemy testy przez ustawianie stanu aplikacji i tokenów JWT na etapie beforeEach.
Innowacyjnym i wartym podkreślenia podejściem jest wykorzystanie własnej bazy MongoDB do zapisu i analizy wyników testów. To pozwala na tworzenie zaawansowanych, spersonalizowanych raportów i dashboardów, śledzenie trendów jakości oprogramowania oraz szybką identyfikację błędów z poziomu CI.
Wreszcie, integracja z komunikatorami takimi jak Google Chat umożliwia błyskawiczne powiadamianie zespołu o krytycznych błędach, co zwiększa przejrzystość pracy i pozwala szybciej reagować na problemy, minimalizując czas blokady procesu wdrożeniowego.
Takie kompleksowe podejście do debugowania i logowania w Cypress znacząco podnosi stabilność i transparentność testów automatycznych oraz przyspiesza proces wytwarzania oprogramowania.
Autorem tekstu jest Łukasz Wieczorek





