Przejdź do treści

Testowanie

Greph jest weryfikowany w trzech warstwach testów:

  1. Testy jednostkowe dla odizolowanych komponentów (parserów, walkerów, kodeków, opcji).
  2. Korpus regresyjny oracle, który porównuje wyjście Greph z kanonicznymi plikami binarnymi grep, ripgrep i ast-grep dla ustalonego zestawu scenariuszy.
  3. Macierz funkcji oparta na sondach, która sprawdza zweryfikowany zakres funkcji opakowań rg i sg.

CI uruchamia się przy każdym wypchnięciu zmian do main i przy każdym żądaniu pull request (.github/workflows/ci.yml). Obejmuje standardy kodowania (composer cs), analizę statyczną (composer analyse), zestawy testów jednostkowych i integracyjnych PHPUnit (composer test) oraz composer audit na PHP 8.4. Korpus oracle (composer test:oracle) nie jest częścią CI, a macierz funkcji jest generowana ręcznie za pomocą php bin/feature-matrix. Zestaw PHPUnit zawiera test, który generuje macierz, gdy nadrzędne narzędzia rg i sg są oznaczone jako niedostępne, i sprawdza strukturę raportu, więc nie kończy się niepowodzeniem, gdy pojedyncza sonda ulegnie regresji.

Praca z klonem repozytorium

Wszystko na tej stronie wymaga klonu repozytorium. Ponieważ pakiet Composer zawiera tylko src/ i cztery pliki wykonywalne środowiska uruchomieniowego, 0.2.3 tests/, scenarios/, benchmarks/ i skrypty deweloperskie z bin/ są z niego wyłączone.

Powłoka
git clone https://github.com/inline0/greph
cd greph
composer install

Uruchamianie testów

Powłoka
# PHPUnit unit and integration suites
composer test

# Oracle regression corpus
composer test:oracle

# Static analysis
composer analyse

# Coding standards
composer cs
composer cs:fix

# Full release-grade verification (analyse + cs + test + test:oracle)
composer verify

composer verify to warunek każdego wydania. Jeśli nie przejdzie, zmiana nie jest gotowa.

Model oracle

Greph stosuje model weryfikacji oparty na oracle. Dla każdego scenariusza uruchamiane są trzy polecenia:

  1. Oracle: grep, ripgrep lub ast-grep, zarejestrowane dla korpusu scenariuszy.
  2. Wynik rzeczywisty: Greph, zarejestrowany dla tego samego korpusu.
  3. Porównywarka: ustrukturyzowane porównanie sprawdzające zgodność wiersz po wierszu lub semantyczną.

Jeśli Greph nie zgadza się z oracle, Greph jest błędne. Jeśli grep i rg nie zgadzają się ze sobą, scenariusz zapisuje rozbieżność w oracle_disagreement, wskazuje narzędzie, za którym podąża Greph w greph_follows, i ustawia porównanie z drugim narzędziem na skip. W korpusie występują oba kierunki rozbieżności.

Scenariusze tekstowe są porównywane z grep i rg, a scenariusze AST i przepisywania z sg. Wyjście oracle jest przechwytywane raz i zatwierdzane w katalogu oracle/ każdego scenariusza, więc zwykłe uruchomienie wymaga tylko PHP; narzędzia zewnętrzne są potrzebne wyłącznie do przechwycenia lub odświeżenia wyjścia oracle.

Implementacja znajduje się w tests/Oracle/, a scenariusze w scenarios/text/, scenarios/ast/, scenarios/rewrite/ i scenarios/edge/.

Układ scenariusza

Każdy scenariusz to samodzielny katalog:

Kod
scenarios/text/literal-simple/
├── scenario.json     # name, category, pattern, flags, path
├── setup/            # corpus to search through
├── oracle/           # captured oracle output (grep.txt, rg.txt, rg.json, ...)
├── actual/           # captured greph output (generated, git-ignored)
└── reports/          # comparison results (generated, git-ignored)

scenario.json deklaruje wzorzec, flagi i ścieżkę wyszukiwania. Opcjonalny obiekt expectations ustawia tryb porównania dla każdego oracle (exact, semantic lub skip); bez niego scenariusze tekstowe porównują dokładnie grep i rg, a rg JSON semantycznie, zaś scenariusze AST i przepisywania porównują z sg.

Uruchamianie pojedynczego scenariusza

Repozytorium zawiera niewielki zestaw interfejsów CLI do pracy z pojedynczymi scenariuszami. Są to narzędzia deweloperskie, a nie punkty wejścia środowiska uruchomieniowego: znajdują się obok plików binarnych środowiska uruchomieniowego w bin/, ale nie należą do pakietu Composer. Każde z nich przyjmuje nazwę scenariusza względem scenarios/.

Powłoka
# Capture oracle output for a scenario (needs grep and rg, or sg)
./bin/oracle text/literal-simple

# Run greph against a scenario, capture its output
./bin/actual text/literal-simple

# Diff oracle vs actual
./bin/compare text/literal-simple

# Full pipeline: oracle (only if missing) -> actual -> compare
./bin/test-scenario text/literal-simple

# Recapture the oracle output first
./bin/test-scenario text/literal-simple --refresh

Uruchamianie pełnego zestawu testów regresyjnych

Powłoka
# All scenarios (the same as composer test:oracle)
./bin/test-regression

# Filter by category
./bin/test-regression --category text
./bin/test-regression --category ast
./bin/test-regression --category rewrite
./bin/test-regression --category edge

# Print only failures and the summary
./bin/test-regression --fast

# Recapture every oracle before comparing
./bin/test-regression --refresh

Scenariusze zawsze są uruchamiane pojedynczo. --jobs N jest akceptowane i wyświetlane w wierszu podsumowania, ale nie uruchamia niczego równolegle (#7). W świeżym klonie text/no-ignore i text/explicit-file-input kończą się niepowodzeniem, ponieważ ich pliki fixture w setup/vendor/ nie są zatwierdzone (#6).

Zestaw testów regresyjnych jest bramką dla nowych funkcji. Nowa flaga, przypadek brzegowy lub poprawka błędu wymagają scenariusza rejestrującego oczekiwane działanie względem oracle.

Raportowanie zgodności

Powłoka
./bin/verify-compliance

verify-compliance sam niczego nie uruchamia. Odczytuje pliki oracle, wyników rzeczywistych i raportów pozostawione przez ostatnie uruchomienia scenariuszy, a następnie wyświetla, które scenariusze przechodzą, które kończą się niepowodzeniem i dla których nie ma jeszcze raportu. Najpierw uruchom ./bin/test-regression. --output report.json zapisuje również raport jako JSON. To właściwe polecenie, gdy chcesz sprawdzić, „czy bieżąca gałąź jest gotowa do wydania”.

Przepływ pracy oparty na testach

Dodając funkcję:

  1. Utwórz katalog scenariusza z korpusem i flagami sprawdzającymi nowe działanie.
  2. Uruchom ./bin/oracle <scenario>, aby przechwycić wyjście kanonicznego narzędzia.
  3. Zaimplementuj funkcję w src/.
  4. Uruchom ./bin/test-scenario <scenario>, aby sprawdzić, czy Greph zgadza się z oracle.
  5. Uruchom ./bin/test-regression --fast, aby upewnić się, że nic innego nie uległo regresji.
  6. Uruchom composer verify przed zatwierdzeniem zmian.

Naprawiając błąd:

  1. Zapisz błędne dane wejściowe jako scenariusz.
  2. Potwierdź, że oracle generuje oczekiwane wyjście.
  3. Potwierdź, że Greph go nie generuje.
  4. Napraw błąd.
  5. Potwierdź, że Greph zgadza się teraz z oracle.
  6. Uruchom composer verify.

Scenariusz na stałe pozostaje w korpusie, więc błąd nie może powrócić niezauważony, ponieważ testy composer test:oracle (i composer verify) zakończą się niepowodzeniem.