AI do testów oprogramowania: generowanie przypadków i stabilne asercje

0
33
2.5/5 - (2 votes)

Nawigacja:

Scenka z życia: kiedy testy nie nadążają za zmianami

Release w każdy piątek, product owner naciska na kolejne usprawnienia, a QA od środy żyje tylko kopiuj–wklej w Jirze i odpalaniem kolejnych zestawów regresji. W piątek wieczorem developer zamiast piwa z ekipą „naprawia” testy E2E, które posypały się po zmianie klasy CSS przycisku, mimo że produkt działa lepiej niż przed zmianą. Gdzieś między flakami w CI a rosnącą listą TODO pojawia się pytanie: czy AI może realnie pomóc, czy tylko dołoży kolejną warstwę chaosu?

W takim środowisku problem rzadko polega wyłącznie na braku czasu. Głębiej w architekturze testów często kryje się słaba definicja tego, co testujemy i jak weryfikujemy wynik. Zbyt dużo przypadków testowych, zbyt mało priorytetyzacji, za mało stabilnych asercji, które przetrwają drobne zmiany w interfejsie czy refaktoryzację. AI może pomóc w generowaniu przypadków testowych i usprawnieniu asercji, ale tylko wtedy, gdy zostanie włączona w proces z głową, jako wsparcie, a nie magiczny automat.

Wprowadzenie AI do testów oprogramowania zmienia przede wszystkim to, jak szybko powstają szkice testów i jak szerokie spektrum scenariuszy można rozważyć. Kluczowe staje się ułożenie procesu: od sposobu podawania kontekstu, przez generowanie przypadków testowych, aż po tworzenie stabilnych asercji, które nie rozpadną się przy każdym drobnym redesignie.

Mini-wniosek z tej scenki jest prosty: tam, gdzie testy stale „gonią” produkt, problem nie leży tylko w objętości pracy QA, ale w jakości definicji zachowania systemu, jakie testy próbują uchwycić. AI może pomóc tę definicję doprecyzować, ustrukturyzować i przekształcić w lepsze przypadki testowe, ale wymaga to świadomego podejścia.

Czego konkretnie oczekiwać od AI w testach oprogramowania

AI w testach oprogramowania łatwo przecenić. LLM brzmią jak obietnica „generatora testów na klik”, ale w praktyce bliżej im do bardzo szybkiego, nie do końca obeznanego w domenie juniora, któremu trzeba dać kontekst, ramy i dobry feedback.

AI jako generator pomysłów kontra producent kodu testów

Najważniejsze rozróżnienie to oddzielenie dwóch ról: AI jako generator pomysłów na testy oraz AI jako autor produkcyjnego kodu testów automatycznych. W pierwszej roli model pomaga wymyślić:

  • scenariusze użytkownika – standardowe ścieżki „happy path” i mniej oczywiste warianty,
  • dane wejściowe – wartości graniczne, nietypowe formaty, kombinacje parametrów,
  • scenariusze błędów – co się dzieje, gdy usługa pomocnicza jest niedostępna, payload jest niekompletny, itp.

To obszar, w którym generowanie przypadków testowych przez AI potrafi przynieść duży zysk w krótkim czasie. LLM dobrze radzi sobie z eksploracją przestrzeni możliwości na podstawie opisu funkcji, API czy zrzutów z logów.

Druga rola – generowanie gotowego kodu testów – wymaga więcej ostrożności. AI potrafi wygenerować test w Playwright, Cypressie, JUnit czy pytest, ale:

  • nie zna twojej konwencji nazewnictwa, struktury katalogów, helperów testowych,
  • często pomija setup/teardown lub przygotowanie danych testowych zgodne z waszym projektem,
  • może produkować niestabilne asercje, np. oparte na pełnym tekście komunikatów czy selektorach podatnych na zmiany UI.

Zdrowe podejście: traktować AI głównie jako generator szkiców, a nie finalnego kodu. Szkice pomagają szybciej wystartować, ale musi je przejrzeć ktoś z kontekstem projektu.

Obszary, w których LLM błyszczy

Najlepiej wykorzystać AI tam, gdzie jej zdolność do „kombinowania” i pracy z językiem naturalnym jest najbardziej użyteczna:

  • Scenariusze użytkownika – z user story „jako klient chcę zamówić produkt z dostawą do paczkomatu” AI potrafi wypisać kilka alternatywnych ścieżek: z kuponem rabatowym, bez logowania, z błędnym adresem, z brakiem produktów na stanie itp.
  • Dane wejściowe i warianty krawędziowe – dla formularza rejestracji AI wygeneruje listę emaili z nietypowymi domenami, polskimi znakami, spacjami, skrajnie długich loginów, kombinacji znaków specjalnych.
  • Testy regresyjne oparte na danych – na podstawie historii błędów i logów AI może podsunąć zestaw przypadków regresyjnych, które warto utrwalić w automatach.

LLM świetnie sprawdza się też jako asystent QA do wstępnego grupowania i porządkowania przypadków testowych: grupuje je według ryzyka, priorytetu czy obszaru funkcjonalnego, co ułatwia planowanie regresji.

Granice możliwości: gdzie AI zawodzi

Są obszary, w których AI obecnie nie radzi sobie dobrze i bez nadzoru eksperta QA lub developera może wprowadzić zespół w błąd:

  • Głębokie zrozumienie domeny – AI nie wie, jakie reguły prawne cię obowiązują, jak twoja organizacja interpretuje „aktywny klient” czy kiedy transakcja jest „zakończona”. Bez jasnego wyjaśnienia tych zasad model będzie wymyślał pozornie sensowne, ale biznesowo błędne testy.
  • Zależności systemowe – złożone integracje między mikroserwisami, kolejkami, bazami danych i cache są trudne do zrozumienia tylko z krótkiego promptu.
  • Bezpieczeństwo i prywatność – generowanie testów bezpieczeństwa przez AI może być inspirujące, ale nie zastąpi specjalistycznych narzędzi i wiedzy z obszaru security.

Bez doprecyzowanego kontekstu AI bywa jak nowy tester „z ulicy” – szybki, kreatywny, ale ryzykowny, gdy ma podejmować samodzielne decyzje.

AI jako „junior QA”, nie kopiarka kodu

Najbardziej produktywny mindset to traktowanie AI jako junior QA o turbo-szybkości, a nie jako automat do kopiowania istniejącego kodu testów. Junior:

  • zadaje dużo pytań (czyli wymaga doprecyzowanego promptu),
  • potrzebuje code review,
  • może wpaść na pomysł scenariusza, którego doświadczony tester by nie wymyślił „z przyzwyczajenia”,
  • ale nie powinien samodzielnie zatwierdzać niczego do produkcji.

Im precyzyjniej określisz rolę AI – np. „pomóż wygenerować 20 kandydatów na przypadki testowe dla tego endpointu, w 3 kategoriach: happy path, błędy walidacji, błędy integracji” – tym sensowniejsze wyniki otrzymasz.

Mini-wniosek: realny zysk z AI w QA zaczyna się tam, gdzie rola modelu jest jasno zdefiniowana i ograniczona, a człowiek zachowuje kontrolę nad selekcją, doprecyzowaniem i implementacją.

Zbliżenie ekranu z kodem PHP podczas pracy nad oprogramowaniem
Źródło: Pexels | Autor: Pixabay

Typy testów, które najlepiej nadają się do wsparcia przez AI

Nie wszystkie testy w projekcie jednakowo korzystają z pomocy AI. Zamiast próbować „przepisać” cały proces QA na generatywne modele, bardziej efektywne jest wskazanie tych typów testów, gdzie korzyść jest najbardziej wyraźna.

Testy jednostkowe: kombinacje wejść i scenariusze błędów

Przy pisaniu testów jednostkowych developerzy często zatrzymują się na kilku oczywistych przypadkach: standardowy input, pojedynczy błąd, może prosty warunek brzegowy. AI może tę przestrzeń poszerzyć.

Na podstawie krótkiego opisu funkcji lub fragmentu kodu, LLM może:

  • wygenerować listę wartości granicznych (minimalne, maksymalne, tuż przed/po granicy),
  • zaproponować różne kombinacje parametrów, w tym zestawy z null, pustymi stringami, nieprawidłowymi typami,
  • podsunąć opisowe nazwy przypadków testowych, co często bywa niedocenianym, ale ważnym aspektem czytelności testów.

Przykład użycia AI:

„Masz funkcję calculateDiscount(price, customerType, couponCode). Wypisz 15 potencjalnych przypadków testowych w formacie: nazwa_case’u, wejście, spodziewane zachowanie (opis). Podziel je na: happy path, błędne dane wejściowe, kombinacje graniczne.”

Takie generowanie przypadków testowych przez AI daje szybki „backlog” do pokrycia w testach jednostkowych, a programista wybiera z niego to, co krytyczne dla domeny.

Testy integracyjne i kontraktowe: nietypowe scenariusze request/response

Testy integracyjne i testy kontraktowe szczególnie dobrze „leżą” AI, bo bazują na strukturach danych i protokołach, które łatwo opisać w tekstowej formie. Na podstawie Swaggera/OpenAPI, fragmentu kontraktu, schema JSON czy przykładowych logów AI może:

  • wygenerować listę wariantów requestów – poprawnych, częściowo poprawnych, błędnych, z brakującymi nagłówkami, z nieoczekiwanymi polami,
  • zapropnować spodziewane odpowiedzi, kody statusu, komunikaty błędów,
  • wskazać scenariusze związane z timeoutami, retry, niekompatybilnymi wersjami kontraktów.

W testach kontraktowych mieliśmy do niedawna głównie dwa źródła inspiracji: dokumentację i realne błędy. AI dokłada trzeci: kreatywne „co jeśli”, oparte o wiedzę z szerokiej bazy przypadków spotykanych w świecie API.

Testy E2E i UI: scenariusze użytkownika, nie piksele

Testy end-to-end i testy UI to obszar, w którym AI najczęściej budzi oczekiwania „pełnej automatyzacji”. Trzeba tu jednak zachować rozsądek.

Największa siła AI to:

  • wymyślanie różnorodnych ścieżek użytkownika – nie tylko prostego „zaloguj – kup – zapłać”, ale np. porzucone koszyki, zmiana adresu w trakcie, przejście do innej sekcji i powrót, użycie wyszukiwarki, zmiana języka interfejsu,
  • wyszukiwanie testów nawigacji – przejścia między widokami, kombinacje kliknięć, które mogą powodować dziwne stany,
  • podpowiedzi do testów walidacji formularzy – różne kombinacje poprawnych, częściowo poprawnych i błędnych pól.

Z kolei słabością AI jest generowanie konkretnych interakcji z UI związanych z selektorami. Gotowy kod typu cy.get('.button-primary') od AI bywa ładny, ale bardzo kruchy. Lepiej, by AI opisała intencję scenariusza („kliknij przycisk potwierdzający zamówienie w koszyku”), a człowiek przekuł to w stabilne selektory i asercje.

Testy niefunkcjonalne: inspiracja, nie zastępstwo narzędzi

W obszarze testów wydajnościowych, obciążeniowych czy odpornościowych AI jest przydatna głównie jako narzędzie koncepcyjne:

  • proponuje rodzaje obciążenia (stałe, rosnące, burst),
  • pomaga zdefiniować parametry scenariuszy w JMeter/Gatling/k6,
  • podpowiada, jakie metryki monitorować i jakie progi uznać za alarmowe (z zastrzeżeniem, że to trzeba skonfrontować z realiami systemu).

Mini-wniosek: na starcie najlepiej wybrać 1–2 typy testów, gdzie AI przynosi szybki, mierzalny zysk – zazwyczaj testy integracyjne/kontraktowe oraz rozszerzone scenariusze dla testów jednostkowych. Dopiero po „oswojeniu” narzędzia warto rozszerzać zakres na testy E2E i niefunkcjonalne.

Jak karmić AI informacjami o systemie: specyfikacja, kod, logi

Jakość wygenerowanych testów jest ściśle powiązana z jakością tego, co dostanie model. „Śmieci na wejściu – śmieci na wyjściu” w przypadku LLM oznacza lakoniczne, ogólnikowe przypadki testowe, które niewiele wnoszą. Natomiast dobrze zorganizowany kontekst potrafi przemienić AI w realnego pomocnika QA.

Źródła danych dla AI: od user stories po logi błędów

Najbardziej użyteczne źródła informacji o systemie, które można wykorzystać w promptach, to:

  • User stories i wymagania – opisują zachowanie z perspektywy biznesu, dzięki czemu AI może zaproponować testy na poziomie scenariuszy użytkownika.
  • Specyfikacje API (Swagger/OpenAPI) – świetna baza do generowania przypadków dla testów kontraktowych, wariantów request/response i walidacji.
  • Istniejące testy – pomagają AI zrozumieć styl projektu, główne zależności i przykłady dobrych asercji.
  • Logi błędów i zgłoszenia z produkcji – stanowią realne przykłady tego, gdzie system się wykłada; AI może z nich budować testy regresyjne.
  • Przykładowe payloady i dane testowe – ułatwiają generowanie dodatkowych wariantów danych, bardziej realistycznych niż czysto podręcznikowe wartości.

Jak przygotować kontekst dla modelu: „paczka wiedzy o systemie”

W wielu zespołach rozmowa z AI wygląda tak: ktoś wkleja jedno user story i prosi o „testy E2E”. Po chwili pada werdykt: „AI generuje ogólniki, słabe to”. Problem rzadko leży w modelu – zwykle w tym, że dostał on szczątkowy obraz systemu.

Dużo lepszą strategią jest traktowanie promptu jak paczki wiedzy, którą przekazujesz nowej osobie w zespole. W praktyce taka paczka może składać się z kilku logicznych bloków:

  • Kontekst biznesowy – 2–4 zdania o domenie („system do obsługi zamówień B2B, gdzie…”, „aplikacja bankowa dla klientów indywidualnych…”).
  • Zasady domenowe – skrót reguł biznesowych, które wpływają na testy („zamówienie można anulować tylko do momentu wysyłki”, „kupon rabatowy jest jednorazowy i nie łączy się z promocjami”).
  • Wybrany fragment specyfikacji – np. schema endpointu, opis funkcji, makieta ekranu.
  • Przykłady istniejących testów – 2–3 testy pokazujące styl asercji, nazewnictwo i strukturę danych testowych.
  • Cel zadania dla AI – jasno sformułowana rola („wygeneruj listę przypadków testowych”, „zaproponuj asercje do istniejących scenariuszy”, „uogólnij i ustabilizuj selektory/oczekiwania”).

Przy tak przygotowanym kontekście model zachowuje się jak nowy członek zespołu, który dostał onboardingowy pakiet dokumentów, zamiast tylko jednego screena z aplikacji.

Mini-wniosek: im bardziej strukturalnie zbierzesz wiedzę o systemie w promptach, tym bliżej jesteś sensownych, powtarzalnych wyników – zamiast losowej „twórczości”.

Jak unikać „zalania” modelu informacjami

Drugi biegun problemu to podejście „wrzućmy wszystko”. Kilkanaście tysięcy linii Swaggera, kilkadziesiąt testów, logi z ostatniego miesiąca – i potem zdziwienie, że model gubi się albo ignoruje część materiału.

Lepszą taktyką jest podzielenie zadania na mniejsze kroki i świadome ograniczenie kontekstu:

  • dla jednego endpointu API – tylko jego fragment specyfikacji, powiązane user stories i 2–3 przykładowe requesty/response’y,
  • dla jednego ekranu UI – opis scenariusza biznesowego, zrzut makiety/struktury DOM (skrócony) i istniejące testy E2E, jeśli są,
  • dla jednostkowego modułu – wybrany plik z kodem, interfejsy zależności i kilka istniejących testów, zamiast całego repo.

Jeżeli danych jest dużo, sensowny workflow wygląda tak:

  1. Najpierw poproś AI o streszczenie długiej specyfikacji lub logów (w punktach, pod kątem potencjalnych ryzyk/testów).
  2. Potem użyj tego streszczenia jako kompasu do generowania konkretnych przypadków testowych lub asercji.

W praktyce zespół backendowy jednego z projektów zrobił tak z logami błędów: najpierw model wypunktował typy awarii i nietypowe kombinacje requestów, a dopiero na tej bazie generowane były testy regresyjne dla najbardziej bolesnych scenariuszy.

Bezpieczeństwo danych a korzystanie z AI

Gdy w grę wchodzą logi, payloady i fragmenty kodu, pojawia się od razu temat bezpieczeństwa. Kilka prostych zasad ogranicza ryzyko do rozsądnego minimum:

  • Anonimizacja danych – usuń lub zmaskuj dane osobowe, identyfikatory klientów, numery dokumentów, nawet jeśli narzędzie deklaruje zgodność z regulacjami.
  • Redukcja zakresu – zamiast przesyłać pełne logi, wybierz reprezentatywne fragmenty, wytnij nieistotne pola, zredukuj payload do minimalnego zestawu potrzebnego do zrozumienia problemu.
  • Środowisko – w miarę możliwości korzystaj z rozwiązań wdrożonych w obrębie organizacji (self-hosted lub w ramach tenantów korporacyjnych), a nie z przypadkowych publicznych narzędzi w przeglądarce.

Jeśli pracujesz w sektorze regulowanym, dobrą praktyką jest przygotowanie „bezpiecznego zestawu przykładów” – syntetyczne dane, scenki i payloady, na których można ćwiczyć z AI i dopiero później przenosić wypracowane schematy na realne środowisko.

Generowanie przypadków testowych z pomocą AI – proces krok po kroku

Wyobraź sobie, że dostajesz świeżutki endpoint „/orders/{id}/cancel”. Deadline się zbliża, a ty musisz szybko wymyślić sensowny zestaw testów. Zamiast samotnie wpatrywać się w Swaggera, można potraktować model jako partnera w burzy mózgów.

Krok 1: Zdefiniuj cel – co konkretnie ma powstać

Zanim wkleisz specyfikację, doprecyzuj, jakiego rodzaju wyniku oczekujesz. Przykładowe cele:

  • lista opisowych przypadków testowych (bez kodu),
  • szkielet testów jednostkowych w danym frameworku (np. JUnit, pytest),
  • propozycje asercji dla istniejących scenariuszy,
  • zestaw danych testowych do określonego przypadku.

Im bardziej precyzyjne jest zadanie, tym mniej „domysłów” po stronie AI. Zamiast „wygeneruj testy dla tego endpointu”, lepiej: „wygeneruj 15 opisowych przypadków testowych dla anulowania zamówienia, podzielonych na: poprawne anulowanie, błędy walidacji, błędy stanów biznesowych”.

Krok 2: Dostarcz minimalny, ale wystarczający kontekst

Na tym etapie dorzucasz do promptu to, co jest kluczowe dla zrozumienia problemu. Dla endpointu anulowania zamówienia może to być:

  • fragment specyfikacji API (metoda, ścieżka, parametry, odpowiedzi),
  • lista statusów zamówienia („NEW, PAID, SHIPPED, DELIVERED, CANCELLED”) i reguły przejść między nimi,
  • krótki opis procesu biznesowego: kto, kiedy i z jakiego miejsca systemu może anulować zamówienie.

Dobry prompt w takiej sytuacji może wyglądać tak (skrócony przykład):

Jesteś doświadczonym testerem API w e-commerce.
System ma endpoint do anulowania zamówienia:
[tu wklejony fragment OpenAPI]

Statusy zamówienia: NEW, PAID, SHIPPED, DELIVERED, CANCELLED.
Zasady:
- zamówienie można anulować tylko w statusach NEW i PAID,
- anulowanie musi zwrócić kod 200 z aktualnym statusem,
- próba anulowania w innych statusach powinna zwrócić 409.

Wygeneruj 15 opisowych przypadków testowych (bez kodu), 
w formacie: nazwa_case'u, preconditions, request, expected result.
Podziel na 3 kategorie: happy path, błędne dane wejściowe, błędy stanów biznesowych.

Taka struktura daje modelowi jasne ramy i redukuje potrzebę „zgadywania” domeny.

Krok 3: Poproś o strukturę i kategoryzację przypadków

Nie chodzi tylko o to, żeby AI „nasypała” przypadków testowych. Chodzi o strukturę, którą da się przełożyć na plan prac. Dlatego opłaca się od razu poprosić o:

  • kategoryzację (np. według typu ścieżki, typu błędu, poziomu ryzyka),
  • policzalny limit (np. „maksymalnie 20 przypadków”),
  • zwięzły, powtarzalny format (nazwa, kroki, dane, oczekiwany rezultat).

Jedno dodatkowe zdanie w promptcie typu: „unikaj powtarzania bardzo podobnych przypadków, jeśli różnią się tylko detalem technicznym” znacząco podnosi jakość wyników – model zaczyna łączyć zbliżone scenariusze, zamiast produkować wariacje tego samego testu.

Krok 4: Wspólne doprecyzowanie – iteracja zamiast jednorazowego strzału

Po pierwszej odpowiedzi rzadko kiedy dostajesz listę idealnych kandydatów. Rolą człowieka jest tu zrobienie szybkiego przeglądu i dopytanie modelu w miejscach, które wyglądają niejasno lub zbyt ogólnie:

  • „Rozwiń przypadki związane z błędami autoryzacji, dodaj 3 konkretne scenariusze.”
  • „Zaproponuj dodatkowe przypadki, które uwzględniają równoczesne zmiany statusu przez inny serwis.”
  • „Połącz te dwa bardzo podobne przypadki w jeden i zaproponuj minimalny zestaw danych wejściowych.”

Taka mini-iteracja działa podobnie jak rozmowa z juniorem w zespole: najpierw ogólny szkic, potem doprecyzowanie i przycinanie zbędnych wariantów.

Krok 5: Selekcja i nadanie priorytetów

Nawet najlepsza lista wygenerowana przez AI nie jest jeszcze planem testów. Potrzebujesz nałożyć na nią filtr ryzyka, biznesowej krytyczności i kosztu implementacji. Ten etap możesz częściowo również oprzeć o model:

  1. Samodzielnie zaznacz w liście testy, które intuicyjnie wydają się kluczowe (np. przyjęte konwencją: P1, P2, P3).
  2. Poproś AI: „Zakładając, że mamy czas na implementację maksymalnie 8 przypadków z tej listy, zaproponuj ranking priorytetów z krótkim uzasadnieniem.”
  3. Skonfrontuj propozycję z realiami – regulator, SLA, historia incydentów produkcyjnych.

W jednym z projektów fintechowych taki ranking pomógł zespołowi odłożyć na później mało prawdopodobne scenariusze techniczne, a skupić się na przypadkach, które mogły prowadzić do błędów salda klienta – mimo że z programistycznej perspektywy były „nudne i oczywiste”.

Krok 6: Przekucie opisów na kod testów

Na tym etapie masz już listę przypadków w ludzkim języku. Kolejny ruch to przełożenie ich na konkretne testy w narzędziu, którego używa zespół. Można wykorzystać AI także tutaj, ale z zastrzeżeniem większej ostrożności.

Dobrym schematem jest:

  • wskazanie frameworka i konwencji używanych w projekcie (np. „używamy pytest, testy nazywamy test_, stosujemy given/when/then w komentarzach”),
  • wklejenie 1–2 przykładowych testów z repozytorium jako wzorca kodu,
  • wybranie kilku priorytetowych przypadków z listy i poproszenie o szkielety testów w tym stylu.

Przykładowy prompt:

Tu są 2 przykładowe testy API w naszym projekcie (pytest + requests):
[tu wklejony kod]

Na podstawie tych przykładów i przypadków testowych 1, 2, 3 z poniższej listy:
[tu wklejona lista przypadków]

Wygeneruj szkielety testów w tym samym stylu, bez mocków i bez danych konfiguracyjnych.
Zostaw TODO w miejscach, gdzie trzeba uzupełnić dane środowiskowe.

Taki sposób wykorzystania modelu oszczędza czas na „klepaniu” struktury testu, ale decyzje co do danych, mocków czy konkretnych asercji nadal zostają po stronie developera/QA.

Krok 7: Review, stabilne asercje i refaktoryzacja

Ostatni etap bywa najczęściej pomijany: testy od AI lądują od razu w repo i po kilku sprintach nikt nie wie, czemu co drugi jest kruchy. Żeby tego uniknąć, warto dodać mini-fazę review skupioną na trzech elementach:

  • Stabilność asercji – czy test nie zależy od elementów zmiennych (dokładny tekst komunikatu bez potrzeby, timestamp w sekundach, kolejność pól w JSON), które nie są esencją zachowania?
  • Powtarzalność danych – czy istnieją dane testowe, które zapewniają stabilne wyniki (np. dedykowane konta testowe, deterministyczne generatory danych), a nie losowo generowane wartości w każdym przebiegu?
  • Czytelność nazewnictwa – czy nazwy testów i opisów jasno mówią, co jest weryfikowane, i czy ułatwią diagnozę przy ewentualnej awarii?

AI może tu jeszcze raz pomóc, np. w uogólnieniu zbyt szczegółowych asercji. Przykład promptu:

To jest test UI wygenerowany wcześniej:
[tu wklejony test]

Asercje są zbyt kruche (zależne od pełnego tekstu komunikatu
i konkretnego selektora CSS). Zaproponuj stabilniejsze asercje,
które skupiają się na:
- tym, że zamówienie zostało utworzone (np. status, numer zamówienia),
- tym, że użytkownik widzi potwierdzenie w odpowiedniej sekcji strony,
bez zależności od dokładnego tekstu i klasy CSS.

Na tej podstawie dostajesz propozycje zamiany pełnego porównania tekstu na sprawdzenie fragmentów, a klas CSS – na selektory oparte na data-testid lub strukturze semantycznej, jeśli takie są dostępne.

Łączenie generowania przypadków z budową regresji

Ciekawym zastosowaniem jest użycie AI do budowy „żywej” regresji opartej na incydentach z produkcji. Schemat działania bywa prosty:

  1. Po incydencie zbierasz logi, payloady i opis zachowania.
  2. Prosisz AI o opisowy przypadek testowy odwzorowujący problem – w takim samym formacie, jak pozostałe przypadki.
  3. Budowanie regresji z incydentów – jak nie zgubić kontekstu

    Po większym incydencie często kończy się na jednym tickecie „naprawione w hotfixie”. Miesiąc później ten sam błąd wraca, tylko pod innym endpointem. Źródłowy problem: nikt nie przełożył incydentu na konkretny, powtarzalny test regresyjny.

    AI pomaga tu w dwóch miejscach: w „odszumianiu” materiału z produkcji i w przekuciu go na regresję, która ma sens biznesowy, a nie tylko techniczny.

  1. Oczyszczenie danych incydentu – zrzut logów, payloady, stacktrace’y bywają chaotyczne. Model może:
    • zebrać z nich spójny przebieg zdarzeń w kilku krokach,
    • wypunktować warunki brzegowe, które doprowadziły do błędu (np. konkretny status zasobu, nietypowa kombinacja parametrów),
    • odciąć elementy nieistotne (szum z innych requestów, retry z load balancera).
  2. Stworzenie test case’u odwzorowującego incydent – na bazie oczyszczonego opisu prosisz o:
    • 1–2 konkretne scenariusze regresyjne (np. „aktualizacja zamówienia po częściowej wysyłce”),
    • jasne preconditions możliwe do ustawienia w środowisku testowym,
    • oczekiwany rezultat zarówno z perspektywy API, jak i użytkownika końcowego.

Dobry prompt może wyglądać tak:

Masz logi z incydentu w systemie płatności:
[tu wklejone logi + payloady + opis zgłoszenia od supportu]

1) Streść krok po kroku, co zrobił użytkownik i system.
2) Wyodrębnij minimalny zestaw preconditions do odtworzenia błędu.
3) Na tej podstawie zdefiniuj 2 przypadki testowe regresji
   w formacie: nazwa, preconditions, kroki, dane, oczekiwany rezultat.

Po otrzymaniu opisów dodajesz je do katalogu przypadków regresyjnych, a dopiero potem – w wybranym momencie sprintu – tłumaczysz na kod testów. Dzięki temu incydent przestaje być jednorazowym „pożarem”, a staje się punktem w stałym, żywym zbiorze testów.

Stabilne asercje oparte na intencji, a nie na pikselach

W jednym z projektów frontendowych co deploy QA dostawał serię „false alarmów”: testy E2E padały po zmianie fontu lub układu kart na stronie. Technicznie wszystko działało, biznesowo też, ale asercje były przywiązane do konkretnych selektorów i pełnych tekstów komunikatów.

Jeśli do gry wchodzi AI, bardzo łatwo wygenerować jeszcze więcej takich kruchych testów. Żeby temu zapobiec, trzeba uporządkować, co właściwie ma być weryfikowane.

Dobrą praktyką jest opisanie intencji asercji przed kodem. Na przykład:

  • zamiast: „tekst komunikatu = 'Zamówienie zostało utworzone pomyślnie’”,
  • formułujesz: „użytkownik widzi czytelne potwierdzenie utworzenia zamówienia w sekcji podsumowania koszyka”.

Z takim opisem możesz poprosić model o propozycje stabilniejszych asercji:

To jest opis testu E2E:
[opis biznesowy scenariusza]

Zaproponuj asercje, które:
- są odporne na zmianę kolejności elementów na stronie,
- nie zależą od dokładnego brzmienia komunikatu (byleby sens był ten sam),
- skupiają się na tym, że zamówienie jest utworzone i widoczne
  w sekcji podsumowania.

Podaj przykłady asercji w Playwright (TypeScript),
wykorzystując data-testid oraz częściowe dopasowanie tekstu.

Efekt to zwykle zestaw asercji typu „element o data-testid=’order-summary’ zawiera numer zamówienia” zamiast „drugi paragraf w trzecim divie ma dokładnie taki tekst”. Mniej przypadkowych awarii testów i mniej złości na CI.

AI jako partner do porządkowania istniejącego zestawu testów

Zdarza się, że zespół ma już sporą paczkę testów, ale nikt nie potrafi powiedzieć, co one faktycznie pokrywają. Ktoś dorzucił swoje E2E, ktoś inny swoje testy integracyjne, część przyszła z innego projektu. Wszystko działa, dopóki nie trzeba zredukować czasu wykonania o połowę.

Model językowy jest przydatny jako „lupa” do takiego zbioru. Nie po to, by decydować za zespół, co usunąć, tylko by nadać strukturę i odkleić się od poziomu pojedynczych plików.

Przykładowe kroki:

  1. Zbierasz metadane testów – np. nazwy, ścieżki plików, tagi, krótkie opisy (jeśli są), a także fragmenty kodu asercji.
  2. Wrzucasz próbkę do AI z prośbą o:
    • grupowanie scenariuszy według obszarów biznesowych,
    • wskazanie duplikatów lub mocno zachodzących na siebie przypadków,
    • oznaczenie testów, które wydają się czysto techniczne (np. sprawdzające tylko kolejność pól w odpowiedzi).
  3. Na tej bazie decydujesz, które testy łączysz, które przenosisz na inny poziom (z E2E na integracyjne), a które spokojnie możesz wyłączyć lub otagować jako „legacy”.

Przykład promptu dla wycinka testów:

Masz listę testów API z krótkimi opisami i fragmentami kodu:
[tu lista: nazwa, opis, istotne asercje]

1) Pogrupuj testy według funkcji biznesowej (np. "płatności", "zwroty").
2) Wskaż grupy testów, które wydają się duplikować ten sam scenariusz.
3) Zaproponuj, które z nich można połączyć w 1–2 stabilniejsze testy,
   bez utraty istotnego pokrycia.

Takie spojrzenie z góry pomaga zapanować nad rozrostem testów, a AI przyspiesza to porządkowanie o kilka sprintów.

Łączenie AI z kontraktami i testami integracyjnymi

W systemach opartych na mikroserwisach część najbardziej bolesnych błędów wynika z drobnych rozjazdów między usługami: tu int zmieniony na string, tam brak pola, gdzie indziej pole opcjonalne nagle staje się wymagane. Kontrakty OpenAPI, protobuf czy Avro niby istnieją, ale testy kontraktowe często są ubogie.

AI można wciągnąć w ten obszar na trzy sposoby:

  • Analiza zmian kontraktów – porównanie dwóch wersji specyfikacji i opisanie ryzyk.
  • Generowanie przypadków testów kontraktowych – na bazie samego kontraktu + kilku reguł biznesowych.
  • Pomoc w osadzeniu testów kontraktowych w pipeline – szkielety testów dla konsumentów i providerów.

Przykładowy scenariusz: zmienia się definicja endpointu zwrotów w OpenAPI. Zamiast ręcznego przeklikiwania diffów, wrzucasz starą i nową wersję do modelu:

Tu jest stara wersja specyfikacji OpenAPI:
[wersja A]

Tu jest nowa wersja:
[wersja B]

1) Wypisz wszystkie breaking changes.
2) Dla każdego z nich zaproponuj 2–3 przypadki testów kontraktowych
   z perspektywy konsumenta usługi.
3) Zaznacz, które testy powinny być obowiązkową częścią regresji.

Na tej bazie dokładasz testy kontraktowe do projektu konsumenta, np. w formie Pact/ Spring Cloud Contract, a implementację samego kontraktu zostawiasz zespołowi. Zysk: mniej niespodzianek na integracji i lepsza rozmowa między zespołami „producent – konsument” API.

Współpraca AI z BDD i scenariuszami Gherkin

W zespołach, które korzystają z BDD, generatywne modele świetnie sprawdzają się jako „tłumacz” między językiem biznesu a zestawem scenariuszy Gherkin. Product owner rzuca ogólny opis: „klient może anulować zamówienie, o ile nie zostało wysłane”, a po chwili można mieć serię sensownych scenariuszy Given/When/Then.

Kluczowe jest, by nie generować ich w próżni, tylko na bazie już istniejących konwencji projektu:

  • szablonów kroków Given/When/Then,
  • aktualnej listy definicji kroków (step definitions),
  • przykładowych scenariuszy zaakceptowanych przez zespół.

Przykładowy prompt:

Tu są 3 istniejące scenariusze Gherkin dotyczące płatności:
[tu scenariusze]

Tu jest lista dostępnych kroków (Given/When/Then), które mamy zdefiniowane:
[tu lista]

Na podstawie opisu funkcji:
"Klient może anulować zamówienie przed wysyłką, 
ale nie może tego zrobić po zmianie statusu na SHIPPED."

Wygeneruj 5 scenariuszy Gherkin dotyczących anulowania zamówień,
używając WYŁĄCZNIE istniejących kroków.
Podziel je na: scenariusze poprawne i scenariusze błędne.

Tak powstaje zestaw scenariuszy, które da się od razu uruchomić, zamiast kolekcji pięknych, ale nierealnych opisów, wymagających tygodnia dopisywania brakujących kroków.

Rozsądne wykorzystanie AI w testach niefunkcjonalnych

Generative AI nie odpali za ciebie testów wydajnościowych na K6 czy Gatlingu, ale może odciążyć w planowaniu i analizie. Największy zysk pojawia się przy projektowaniu obciążeń i patrzeniu na wyniki z kilku perspektyw.

Przykład z praktyki: zespół miał jedną, mocno „syntetyczną” próbę wydajnościową na głównym endpointcie. Wyniki były zielone, a mimo to w godzinach szczytu system przycinał. Po wrzuceniu fragmentów logów i opisu ruchu produkcyjnego do modelu okazało się, że wzorzec obciążenia w testach nie ma nic wspólnego z rzeczywistością – brakowało pików, burstów, charakterystycznych sekwencji działań użytkowników.

Jak podejść do tematu:

  1. Zbierasz krótki opis ruchu produkcyjnego (np. z analityki, logów, monitoringu).
  2. Wrzucasz go do AI z prośbą o:
    • zdefiniowanie kilku wzorców obciążenia (pik poranny, spokojne godziny, końcówka promocji),
    • propozycję rozłożenia requestów w czasie dla każdego wzorca,
    • wskazanie newralgicznych sekwencji (np. rejestracja → logowanie → zakup → zwrot).
  3. Na tej podstawie prosisz o szkic skryptów obciążeniowych w konkretnym narzędziu, np. K6:
    Na podstawie tych wzorców obciążenia:
    [tu opis ruchu i wybrane wzorce]
    
    Wygeneruj szkic 2 skryptów K6:
    - jeden dla ruchu dziennego (średnie obciążenie),
    - drugi dla końcówki promocji (krótkie, intensywne piki).
    
    Uwzględnij endpointy:
    [lista endpointów z krótkim opisem],
    przykładowe dane wejściowe możesz uprościć.

Później zespół optymalizuje te skrypty i dopina szczegóły, ale startuje z sensowną bazą, a nie z domysłów.

Bezpieczeństwo i prywatność przy przekazywaniu danych do AI

Przy całej użyteczności modeli trzeba mieć z tyłu głowy, że testy dotykają danych wrażliwych. Logi z incydentu mogą zawierać dane osobowe, numery kart czy inne informacje, których nie chcesz wysyłać do zewnętrznego dostawcy.

Przed włączeniem AI w proces testowy dobrze jest ustalić proste, techniczne reguły:

  • Maskowanie danych – zanim wkleisz logi czy payloady do promptu, przepuść je przez skrypt, który:
    • podmienia maile, numery telefonów, identyfikatory klientów na losowe, ale spójne wartości,
    • usuwa dane kart płatniczych, hasła, tokeny.
  • Oddzielenie środowisk – do generowania przypadków i szkieletów testów wystarczy najczęściej specyfikacja i dane z środowisk testowych, nie produkcyjnych.
  • Modele on-premise / private – dla organizacji o wyższych wymaganiach (banki, medycyna) rozsądne jest korzystanie z modeli uruchomionych we własnej infrastrukturze lub u dostawcy z wyraźnie opisaną polityką danych.

W praktyce w wielu zespołach kończy się to na prostym „sanitizerze” logów i payloadów w repo narzędzi testowych oraz krótkiej liście zasad, co wolno wklejać do narzędzia AI, a czego nie. To zwykle wystarcza, żeby połączyć wygodę z odpowiedzialnością.

Zmiana roli QA i developera w świecie „testów z AI”

Po kilku miesiącach sensownego używania AI do testów zwykle pojawia się to samo pytanie: „to teraz tester ma pisać prompty, a nie testy?”. Odpowiedź jest mniej dramatyczna, niż się wydaje – zmienia się rozkład pracy, a nie sama odpowiedzialność za jakość.

W praktyce wygląda to tak:

  • QA coraz częściej:
    • projektuje strategie i scenariusze,
    • pilnuje stabilności asercji i sensu biznesowego testów,
    • uczy zespół, jak karmić AI wartościowym kontekstem.
  • Najczęściej zadawane pytania (FAQ)

    Jakie są realne korzyści z użycia AI przy testowaniu oprogramowania?

    Typowy obrazek: QA siedzi po godzinach, dopisując kolejne przypadki do regresji, a i tak ma poczucie, że coś może umknąć. AI nie zabierze tej odpowiedzialności, ale potrafi błyskawicznie „rozdmuchać” przestrzeń pomysłów: od wariantów danych wejściowych po nietypowe ścieżki użytkownika.

    Najbardziej odczuwalne korzyści to:

    • szybsze tworzenie szkiców przypadków testowych (szczególnie dla nowych funkcji i endpointów),
    • lepsze pokrycie scenariuszy krawędziowych i błędów, o których zespół by nie pomyślał,
    • uporządkowanie istniejących testów – grupowanie według ryzyka, obszaru czy priorytetu,
    • współtworzenie stabilniejszych asercji, które nie sypią się przy każdym kosmetycznym redesignie UI.
    • Mini-wniosek: AI nie robi „magii”, ale usuwa sporo ręcznej, powtarzalnej pracy związanej z wymyślaniem i organizowaniem testów.

    Czy AI może samodzielnie generować gotowe testy automatyczne do produkcji?

    Scenka z zespołu: ktoś wrzuca prompt „wygeneruj mi testy w Cypressie” i po godzinie mamy PR z pięknie wyglądającym kodem… który kompletnie nie pasuje do struktury projektu i łamie się przy pierwszej zmianie klasy CSS. To dość typowy efekt, gdy traktuje się AI jak kopiarkę kodu.

    AI potrafi wygenerować kod testów (Playwright, Cypress, JUnit, pytest itd.), ale:

    • nie zna Twoich helperów, konwencji, sposobu przygotowania danych testowych,
    • często tworzy niestabilne asercje (np. łapie po pełnym tekście komunikatów czy kruchych selektorach),
    • pomija setup/teardown, który w waszym projekcie jest kluczowy.
    • Rozsądne podejście: używać AI do szkiców testów, które przechodzą normalne code review. Model jest jak bardzo szybki junior – przydatny, ale nie puszcza się go samego na produkcję.

    Do jakich typów testów AI nadaje się najlepiej?

    Najczęstszy błąd to próba „wrzucenia” AI wszędzie na raz – od testów jednostkowych po złożone scenariusze E2E z dziesięcioma integracjami. Zamiast tego lepiej wybrać obszary, gdzie model faktycznie błyszczy.

    AI szczególnie dobrze sprawdza się przy:

    • testach jednostkowych – generowanie kombinacji wejść, wartości granicznych, nietypowych parametrów,
    • testach integracyjnych/kontraktowych – podpowiadanie różnych wariantów request/response, obsługi błędów, timeoutów,
    • testach opartych na danych – budowanie zestawów regresyjnych na bazie logów i historii błędów,
    • scenariuszach użytkownika – rozbijanie user story na konkretne ścieżki (happy path + mniej oczywiste warianty).
    • Mini-wniosek: największy zwrot daje używanie AI tam, gdzie głównym problemem jest „ile scenariuszy ogarnąć”, a nie skomplikowana logika domenowa.

    Jak wykorzystać AI do generowania przypadków testowych w praktyce?

    Wyobraź sobie, że tłumaczysz nowemu testerowi endpoint lub funkcję i prosisz: „wypisz mi wszystko, co warto tu przetestować”. Z AI robisz dokładnie to samo, tylko w formie dobrze zadanego promptu.

    Przykładowy schemat:

    • daj krótki opis funkcji lub fragment kodu (np. sygnatura metody, opis endpointu),
    • sprecyzuj kategorie: „happy path, błędne dane wejściowe, przypadki graniczne, błędy integracji”,
    • poproś o konkretny format: „nazwa_case’u, wejście, oczekiwane zachowanie (opis)”,
    • ogranicz liczbę: „wygeneruj 15–20 kandydatów na przypadki testowe”.
    • Potem przychodzi najważniejszy etap: selekcja przez QA/devów z kontekstem projektu. AI tworzy szeroki „backlog” pomysłów, a zespół wybiera i doprecyzowuje te, które mają sens biznesowy i techniczny.

    Jak pisać stabilne asercje z pomocą AI, żeby testy nie sypały się przy każdej zmianie UI?

    Znany obrazek: zmienia się tekst przycisku lub nazwa klasy CSS, a połowa testów E2E leci na czerwono. Problem rzadko leży w samej automatyzacji – zwykle chodzi o to, że asercje są zbyt mocno przyklejone do detali wyglądu.

    AI można poprosić o:

    • propozycje bardziej odpornych selektorów (data-testid, stabilne atrybuty domenowe zamiast klas z CSS),
    • asercje oparte na zachowaniu, nie dosłownym tekście (np. „użytkownik widzi informację o błędzie i nie może przejść dalej”, zamiast „tekst dokładnie równy ‘Wystąpił błąd’”),
    • alternatywne sposoby weryfikacji (sprawdzenie zmian w bazie, API, logach zamiast tylko UI).
    • Mini-wniosek: AI pomaga przeformułować to, co testujesz, z „czy tekst brzmi dokładnie tak” na „czy system zachowuje się zgodnie z oczekiwaniem”, co naturalnie prowadzi do stabilniejszych asercji.

    Jakie są ograniczenia AI w testach oprogramowania i gdzie trzeba szczególnie uważać?

    Sytuacja z życia: model generuje eleganckie scenariusze testowe dla systemu finansowego, tylko że… kompletnie ignoruje lokalne przepisy i definicję „aktywnego klienta” stosowaną w firmie. Na papierze wszystko wygląda sensownie, w praktyce – testy nie łapią kluczowych ryzyk.

    Główne ograniczenia AI w QA to:

    • płytkie rozumienie domeny biznesowej bez dostarczonego kontekstu,
    • słabe wyczucie złożonych zależności systemowych (mikroserwisy, kolejki, cache),
    • brak specjalistycznej wiedzy security – generowane „testy bezpieczeństwa” są raczej inspiracją niż realnym pokryciem.
    • Dlatego model najlepiej traktować jak nowego testera: szybki, kreatywny, ale wymagający jasnych wytycznych i regularnego feedbacku. Kontrola eksperta QA lub developera nie jest „opcją”, tylko warunkiem sensownego użycia AI.

    Jak zorganizować proces, żeby AI realnie odciążyło QA, a nie dołożyło chaosu?

    W wielu zespołach pierwsze próby z AI kończą się tym, że QA ma dodatkowe zadanie: „posprzątaj po tym, co wygenerował model”. To znak, że brakuje procesu, a rola AI jest niejasna.

    Praktyczny schemat:

    • zdefiniuj rolę AI – np. „generator kandydatów na przypadki testowe” zamiast „autor gotowych testów”,
    • ustal format wejścia (jak opisujemy funkcję, endpoint, user story) i wyjścia (format przypadków/asercji),
    • zapewnij code review/test review – nic z AI nie wchodzi do repo bez oka człowieka,
    • Bibliografia i źródła

    • ISO/IEC/IEEE 29119 Software Testing – Parts 1–4. International Organization for Standardization (2013) – Standardy terminologii, procesów i dokumentacji testów oprogramowania
    • ISTQB Glossary of Testing Terms. International Software Testing Qualifications Board (2024) – Definicje pojęć QA: przypadek testowy, regresja, asercja, typy testów
    • Agile Testing: A Practical Guide for Testers and Agile Teams. Addison-Wesley (2009) – Rola testerów w zwinnych zespołach, regresja, priorytetyzacja testów
    • Exploratory Software Testing. Addison-Wesley Professional (2009) – Techniki eksploracyjne, generowanie scenariuszy i wariantów testowych
    • Testing Web APIs. Manning Publications (2022) – Projektowanie przypadków testowych dla API, błędy walidacji i integracji