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

```bash
git clone https://github.com/inline0/greph
cd greph
composer install
```

## Uruchamianie testów

```bash
# 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:

```
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/`.

```bash
# 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

```bash
# 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](https://github.com/inline0/greph/issues/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](https://github.com/inline0/greph/issues/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

```bash
./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.
