Jak odróżnić rzeczywisty błąd od niestabilnego testu?
Uruchom test kilka razy z wyłączonymi ponownymi próbami i policz wyniki. Rzeczywisty błąd powoduje takie samo niepowodzenie przy każdym uruchomieniu, a niestabilny test czasem przechodzi, a czasem nie, mimo braku zmian. Poniższy przykład robi dokładnie to na dowolnym komputerze z Playwright, a następnie pokazuje, jak Nexus Studio obsługuje każdy wynik.
Autorzy: zespół Nexus Studio, Verdict System LLC. 27 października 2026.
Jak odróżnić je w minutę?
Uruchom test kilka razy z rzędu z wyłączonymi ponownymi próbami. W Playwright służą do tego dwie flagi: --retries=0, aby ponowna próba nie mogła ukryć niepowodzenia, oraz --repeat-each=6, która uruchamia każdy test sześć razy. Następnie policz wyniki każdego testu.
- Nie przeszedł ani razu: traktuj to jako błąd, dopóki nie wykażesz, że jest inaczej. Niepowodzenie przy każdym uruchomieniu może też wynikać ze środowiska, na przykład zablokowanego żądania lub niedostępnego hosta, więc najpierw przeczytaj komunikat błędu.
- Czasem przechodził, a czasem nie: test jest niestabilny. Kod i test nie zmieniały się między uruchomieniami, więc przyczyną jest coś niestabilnego w aplikacji lub w teście.
- Przeszedł za każdym razem: na razie nic nie widać. Usterka, która ujawnia się raz na pięćdziesiąt uruchomień, wymaga większej liczby uruchomień lub zajrzenia do Historii testu.
Czy mogę sprawdzić to na przykładzie, który da się uruchomić?
Zapisz to jako bug-or-flaky.spec.js. Pierwszy test symuluje niestabilność: nie przechodzi przy jednym na trzy uruchomienia. Drugi test wykrywa rzeczywisty błąd: strona wyświetla "Welcome", a test oczekuje "Welcome back", więc nie może przejść przy żadnym uruchomieniu.
import { test, expect } from '@playwright/test';
// Fails on its first attempt of every third run, passes otherwise: a simulated flake.
test('flaky: a slow load now and then', async ({ page }, info) => {
await page.setContent('<h1>Welcome</h1>');
expect((info.repeatEachIndex + info.retry) % 3, 'simulated slow load').not.toBe(0);
});
// Fails the same way every time: the heading says "Welcome", the test expects "Welcome back".
test('real bug: wrong heading', async ({ page }) => {
await page.setContent('<h1>Welcome</h1>');
await expect(page.locator('h1')).toHaveText('Welcome back', { timeout: 300 });
});
Uruchom go sześć razy z wyłączonymi ponownymi próbami:
npx playwright test --retries=0 --repeat-each=6
Playwright kończy z 8 niepowodzeniami i 4 powodzeniami. Odpowiedź na pytanie daje liczba wyników dla każdego testu, którą moduł raportujący w formie listy wypisał wiersz po wierszu:
flaky: a slow load now and then 4 passed, 2 failed
real bug: wrong heading 0 passed, 6 failed
Teraz uruchom go raz z dwiema ponownymi próbami:
npx playwright test --retries=2
Playwright kończy z jednym testem w każdej grupie. Niestabilny test nie przeszedł za pierwszym razem, ale przeszedł przy ponownej próbie #1. Test wykrywający rzeczywisty błąd nie przeszedł w żadnej z trzech prób.
1 failed
bug-or-flaky.spec.js:10:1 › real bug: wrong heading
1 flaky
bug-or-flaky.spec.js:4:1 › flaky: a slow load now and then
Czy udana ponowna próba oznacza, że aplikacja działa prawidłowo?
Nie. Udana ponowna próba mówi tylko tyle, że próby dały różne wyniki. Jeśli wynik uruchomienia zmieni się na zielony i nikt go nie sprawdzi, sporadyczna usterka w aplikacji, taka jak wyścig, współdzielone dane czy wolno działająca zależność, staje się niewidoczna, a takie usterki należą do najdroższych do wykrycia. Traktuj niestabilny wynik jako wykryty problem, a nie sukces, który można zignorować, i nie zakładaj, że wina leży po stronie testu.
Jak Nexus Studio obsługuje każdy wynik?
Nexus Studio rejestruje każdą próbę i przypisuje wynikowi osobną ocenę, więc ponowna próba nigdy nie zamienia usterki w zwykły zielony wynik.
- FLAKY: test nie przeszedł, potem przeszedł przy ponownej próbie, choć niczego nie naprawiono. Kończy się kodem 0, więc nie przerywa procesu budowania, a raport i Historia pokazują zastrzeżenie.
- BREACHED: test nie przeszedł w jednej próbie, a błędu nie wyjaśnia żaden wzorzec związany ze środowiskiem ani infrastrukturą testową. Kończy się kodem 1.
- BREACHED_FLAKY: test nie przeszedł w ostatniej próbie po wcześniejszej ponownej próbie, a niepowodzenia nie wyjaśnia żaden wzorzec związany ze środowiskiem. Kończy się kodem 1. Porównaj próby, zanim zgłosisz błąd.
Historia zachowuje jeden wiersz na każde uruchomienie każdego testu, więc test, którego wynik zmienia się z zielonego na czerwony i znów na zielony, ujawnia trend zamiast znikać w kolejnych uruchomieniach. Poradnik dotyczący niestabilnych testów wymienia pliki pozostawiane przy każdej ocenie.
Jakie są ograniczenia?
- Niestabilność w przykładzie jest symulowana za pomocą działań arytmetycznych, aby była powtarzalna. Rzeczywista niestabilność ma przyczynę, a jej znalezienie nadal wymaga pracy człowieka.
- Sześć uruchomień to szybkie sprawdzenie, nie statystyka. Test, który nie przechodzi raz na pięćdziesiąt uruchomień, może przejść sześć razy z rzędu.
- Niepowodzenie przy każdym uruchomieniu nie zawsze oznacza błąd w aplikacji: wolna sieć, strona blokady lub niedziałająca przeglądarka też powodują niepowodzenia testów. Poradnik dotyczący fałszywych niepowodzeń pokazuje, jak je rozróżnić.
- Gdy ponawianie prób jest wyłączone, sporadyczne niepowodzenie w Nexus Studio otrzymuje status BREACHED, ponieważ tylko ponowna próba pozwala odróżnić FLAKY od zwykłego niepowodzenia. Klasyfikacja opiera się na treści błędu, więc otwórz metadata.json, gdy werdykt Cię zaskoczy.
Gdzie mogę to zobaczyć?
Przewodnik po werdyktach wyjaśnia, w jakiej kolejności silnik ustala wszystkie 14 werdyktów, a strona z materiałem dowodowym śledzi jeden nieudany test przez wszystkie pozostawione przez niego pliki. 30-dniowa wersja próbna pozwala uruchomić ten sam silnik na własnych testach.