Przejdź do głównej zawartości

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.

  • 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.

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.

ArtefaktKto go tworzyJak jest weryfikowanyKto zatwierdza
Lista plików do przetestowania według priorytetuCodex, tylko do odczytuCzytasz 10 linii, nie kodProgramista
Planowane nazwy testów w torzeCodexCzytasz listę, zanim powstanie jakikolwiek testProgramista
Wygenerowane pliki testówCodex, w torze w worktreeBramka „tylko testy”; pięć zielonych przebiegów z rzęduSkrypt bramki
Przyrost pokryciaUruchomienie testówRóżnica na plik względem bazowego pomiaru toruSkrypt bramki
Skuteczność w łapaniu błędówStrykerJSWynik mutacyjny i lista mutantów, które przeżyłyRecenzent czyta ocalałe mutanty
Jakość testówDrugi przebieg Codexacodex review i prompt audytowyRecenzent czyta ustalenia
MergeCIPełny zestaw testów, typy i lint na czystej maszynieWł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”
  1. Wpisz polecenia testowe do AGENTS.md. Codex czyta AGENTS.md przed rozpoczęciem pracy, więc uruchamia twoje polecenia zamiast zgadywać. Od Codex CLI 0.150.0 niezaufany projekt nie dostarcza swojego projektowego AGENTS.md, dlatego najpierw oznacz repozytorium jako zaufane: uruchom codex w 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.

  2. Zapisz raport pokrycia dla commita bazowego. Uruchom samodzielnie polecenie pokrycia z listy powyżej. Reporter json-summary zapisuje coverage/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.

  3. Opcjonalnie zainstaluj skill „najpierw test”. Skill tdd z mattpocock/skills sprawia, że Codex planuje zachowania, zanim napisze testy. Zainstaluj go na poziomie projektu poleceniem npx skills add mattpocock/skills --skill tdd codebase-design -a codex -y. Skill codebase-design jest w poleceniu, bo tdd sięga po niego po słownictwo, a sam tdd zostawiłby to odwołanie bez celu. Opcje i pułapki opisuje strona skille do testowania i debugowania.

  4. 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-runner
    echo '{ "testRunner": "vitest" }' > stryker.config.json
    printf 'reports/\n.stryker-tmp/\n' >> .gitignore
    git add package.json package-lock.json stryker.config.json .gitignore
    git 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ę od origin/main, więc każdy dziedziczy tę konfigurację, a żaden tor nie dotyka package.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:

Okno terminala
codex exec --sandbox read-only --ephemeral -o coverage-gaps.md - < rank-gaps.txt

Plik 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ę.

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.

  1. Utwórz po jednym worktree na tor i sam zainstaluj zależności. Nowy worktree nie ma node_modules ani 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 origin
    for lane in orders payments auth; do
    git 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")
    done

    Zastąp origin/main swoją domyślną gałęzią, a nazwy torów tymi z analizy luk.

  2. Zatwierdź planowane nazwy testów w każdym torze. Uruchom codex w 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.

  3. 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; do
    codex exec -C "../app-tests-$lane" -c default_permissions=":workspace" \
    --ephemeral -o "/tmp/lane-$lane.md" - < "prompts/tests-$lane.txt" &
    done
    wait

    default_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ścia codex exec opisuje 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 worktree
set -euo pipefail
lane="$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 none
for 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 baseline
npx vitest run --coverage --coverage.reporter=json-summary >/dev/null
node -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/ || true

Bramka 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.

Okno terminala
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.

ObjawPrzyczynaJak wyjść
Pokrycie wzrosło, wynik mutacyjny został niskiTesty wykonują kod, ale sprawdzają tylko wywołanie mocka albo to, że wartość jest niepusta lub zdefiniowanaUruchom 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 pokryciaTesty importują mocka albo moduł spod innej ścieżkiWskaż niepokrytą gałąź z numerem linii i poproś Codexa o pomiar pokrycia tylko dla tego pliku
Testy przechodzą w torze, padają po scaleniuTor 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ściPoproś 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łamiWorktree 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ć wolnoKażdy wygenerowany test integracyjny stawia własną bazę danychWymagaj wspólnego przygotowania w beforeAll i transakcji na test; zobacz zarządzanie danymi testowymi
Codex ignoruje twoje polecenia testoweProjekt 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

Używasz też innego agenta? To samo zadanie opisują strony generowanie testów i TDD z Claude Code oraz wzorce testowania w Cursorze.