
# Testování

Greph se ověřuje ve třech vrstvách testů:

1. **Jednotkové testy** izolovaných komponent (parserů, procházečů, kodeků a voleb).
2. **Regresní korpus oracle**, který porovnává výstup Greph s kanonickými binárními soubory `grep`, `ripgrep` a `ast-grep` na pevné sadě scénářů.
3. **Matice funkcí řízená sondami**, která ověřuje dostupné funkce obalů `rg` a `sg`.

CI se spouští při každém odeslání změn do `main` a při každém požadavku na sloučení (`.github/workflows/ci.yml`). Spouští kontroly standardů kódu (`composer cs`), statickou analýzu (`composer analyse`), jednotkové a integrační sady PHPUnit (`composer test`) a `composer audit` na PHP 8.4. Korpus oracle (`composer test:oracle`) není součástí CI a matice funkcí se znovu generuje ručně pomocí `php bin/feature-matrix`. Sada PHPUnit obsahuje test, který vygeneruje matici s upstream nástroji `rg` a `sg` označenými jako nedostupné a ověří strukturu reportu, takže test neselže, když se zhorší výsledky jediné sondy.

## Práce s klonem

Vše na této stránce vyžaduje klon repozitáře. Protože 0.2.3 balíček Composer obsahuje pouze `src/` a čtyři spustitelné soubory za běhu; `tests/`, `scenarios/`, `benchmarks/` a vývojové skripty v `bin/` v něm chybí.

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

## Spouštění testů

```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` je podmínkou každého vydání. Pokud neprojde, změna není hotová.

## Model oracle

Greph se řídí modelem ověřování založeným na oracle. Pro každý scénář se spustí tři příkazy:

1. **Oracle**: `grep`, `ripgrep` nebo `ast-grep`, zachycený pro korpus scénářů.
2. **Skutečný výstup**: Greph, zachycený pro stejný korpus.
3. **Porovnávač**: strukturovaný rozdíl, který kontroluje shodu řádek po řádku nebo sémantickou ekvivalenci.

Pokud se Greph neshoduje s oracle, Greph je chybný. Pokud se `grep` a `rg` neshodují, scénář zaznamená tento rozpor pod `oracle_disagreement`, uvede nástroj, jehož výstup Greph v `greph_follows`, a porovnání s druhým nástrojem nastaví na `skip`. V korpusu se vyskytují oba směry.

Textové scénáře se porovnávají s `grep` a `rg`, scénáře AST a přepisování s `sg`. Výstup oracle se zachytí jednou a uloží se do adresáře `oracle/` každého scénáře, takže běžné spuštění potřebuje pouze PHP; externí nástroje jsou potřeba jen k zachycení nebo obnovení výstupu oracle.

Implementace je v `tests/Oracle/` a scénáře jsou v `scenarios/text/`, `scenarios/ast/`, `scenarios/rewrite/` a `scenarios/edge/`.

## Struktura scénářů

Každý scénář je samostatný adresář:

```
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 vzor, příznaky a cestu vyhledávání. Volitelný objekt `expectations` nastavuje režim porovnávání pro jednotlivé oracle (`exact`, `semantic` nebo `skip`); bez něj se textové scénáře porovnávají přesně podle `grep` a `rg` a sémanticky podle `rg` JSON, zatímco scénáře AST a přepisování se porovnávají s `sg`.

## Spuštění jednoho scénáře

Repozitář obsahuje několik malých CLI nástrojů pro práci s jednotlivými scénáři. Jsou to vývojové nástroje, nikoli vstupní body běhového prostředí: nacházejí se vedle spustitelných souborů v `bin/`, ale nejsou součástí balíčku Composer. Každý z nich přijímá název scénáře relativně k `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
```

## Spuštění celé regresní sady

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

Scénáře se vždy spouštějí jeden po druhém. `--jobs N` je přijímán a vypisován v souhrnném řádku, ale nic nespouští paralelně ([#7](https://github.com/inline0/greph/issues/7)). V novém klonu `text/no-ignore` a `text/explicit-file-input` selžou, protože jejich soubory fixture v `setup/vendor/` nejsou commitnuté ([#6](https://github.com/inline0/greph/issues/6)).

Regresní sada je podmínkou pro nové chování. Nový příznak, okrajový případ nebo oprava chyby vyžaduje scénář, který zachytí očekávané chování podle oracle.

## Reportování shody

```bash
./bin/verify-compliance
```

`verify-compliance` samo nic nespouští. Čte soubory oracle, skutečných výstupů a reportů, které po sobě zanechala poslední spuštěná sada scénářů, a vypisuje, které scénáře prošly, které selhaly a u kterých report zatím chybí. Nejprve spusťte `./bin/test-regression`. `--output report.json` také zapisuje report jako JSON. Je to správný příkaz, pokud chcete zjistit, „je současná větev připravena k vydání?“.

## Pracovní postup vývoje řízeného testy

Při přidávání funkce:

1. Vytvořte adresář scénáře s korpusem a příznaky, které prověří nové chování.
2. Spusťte `./bin/oracle <scenario>` a zachyťte výstup kanonického nástroje.
3. Implementujte funkci v `src/`.
4. Spusťte `./bin/test-scenario <scenario>` a ověřte, že Greph odpovídá oracle.
5. Spusťte `./bin/test-regression --fast` a zkontrolujte, že se nic dalšího nezhoršilo.
6. Před commitem spusťte `composer verify`.

Při opravě chyby:

1. Zachyťte vstup, který chybu vyvolává, jako scénář.
2. Ověřte, že oracle vytvoří očekávaný výstup.
3. Ověřte, že Greph jej nevytvoří.
4. Opravte chybu.
5. Ověřte, že Greph nyní odpovídá oracle.
6. Spusťte `composer verify`.

Scénář zůstane v korpusu natrvalo, takže se chyba nemůže vrátit, aniž by selhaly `composer test:oracle` (a `composer verify`).
