Przejdź do głównej zawartości

Programowanie sterowane testami z pomocą AI

Prosisz AI o zbudowanie rate limitera. Generuje coś, co wygląda poprawnie. Wdrażasz to. Dwa dni później twoje API pada, bo rate limiter nie obsługuje poprawnie współbieżnych żądań — wyścig warunków, którego AI nigdy nie pomyślało testować, bo nigdy mu nie powiedziałeś, co oznacza “działający”.

TDD odwraca tę dynamikę. Gdy piszesz testy pierwsze, AI ma precyzyjną, maszynowo weryfikowalną definicję sukcesu. Nie musi zgadywać, czego chcesz. Uruchamia testy, widzi niepowodzenia i iteruje, aż przejdą. To pojedyncza technika o najwyższej dźwigni do uzyskiwania niezawodnych wyników od asystentów AI do kodowania.

  • Przepływ pracy do pisania specyfikacji testów jako pierwszych i pozwalania AI implementować na ich podstawie
  • Prompty do generowania kompleksowych przypadków testowych z wymagań
  • Strategie radzenia sobie z tendencją AI do osłabienia asercji, żeby testy przechodziły
  • Jasne zrozumienie, kiedy TDD z AI oszczędza czas, a kiedy dodaje narzut

Tradycyjne TDD podąża za cyklem czerwone-zielone-refaktoryzacja. Z AI ten cykl staje się dramatycznie szybszy, ponieważ AI obsługuje fazy zieloną i refaktoryzacji, a ty skupiasz się na pisaniu sensownych czerwonych testów.

  1. Piszesz test, który nie przechodzi, uchwycając oczekiwane zachowanie
  2. AI pisze kod, który sprawia, że test przechodzi
  3. AI refaktoryzuje implementację, utrzymując testy na zielono
  4. Przeglądasz implementację i piszesz następny test

Kluczowe spostrzeżenie: test jest twoją specyfikacją. Dobrze napisany test komunikuje zamiar znacznie precyzyjniej niż jakikolwiek prompt w języku naturalnym.

Zacznij od zdefiniowania zachowania, które chcesz, a nie implementacji. Możesz napisać test samodzielnie lub współpracować z AI przy generowaniu przypadków testowych z wymagań — ale musisz przejrzeć i zatwierdzić testy, zanim poprosisz o implementację.

Otwórz tryb Agent. Poproś Cursor o pomoc w wygenerowaniu przypadków testowych, a następnie przejrzyj je przed poproszeniem o implementację:

I need to build a rate limiter middleware for our Express API.
Requirements:
- 100 requests per minute per API key
- Returns 429 with a Retry-After header when exceeded
- Tracks limits in Redis
- Handles concurrent requests correctly
Write the test file first at src/middleware/__tests__/rateLimiter.test.ts.
Use our existing test patterns from @src/middleware/__tests__/auth.test.ts.
Do NOT write the implementation yet.

Przejrzyj testy. Dodaj przypadki brzegowe, które AI pominęło. Następnie:

Good tests. Now implement src/middleware/rateLimiter.ts to make
all tests pass. Run the tests after implementation and fix any
failures.

Cursor uruchomi testy w zintegrowanym terminalu, zobaczy niepowodzenia i będzie iterował, aż wszystkie przejdą.

Gdy testy są na miejscu, faza implementacji to miejsce, gdzie AI dostarcza największą wartość. Testy działają jako ciągły sygnał sprzężenia zwrotnego, który utrzymuje AI na właściwym torze.

Odwołaj się zarówno do pliku testów, jak i do odpowiedniego istniejącego kodu:

Implement the rate limiter to pass @src/middleware/__tests__/rateLimiter.test.ts.
Reference @src/middleware/auth.ts for our middleware patterns.
Run the tests after each significant change.
If a test fails, read the error carefully and fix the root cause.

Użyj checkpointów Cursor do zrobienia migawki znanych dobrych stanów. Jeśli AI zepsuje coś, co przechodziło, cofnij do checkpointu zamiast debugować do przodu.

Najbardziej niebezpieczny tryb awarii w TDD wspomaganym AI to sytuacja, gdy AI modyfikuje twoje testy, żeby przechodziły, zamiast naprawiać implementację. Zwracaj uwagę na te znaki:

  • Asercje stają się mniej konkretne. expect(result).toBe(429) staje się expect(result).toBeDefined().
  • Testy są usuwane. AI usuwa “niestabilne” testy zamiast naprawiać kod.
  • Mocki zastępują prawdziwe zachowanie. AI mockuje dokładnie to, co chciałeś przetestować.

AI generuje trywialne testy. Jeśli twoje prompty testowe są ogólnikowe (“write tests for this function”), AI napisze testy weryfikujące, że funkcja istnieje i coś zwraca. Bądź konkretny w kwestii zachowań, które chcesz przetestować. Dołącz konkretne przykłady wejść i wyjść.

Testy są zbyt ściśle powiązane z implementacją. Jeśli twoje testy sprawdzają wewnętrzne szczegóły implementacji (wywołania prywatnych metod, konkretne struktury danych), AI nie może swobodnie refaktoryzować. Pisz testy pod publiczne API i oczekiwane zachowania, nie wewnętrzną mechanikę.

Zestaw testów jest zbyt wolny. TDD wspomagane AI działa najlepiej, gdy testy uruchamiają się w sekundach. Jeśli pełny zestaw testów trwa 10 minut, AI nie będzie efektywnie iterował. Użyj --testPathPattern lub --grep, aby uruchamiać tylko odpowiednie testy podczas rozwoju.

Piszesz zbyt wiele testów z góry. Zacznij od 3-5 testów pokrywających podstawowe zachowanie. Pozwól implementacji ujawnić, które przypadki brzegowe są ważne, a następnie dodawaj więcej testów iteracyjnie. Próbowanie napisania 30 testów przed jakąkolwiek implementacją prowadzi do paraliżu analitycznego.