Generowanie i uruchamianie testów z Codexem
Generowanie testów z Codexem bezpiecznie domyka luki w pokryciu, gdy każdy moduł dostaje własny tor w osobnym worktree Git, tor może dodawać testy, ale nigdy nie zmienia kodu źródłowego, a wynik ocenia się po dowodach, nie po lekturze: bramka „tylko testy”, przyrost pokrycia na plik, wynik testów mutacyjnych i przebieg codex review przed merge’em.
Raport pokrycia pokazuje 34%, lista kontrolna wydania wymaga 80%, a 200 niepokrytych funkcji leży w 40 plikach. Możesz poprosić Codexa, żeby „dopisał testy, aż pokrycie dojdzie do 80%”, i zrobi to: testami, które sprawdzają, czy wywołano mocki, i przechodzą niezależnie od tego, co robi kod. Ta strona jest dla programistów, którzy oddają pisanie testów Codexowi, i dla tech leadów, którzy decydują, co pull request z wygenerowanymi testami musi udowodnić przed merge’em. Polecenia sprawdzono na Codex CLI 0.157.1 w dniu 2026-09-26.
Co zyskasz na generowaniu testów z Codexem
Dział zatytułowany „Co zyskasz na generowaniu testów z Codexem”- Układ torów, w którym kilka zadań testowych Codexa działa równolegle w osobnych worktree, nie dotykając siebie nawzajem ani twojego katalogu roboczego.
- Trzy prompty do skopiowania: analiza luk, testy zgodne z konwencjami projektu i krytyczny audyt wygenerowanych testów.
- Skrypt bramki, który odrzuca każdy tor zmieniający kod źródłowy, oraz kontrolę przyrostu pokrycia na plik.
- Testy mutacyjne ze StrykerJS, które pokazują, czy nowe testy łapią błędy, a nie tylko wykonują linie.
- Cotygodniowy raport o kondycji testów do uruchamiania z harmonogramu i tabelę awarii ze sposobem wyjścia z każdej.
Jeśli worktree w Codexie są dla ciebie nowe, zacznij od strony izolowane zadania Codexa w worktree Git. Debugowanie padającego testu to inne zadanie, opisane w debugowaniu i polowaniu na błędy z Codexem.
Kto co sprawdza, gdy testy pisze Codex?
Dział zatytułowany „Kto co sprawdza, gdy testy pisze Codex?”Procent pokrycia to liczba, o którą wszyscy pytają, i najsłabszy dowód, jaki masz. Test, który wywołuje funkcję i niczego nie sprawdza, podnosi pokrycie linii tak samo jak dobry test. Podziel pracę tak, żeby każdy artefakt miał kontrolę, która nie jest opinią samego Codexa.
| Artefakt | Kto go tworzy | Jak jest weryfikowany | Kto zatwierdza |
|---|---|---|---|
| Lista plików do przetestowania według priorytetu | Codex, tylko do odczytu | Czytasz 10 linii, nie kod | Programista |
| Planowane nazwy testów w torze | Codex | Czytasz listę, zanim powstanie jakikolwiek test | Programista |
| Wygenerowane pliki testów | Codex, w torze w worktree | Bramka „tylko testy”; pięć zielonych przebiegów z rzędu | Skrypt bramki |
| Przyrost pokrycia | Uruchomienie testów | Różnica na plik względem bazowego pomiaru toru | Skrypt bramki |
| Skuteczność w łapaniu błędów | StrykerJS | Wynik mutacyjny i lista mutantów, które przeżyły | Recenzent czyta ocalałe mutanty |
| Jakość testów | Drugi przebieg Codexa | codex review i prompt audytowy | Recenzent czyta ustalenia |
| Merge | CI | Pełny zestaw testów, typy i lint na czystej maszynie | Właściciel kodu, na podstawie dowodów |
Dlaczego zielony zestaw testów sam w sobie niczego nie dowodzi i jak silny musi być, zanim przestaniesz go czytać, wyjaśnia strona jak silna jest twoja wyrocznia?
Przygotuj repozytorium, zanim Codex napisze pierwszy test
Dział zatytułowany „Przygotuj repozytorium, zanim Codex napisze pierwszy test”-
Wpisz polecenia testowe do
AGENTS.md. Codex czytaAGENTS.mdprzed rozpoczęciem pracy, więc uruchamia twoje polecenia zamiast zgadywać. Od Codex CLI 0.150.0 niezaufany projekt nie dostarcza swojego projektowegoAGENTS.md, dlatego najpierw oznacz repozytorium jako zaufane: uruchomcodexw katalogu głównym repozytorium i zaakceptuj pytanie Trust this folder?.## Tests- One file: `npx vitest run tests/unit/services/orders/createOrder.test.ts`- Full suite: `npx vitest run`- Coverage: `npx vitest run --coverage --coverage.reporter=json-summary --coverage.reporter=text`- Tests live in tests/unit/ and tests/integration/, mirroring src/.- Never edit a test to make it pass, and never change src/ in a test-writing task.Więcej o tym pliku w artykule jak pisać AGENTS.md dla Codexa.
-
Zapisz raport pokrycia dla commita bazowego. Uruchom samodzielnie polecenie pokrycia z listy powyżej. Reporter
json-summaryzapisujecoverage/coverage-summary.json, z którego korzysta prompt analizy luk i z którym później porównuje się bramka. Flaga pokrycia wymaga zainstalowanego pakietu@vitest/coverage-v8; jeśli repozytorium go nie ma, najpierw wykonaj krok 4. -
Opcjonalnie zainstaluj skill „najpierw test”. Skill
tddzmattpocock/skillssprawia, że Codex planuje zachowania, zanim napisze testy. Zainstaluj go na poziomie projektu poleceniemnpx skills add mattpocock/skills --skill tdd codebase-design -a codex -y. Skillcodebase-designjest w poleceniu, botddsięga po niego po słownictwo, a samtddzostawiłby to odwołanie bez celu. Opcje i pułapki opisuje strona skille do testowania i debugowania. -
Przygotuj testy mutacyjne na gałęzi bazowej. Późniejsza kontrola mutacyjna potrzebuje StrykerJS w każdym torze, a flaga pokrycia wymaga zainstalowanego pakietu
@vitest/coverage-v8, więc oba trafiają do tego samego commita bazowego. Zainstaluj go, skonfiguruj i wyklucz jego wyniki z repozytorium w jednym commicie, a ten commit wprowadź do gałęzi domyślnej (przez pull request, jeśli gałąź jest chroniona), zanim utworzysz pierwszy tor:Okno terminala npm install -D @vitest/coverage-v8 @stryker-mutator/core @stryker-mutator/vitest-runnerecho '{ "testRunner": "vitest" }' > stryker.config.jsonprintf 'reports/\n.stryker-tmp/\n' >> .gitignoregit add package.json package-lock.json stryker.config.json .gitignoregit commit -m "Add StrykerJS and the Vitest coverage provider"Stryker zapisuje raport HTML w
reports/mutation/, a kopie robocze w.stryker-tmp/, więc oba katalogi muszą być ignorowane, inaczej bramka „tylko testy” zgłosi je jako zbędne pliki. Tory odgałęziają się odorigin/main, więc każdy dziedziczy tę konfigurację, a żaden tor nie dotykapackage.json.
Znajdź luki w pokryciu, które warto zamknąć najpierw
Dział zatytułowany „Znajdź luki w pokryciu, które warto zamknąć najpierw”Niskie pokrycie w module ładującym konfigurację znaczy mniej niż niskie pokrycie gałęzi w kodzie, który obsługuje pieniądze. Poproś Codexa o ranking luk i zostaw go w trybie tylko do odczytu: analiza nie potrzebuje prawa zapisu.
Uruchom go interaktywnie albo bez nadzoru, z sandboxem tylko do odczytu i bez zapisywania sesji:
codex exec --sandbox read-only --ephemeral -o coverage-gaps.md - < rank-gaps.txtPlik rank-gaps.txt zawiera powyższy prompt. Czytasz coverage-gaps.md, poprawiasz podział na tory i na tym etapie zatwierdzasz tylko tę dziesięciowierszową tabelę.
Generuj testy w równoległych torach w worktree
Dział zatytułowany „Generuj testy w równoległych torach w worktree”Każdy tor dostaje własny worktree i własną gałąź, więc dwóch agentów nigdy nie edytuje tego samego katalogu, a nieudany tor usuwasz bez sprzątania w swoim. git worktree add daje nazwane gałęzie, z których później powstają pull requesty; codex --worktree to interaktywna alternatywa, gdy prowadzisz jeden tor ręcznie. Ile torów uruchamiać naraz i w jakiej kolejności je scalać, opisuje strona przepływy wieloagentowe w Codexie.
-
Utwórz po jednym worktree na tor i sam zainstaluj zależności. Nowy worktree nie ma
node_modulesani plików ignorowanych przez Git. Instaluj z własnego terminala, bo sandbox przestrzeni roboczej odcina Codexowi dostęp do sieci. Potem zapisz bazowy pomiar pokrycia dla samego toru: kluczami w podsumowaniu są ścieżki bezwzględne, więc pomiar z głównego katalogu roboczego nie pasuje do plików toru.Okno terminala git fetch originfor lane in orders payments auth; dogit worktree add -b "tests/$lane" "../app-tests-$lane" origin/main(cd "../app-tests-$lane" && npm ci \&& npx vitest run --coverage --coverage.reporter=json-summary >/dev/null \&& cp coverage/coverage-summary.json "/tmp/coverage-before-$lane.json")doneZastąp
origin/mainswoją domyślną gałęzią, a nazwy torów tymi z analizy luk. -
Zatwierdź planowane nazwy testów w każdym torze. Uruchom
codexw worktree toru, wklej poniższy prompt generujący i zatrzymaj się na liście nazw testów. Przeczytanie 15 nazw zajmuje minutę; przeczytanie 400 linii kodu testów po prostu się nie wydarzy. Dopisz każde brakujące zachowanie, na którym ci zależy. -
Uruchom tory. Kontynuuj każdą zatwierdzoną sesję interaktywnie albo zapisz prompt każdego toru z dopisanymi zatwierdzonymi nazwami i uruchom tory równolegle, bez nadzoru:
Okno terminala for lane in orders payments auth; docodex exec -C "../app-tests-$lane" -c default_permissions=":workspace" \--ephemeral -o "/tmp/lane-$lane.md" - < "prompts/tests-$lane.txt" &donewaitdefault_permissions=":workspace"wybiera wbudowany profil uprawnień przestrzeni roboczej, który w 0.157.1 jest w wersji beta; w wersji Codexa bez profili użyj zamiast tego--sandbox workspace-write. Nie łącz obu: OpenAI pisze, że profili uprawnień i starszego systemu sandboxa nie da się łączyć. Wszystkie flagi i opcje wyjściacodex execopisuje strona Codex w trybie nieinteraktywnym.
Reguła BUG?: jest kluczowa. Gdy test pada, bo kod jest błędny, najprostsza droga do zielonego wyniku to dopasować asercję do błędu. Zakaz zmian w kodzie źródłowym i prośba o oznaczony, pominięty test zamieniają ukryty błąd w linię raportu, którą sam oceniasz.
Udowodnij, że wygenerowane testy łapią błędy, bez czytania ich
Dział zatytułowany „Udowodnij, że wygenerowane testy łapią błędy, bez czytania ich”Uruchom te kontrole w każdym torze, zanim otworzysz choć jeden plik testów, i zatrzymaj się na pierwszej porażce. Dwie pierwsze są mechaniczne, dwie ostatnie mierzą siłę testów.
1. Bramka „tylko testy”. Tor piszący testy, który zmienił kod źródłowy, jest odrzucany niezależnie od wyników:
#!/usr/bin/env bash# tests-only-gate.sh LANE — run from inside the lane's worktreeset -euo pipefaillane="$1"stray=$(git status --porcelain --untracked-files=all | cut -c4- | grep -v -E '^tests/' || true)[ -z "$stray" ] || { echo "FAIL: lane changed files outside tests/:"; echo "$stray"; exit 1; }
# The new tests must pass five times in a row: a flaky generated test is worse than nonefor i in 1 2 3 4 5; do npx vitest run tests/ >/dev/null || { echo "FAIL on run $i"; exit 1; }; done
# Per-file branch-coverage change against this lane's own baselinenpx vitest run --coverage --coverage.reporter=json-summary >/dev/nullnode -e 'const a = require(process.argv[1]), b = require("./coverage/coverage-summary.json");for (const f of Object.keys(b)) { if (f === "total") continue; const d = b[f].branches.pct - (a[f]?.branches.pct ?? 0); if (d !== 0) console.log(d.toFixed(1).padStart(6), f);}' "/tmp/coverage-before-$lane.json"grep -rn "BUG?:" tests/ || trueBramka zakłada, że katalog coverage/ jest ignorowany przez Git. Jeśli pliku docelowego nie ma w wyniku pokrycia, testy do niego nie dotarły, niezależnie od ich liczby. Odeślij tor z powrotem, podając niepokrytą gałąź z numerem linii.
2. Testy mutacyjne. Pokrycie linii pokazuje, które linie się wykonały; testy mutacyjne pokazują, czy błędna linia zostałaby zauważona. StrykerJS wprowadza do kodu drobne zmiany (odwrócony warunek, usunięta gałąź, > zamiast >=) i ponownie uruchamia testy; mutant, który przeżył, wskazuje zachowanie, którego żaden test nie pilnuje. W próbnym przebiegu z jednym testem tylko dla scenariusza pozytywnego Stryker 10.0.0 zgłosił pełne pokrycie linii, a mimo to znalazł mutanty, które przeżyły. Właśnie tę lukę zamyka ta kontrola.
npx stryker run --mutate "src/services/orders/**/*.ts"Stryker jest już w torze zainstalowany i skonfigurowany, bo tor odgałęził się od commita bazowego przygotowanego w kroku 4 konfiguracji. Ogranicz --mutate do plików docelowych toru: przebieg na całym repozytorium trwa znacznie dłużej i nic nie mówi o tym torze. Poziom, do którego warto dążyć, i sposób czytania ocalałych mutantów opisuje strona jak silna jest twoja wyrocznia?
3. Przebieg recenzji. Uruchom w torze codex review --uncommitted, żeby dostać wbudowaną recenzję Codexa, albo wpisz /review w sesji interaktywnej i pokieruj nią promptem audytowym poniżej. W 0.157.1 codex review nie przyjmuje własnych instrukcji razem z --uncommitted ani --base (sprawdzone 2026-09-26), więc stałe reguły w rodzaju „oznacz testy bez sensownej asercji” trafiają do AGENTS.md. Tę samą konfigurację recenzenta w skali pull requestów opisuje strona code review z Codexem.
4. Dowody do pull requesta. Gdy bramka przejdzie, sam zacommituj tor, wypchnij gałąź i otwórz pull request z przyrostem pokrycia, wynikiem mutacyjnym i listą ocalałych mutantów, listą BUG?: i tabelą z audytu. Recenzenci czytają te dowody i otwierają tylko testy, które one wskazują. Co pull request powinien dołączyć, definiuje pakiet dowodów. Żeby późniejsze zadanie nie osłabiło tych testów, dodaj tests/ do CODEOWNERS i kontrolę CI opisaną w artykule ochrona wyroczni.
Nie pozwól, żeby pokrycie i kondycja testów znów spadły
Dział zatytułowany „Nie pozwól, żeby pokrycie i kondycja testów znów spadły”Zestaw testów silny we wrześniu słabnie, gdy nowy kod trafia do repozytorium bez testów. Dwie kontrole trzymają poziom.
Po pierwsze, niech CI pilnuje progu. Ustawienie coverage.thresholds w konfiguracji Vitest sprawia, że przebieg kończy się błędem, gdy pokrycie spadnie poniżej ustalonych wartości; podnoś je po każdym scalonym torze i nigdy nie obniżaj, żeby przepchnąć pull request. Jak podpiąć to zadanie do GitHub Actions, opisuje strona CI/CD z Codexem.
Po drugie, zaplanuj cotygodniowy raport o kondycji testów. Automatyzacje Codexa w aplikacji desktopowej uruchamiają prompt według harmonogramu; zadanie cron w CI z codex exec robi to samo z poziomu pipeline’u. Kompromisy, wybór sandboxa i typowe awarie opisuje strona zaplanowane automatyzacje Codexa.
Raz zacommituj podsumowanie z kroku 2 jako coverage-baseline.json, żeby pierwszy zaplanowany przebieg miał z czym porównywać.
Plik coverage-baseline.json aktualizuj ręcznie, w recenzowanym commicie, po scaleniu toru. Zadanie, które samo nadpisuje swój punkt odniesienia, może ukryć regresję w tym samym przebiegu, w którym ją wywołało.
Co się psuje przy generowaniu testów z Codexem
Dział zatytułowany „Co się psuje przy generowaniu testów z Codexem”| Objaw | Przyczyna | Jak wyjść |
|---|---|---|
| Pokrycie wzrosło, wynik mutacyjny został niski | Testy wykonują kod, ale sprawdzają tylko wywołanie mocka albo to, że wartość jest niepusta lub zdefiniowana | Uruchom prompt audytowy; odeślij tor z ocalałymi mutantami jako wymaganymi asercjami |
Bramka zgłasza pliki spoza tests/ | Codex „naprawił” kod, żeby test przeszedł | Odrzuć te zmiany przez git checkout -- src/; uruchom tor ponownie z regułą BUG?:; sam oceń oznaczone zachowanie |
| Plik docelowy nie pokazuje zmiany pokrycia | Testy importują mocka albo moduł spod innej ścieżki | Wskaż niepokrytą gałąź z numerem linii i poproś Codexa o pomiar pokrycia tylko dla tego pliku |
| Testy przechodzą w torze, padają po scaleniu | Tor wyszedł ze starszej bazy albo dwa tory zmieniły wspólną fiksturę | Zrób rebase toru na aktualną bazę i ponownie uruchom bramkę; trzymaj fikstury w jednym torze albo w osobnej, wcześniejszej zmianie |
| Mocki rozjeżdżają się z rzeczywistością | Mocki napisano z perspektywy testu, nie zależności | Poproś o mocki zbudowane z typów prawdziwego modułu; dodaj jeden test integracyjny na każdy styk, jak we wzorcach testów integracyjnych |
| Tory padają na pierwszym poleceniu z brakującymi modułami | Worktree nie ma node_modules, a sandbox blokuje instalację | Uruchom npm ci w torze z własnego terminala, potem wznów tor |
| Testy zaczęły działać wolno | Każdy wygenerowany test integracyjny stawia własną bazę danych | Wymagaj wspólnego przygotowania w beforeAll i transakcji na test; zobacz zarządzanie danymi testowymi |
| Codex ignoruje twoje polecenia testowe | Projekt jest niezaufany, więc AGENTS.md nie został wczytany (0.150.0 i nowsze) | Uruchom codex w katalogu głównym repozytorium i zaakceptuj Trust this folder?, potem zapytaj Codexa, jakie instrukcje wczytał; szczegóły w artykule jak pisać AGENTS.md dla Codexa |
Dokąd dalej po wygenerowaniu testów z Codexem
Dział zatytułowany „Dokąd dalej po wygenerowaniu testów z Codexem”Używasz też innego agenta? To samo zadanie opisują strony generowanie testów i TDD z Claude Code oraz wzorce testowania w Cursorze.