
# Testen

Greph wordt gevalideerd met drie testlagen:

1. **Unit-tests** voor geïsoleerde componenten (parsers, walkers, codecs, opties).
2. **Regressiecorpus van het orakel** dat de uitvoer van Greph vergelijkt met de canonieke binaire bestanden van `grep`, `ripgrep` en `ast-grep` aan de hand van een vaste reeks scenario's.
3. **Functiematrix op basis van probes** die het geverifieerde oppervlak van de wrappers `rg` en `sg` controleert.

CI wordt uitgevoerd bij elke push naar `main` en bij elke pull request (`.github/workflows/ci.yml`). Het voert coderingsstandaarden (`composer cs`), statische analyse (`composer analyse`), de unit- en integratietestsuites van PHPUnit (`composer test`) en `composer audit` uit op PHP 8.4. Het orakelcorpus (`composer test:oracle`) maakt geen deel uit van CI en de functiematrix wordt handmatig opnieuw gegenereerd met `php bin/feature-matrix`. De suite PHPUnit bevat een test die de matrix genereert terwijl de upstream `rg` en `sg` als niet beschikbaar zijn gemarkeerd, en controleert de structuur van het rapport. Daardoor mislukt de test niet als één probe een regressie vertoont.

## Werken vanuit een kloon

Voor alles op deze pagina is een kloon van de repository nodig. Omdat het Composer-pakket van 0.2.3 alleen `src/` en de vier runtime-uitvoerbare bestanden bevat, zijn `tests/`, `scenarios/`, `benchmarks/` en de ontwikkelscripts in `bin/` ervan uitgesloten.

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

## De tests uitvoeren

```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` is de norm voor elke release. Als deze niet slaagt, is de wijziging niet af.

## Het orakelmodel

Greph volgt een verificatiemodel dat door een orakel wordt gestuurd. Voor elk scenario worden drie opdrachten uitgevoerd:

1. **Orakel**: `grep`, `ripgrep` of `ast-grep`, vastgelegd voor het scenariocorpus.
2. **Werkelijk**: Greph, vastgelegd voor hetzelfde corpus.
3. **Vergelijker**: een gestructureerde diff die gelijkwaardigheid per regel of semantisch controleert.

Als Greph afwijkt van het orakel, is Greph onjuist. Als `grep` en `rg` van elkaar afwijken, legt het scenario het verschil vast onder `oracle_disagreement`, vermeldt het welke tool Greph volgt in `greph_follows` en stelt het de vergelijking met de andere tool in op `skip`. Beide richtingen komen voor in het corpus.

Tekstscenario's worden vergeleken met `grep` en `rg`; AST- en herschrijvingsscenario's met `sg`. De orakeluitvoer wordt eenmaal vastgelegd en opgeslagen in de map `oracle/` van elk scenario. Voor een normale uitvoering is daarom alleen PHP nodig; de externe tools zijn alleen nodig om orakeluitvoer vast te leggen of te vernieuwen.

De implementatie staat onder `tests/Oracle/` en de scenario's staan onder `scenarios/text/`, `scenarios/ast/`, `scenarios/rewrite/` en `scenarios/edge/`.

## Scenariostructuur

Elk scenario is een zelfstandige map:

```
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` definieert het patroon, de flags en het zoekpad. Een optioneel object `expectations` stelt de vergelijkingsmodus per orakel in (`exact`, `semantic` of `skip`). Zonder dit object vergelijken tekstscenario's `grep` en `rg` exact en de `rg` JSON semantisch; AST- en herschrijvingsscenario's vergelijken met `sg`.

## Eén scenario uitvoeren

De repository bevat een kleine set CLI's om met afzonderlijke scenario's te werken. Dit zijn ontwikkeltools, geen runtime-entrypoints: ze staan naast de runtime-binaire bestanden in `bin/`, maar maken geen deel uit van het Composer-pakket. Elke CLI gebruikt de scenarionaam relatief ten opzichte van `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
```

## De volledige regressiesuite uitvoeren

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

Scenario's worden altijd één voor één uitgevoerd. `--jobs N` wordt geaccepteerd en weergegeven in de samenvattingsregel, maar voert niets parallel uit ([#7](https://github.com/inline0/greph/issues/7)). In een nieuwe kloon mislukken `text/no-ignore` en `text/explicit-file-input`, omdat hun fixturebestanden in `setup/vendor/` niet zijn opgeslagen ([#6](https://github.com/inline0/greph/issues/6)).

De regressiesuite is de poortwachter voor nieuw gedrag. Voor een nieuwe flag, een nieuw randgeval of een bugfix is een scenario nodig waarin het verwachte gedrag aan de hand van een orakel wordt vastgelegd.

## Nalevingsrapportage

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

`verify-compliance` voert zelf niets uit. Het leest de orakel-, werkelijke en rapportbestanden die de laatste scenariorun heeft achtergelaten en geeft aan welke scenario's slagen, welke mislukken en voor welke nog geen rapport bestaat. Voer eerst `./bin/test-regression` uit. `--output report.json` schrijft het rapport ook weg als JSON. Dit is de juiste opdracht als u wilt weten: "is de huidige branch klaar voor release?".

## Testgestuurde ontwikkelworkflow

Bij het toevoegen van een functie:

1. Schrijf een scenariomap met het corpus en de flags die het nieuwe gedrag testen.
2. Voer `./bin/oracle <scenario>` uit om de uitvoer van de canonieke tool vast te leggen.
3. Implementeer de functie in `src/`.
4. Voer `./bin/test-scenario <scenario>` uit om te controleren of Greph overeenkomt met het orakel.
5. Voer `./bin/test-regression --fast` uit om te controleren of er niets anders is verslechterd.
6. Voer `composer verify` uit voordat u commit.

Bij het oplossen van een bug:

1. Leg de mislukte invoer vast als scenario.
2. Controleer of het orakel de verwachte uitvoer produceert.
3. Controleer of Greph dat niet doet.
4. Los de bug op.
5. Controleer of Greph nu overeenkomt met het orakel.
6. Voer `composer verify` uit.

Het scenario blijft permanent in het corpus, zodat de bug niet terug kan komen zonder dat `composer test:oracle` (en `composer verify`) mislukken.
