Przejdź do głównej zawartości

Strategie i generowanie testów jednostkowych

Prosisz AI o “napisz testy jednostkowe dla UserService” i generuje 40 testów. Wszystkie przechodzą. Pokrycie wynosi 95%. Czujesz się dobrze, aż klient zgłasza, że użytkownicy z plusami w adresach email nie mogą się zarejestrować. Żaden z tych 40 testów nie pokrywał tego przypadku, ponieważ AI testowało happy path na 40 nieco różnych sposobów. Ilość to nie pokrycie. Właściwe testy na właściwych granicach łapią błędy — a to wymaga specyficznego, świadomego promptowania.

  • Wzorce promptów generujące testy skupione na zachowaniu i przypadkach brzegowych, nie tylko pokryciu linii
  • Strategie mockowania utrzymujące testy szybkie i niezawodne bez nadmiernego mockowania
  • Techniki testowania obsługi błędów, współbieżności i warunków brzegowych
  • Przepływy pracy dla utrzymywania testów w miarę ewolucji kodu
  • Integracja testowania mutacyjnego dla weryfikacji, że testy faktycznie łapią błędy

Najbardziej efektywne testy generowane przez AI opisują co kod powinien robić, nie jak robi to wewnętrznie.

Otwórz plik do testowania i użyj trybu Agent:

@src/services/order.service.ts
Wygeneruj testy jednostkowe dla OrderService.calculateTotal. Skup się na ZACHOWANIU:
1. "should apply percentage discount correctly" (10% zniżki z $100 = $90)
2. "should apply fixed discount correctly" ($15 zniżki z $100 = $85)
3. "should not allow total below zero" (zniżka > suma częściowa)
4. "should calculate tax after discount" (podatek od kwoty po zniżce, nie oryginalnej)
5. "should handle empty cart" (zero pozycji, bez zniżki)
6. "should round to 2 decimal places" (unikaj dziwactw floating point)
7. "should reject negative quantities" (rzuć ValidationError)
8. "should handle mixed currency items" (rzuć CurrencyMismatchError)
Testuj tylko przez publiczne API. Nie mockuj metod wewnętrznych.
Mockuj tylko bazę danych i zależności zewnętrznych serwisów.
Podążaj za wzorcami w @src/services/__tests__/payment.service.test.ts

Przestań hardcodować dane testowe. Używaj fabryk generujących realistyczne dane z nadpisywalnymi domyślnymi wartościami.

Obsługa błędów to miejsce, gdzie większość testów generowanych przez AI jest najsłabsza. Promptuj specyficznie dla scenariuszy błędów.

Narzędzia AI mogą generować testy współbieżności, które większość deweloperów pomija.

Testowanie mutacyjne: Udowadnianie, że Twoje testy działają

Dział zatytułowany „Testowanie mutacyjne: Udowadnianie, że Twoje testy działają”

Metryki pokrycia kłamią. Test wykonujący linię niekoniecznie weryfikuje jej zachowanie. Testowanie mutacyjne wprowadza małe zmiany (mutacje) do twojego kodu i sprawdza, czy testy je łapią.

  1. Zainstaluj Stryker Mutator

    Okno terminala
    npm install --save-dev @stryker-mutator/core @stryker-mutator/jest-runner @stryker-mutator/typescript-checker
  2. Skonfiguruj dla swojego projektu

    Okno terminala
    npx stryker init
    # Wybierz runner Jest, checker TypeScript
    # Ustaw mutate na: src/services/**/*.ts (zacznij od małego)
  3. Uruchom i przeanalizuj wyniki

    Okno terminala
    npx stryker run
    # Przejrzyj raport HTML - skup się na przeżywających mutacjach
  4. Użyj AI do zabicia przeżywających mutantów

    Podaj przeżywające mutacje z powrotem do AI dla ukierunkowanego generowania testów.

Kiedy twoja implementacja się zmienia, AI może inteligentnie zaktualizować testy.

“AI generuje testy, które wszystkie wyglądają tak samo.” Podałeś ogólny prompt. Bądź specyficzny co do scenariuszy, które chcesz przetestować. Wypisz przypadki brzegowe, warunki błędów i wartości graniczne wprost.

“Testy przechodzą lokalnie ale zawodzą w CI.” Sprawdź problemy z izolacją testów. Testy generowane przez AI czasami dzielą zmienialny stan między testami. Upewnij się, że beforeEach resetuje wszystkie mocki i stan testowy. Dodaj --runInBand do CI jeśli testy mają ukryte problemy z równoległością.

“Wynik mutacji jest niski pomimo wysokiego pokrycia.” Twoje testy wykonują kod bez weryfikowania jego outputu. Skup się na dodawaniu asercji dla wartości zwracanych, efektów ubocznych i warunków błędów. Pokrycie bez asercji jest bez sensu.

“Suite testowy jest wolny po tym jak AI wygenerowało setki testów.” Przejrzyj pod kątem redundancji. Zapytaj AI: “Przeanalizuj te testy i zidentyfikuj zestawy pokrywające te same ścieżki kodu. Które testy można usunąć bez zmniejszenia pokrycia mutacyjnego?”