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.
Czego się nauczysz
Dział zatytułowany „Czego się nauczysz”- 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
Pętla sprzężenia zwrotnego TDD-AI
Dział zatytułowany „Pętla sprzężenia zwrotnego TDD-AI”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.
- Piszesz test, który nie przechodzi, uchwycając oczekiwane zachowanie
- AI pisze kod, który sprawia, że test przechodzi
- AI refaktoryzuje implementację, utrzymując testy na zielono
- 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.
Pisanie testów jako pierwszych
Dział zatytułowany „Pisanie testów jako pierwszych”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 makeall tests pass. Run the tests after implementation and fix anyfailures.Cursor uruchomi testy w zintegrowanym terminalu, zobaczy niepowodzenia i będzie iterował, aż wszystkie przejdą.
Użyj Plan Mode do wygenerowania specyfikacji testów, a następnie przełącz na Normal Mode do implementacji:
I need a rate limiter middleware. Requirements:- 100 requests/minute per API key- 429 response with Retry-After header when exceeded- Redis-backed tracking- Thread-safe under concurrent requests
Write comprehensive tests at src/middleware/__tests__/rateLimiter.test.ts.Follow existing test patterns in the codebase. Do not implement yet.Po przejrzeniu i zatwierdzeniu testów:
Implement src/middleware/rateLimiter.ts to pass all the tests.Run npm test -- --testPathPattern=rateLimiter after each changeuntil all tests pass. Address root causes, not symptoms.Agentyczna pętla Claude Code uruchomi testy, przeczyta wyjście, naprawi problemy i automatycznie ponownie uruchomi. To właśnie w tej pętli TDD z AI naprawdę się sprawdza.
Poproś Codex o wygenerowanie pliku testów jako pierwszego. Codex weryfikuje własną pracę, uruchamiając testy w swoim sandboxie:
Write tests for a rate limiter middleware atsrc/middleware/__tests__/rateLimiter.test.ts.
Requirements:- 100 requests/minute per API key- 429 + Retry-After header when exceeded- Redis-backed- Handles concurrent requests safely
Follow existing test patterns in the codebase. Do not implement yet.Po przejrzeniu rozpocznij nowy wątek do implementacji:
Implement src/middleware/rateLimiter.ts to pass all tests insrc/middleware/__tests__/rateLimiter.test.ts.Run the test suite and iterate until all tests pass.Używanie oddzielnych wątków utrzymuje czysty kontekst. Wątek implementacji skupia się wyłącznie na osiągnięciu zielonego stanu testów, bez rozmowy o generowaniu testów zaśmiecającej kontekst.
Kierowanie fazą implementacji
Dział zatytułowany „Kierowanie fazą implementacji”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.
Daj Claude jasną dyrektywę implementacji z weryfikacją:
Implement rateLimiter.ts to pass all tests. After implementation:1. Run npm test -- --testPathPattern=rateLimiter2. If any test fails, read the full error output3. Fix the root cause (don't modify the tests)4. Re-run until all tests pass5. Then run the full test suite to check for regressionsJeśli Claude utknie w pętli nieudanych testów, użyj /clear i rozpocznij nową sesję z bardziej precyzyjnym promptem opisującym konkretne niepowodzenie.
Sandbox Codex automatycznie uruchamia weryfikacje:
Implement src/middleware/rateLimiter.ts to pass all existing tests.Follow the middleware pattern from src/middleware/auth.ts.Run the test suite after implementation. Do not modify test files.If tests fail, fix the implementation, not the tests.W aplikacji Codex możesz obserwować implementację w czasie rzeczywistym i widzieć wyniki testów, gdy Codex iteruje.
Wychwytywanie antywzorca “osłabiania testów”
Dział zatytułowany „Wychwytywanie antywzorca “osłabiania testów””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ć.
Kiedy to nie działa
Dział zatytułowany „Kiedy to nie działa”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.