
# Testning

Greph valideras med tre testlager:

1. **Enhetstester** för isolerade komponenter (parsrar, vandrare, kodare, alternativ).
2. **Oracle-regressionskorpus** som jämför Grephs utdata med de kanoniska binärfilerna `grep`, `ripgrep` och `ast-grep` för en fast uppsättning scenarier.
3. **Sondstyrd funktionsmatris** som verifierar den stödda ytan hos omslagen `rg` och `sg`.

CI körs vid varje push till `main` och vid varje pull-begäran (`.github/workflows/ci.yml`). Den kör kodningsstandarder (`composer cs`), statisk analys (`composer analyse`), enhets- och integrationstesterna för PHPUnit (`composer test`) samt `composer audit` på PHP 8.4. Oracle-korpuset (`composer test:oracle`) ingår inte i CI, och funktionsmatrisen genereras manuellt med `php bin/feature-matrix`. Testsviten PHPUnit innehåller ett test som genererar matrisen med uppströmsverktygen `rg` och `sg` markerade som otillgängliga och kontrollerar rapportens struktur, så den misslyckas inte när en enskild sond går sönder.

## Arbeta från en klon

Allt på den här sidan kräver en klon av kodarkivet. Eftersom 0.2.3-paketet Composer bara innehåller `src/` och de fyra körbara filerna för körning, utelämnas `tests/`, `scenarios/`, `benchmarks/` och utvecklingsskripten i `bin/`.

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

## Köra testerna

```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` är kravet för varje release. Om det inte godkänns är ändringen inte klar.

## Oracle-modellen

Greph använder en oracle-styrd verifieringsmodell. För varje scenario körs tre kommandon:

1. **Oracle**: `grep`, `ripgrep` eller `ast-grep`, insamlat för scenariokorpuset.
2. **Faktiskt resultat**: Greph, insamlat för samma korpus.
3. **Jämförelseverktyg**: en strukturerad jämförelse som kontrollerar likvärdighet rad för rad eller semantiskt.

Om Greph inte stämmer överens med oracle-resultatet är Greph fel. Om `grep` och `rg` inte stämmer överens med varandra registrerar scenariot avvikelsen under `oracle_disagreement`, anger vilket verktyg Greph följer i `greph_follows` och sätter jämförelsen mot det andra verktyget till `skip`. Båda riktningarna förekommer i korpuset.

Textscenarier jämförs med `grep` och `rg`, AST- och omskrivningsscenarier med `sg`. Oracle-utdata samlas in en gång och checkas in under varje scenarios katalog `oracle/`, så en vanlig körning behöver bara PHP; externa verktyg behövs endast för att samla in eller uppdatera oracle-utdata.

Implementationen finns under `tests/Oracle/` och scenarierna finns under `scenarios/text/`, `scenarios/ast/`, `scenarios/rewrite/` och `scenarios/edge/`.

## Scenariostruktur

Varje scenario är en fristående 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` anger mönstret, flaggorna och sökvägen. Ett valfritt `expectations`-objekt ställer in jämförelseläget för varje oracle (`exact`, `semantic` eller `skip`); utan det jämförs textscenariernas `grep` och `rg` exakt och `rg` JSON semantiskt, medan AST- och omskrivningsscenarier jämförs med `sg`.

## Köra ett enskilt scenario

Kodarkivet har en liten uppsättning CLI-verktyg för att arbeta med enskilda scenarier. De är utvecklingsverktyg, inte körningsingångar: de finns bredvid körningens binärfiler i `bin/` men ingår inte i paketet Composer. Varje verktyg tar scenarionamnet relativt `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
```

## Köra hela regressionssviten

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

Scenarier körs alltid ett i taget. `--jobs N` godtas och återges på sammanfattningsraden, men kör ingenting parallellt ([#7](https://github.com/inline0/greph/issues/7)). I en ny klon misslyckas `text/no-ignore` och `text/explicit-file-input`, eftersom deras fixture-filer under `setup/vendor/` inte har checkats in ([#6](https://github.com/inline0/greph/issues/6)).

Regressionssviten är grinden för nytt beteende. En ny flagga, ett nytt specialfall eller en ny buggfix kräver ett scenario som fångar det förväntade beteendet mot ett oracle.

## Efterlevnadsrapportering

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

`verify-compliance` kör ingenting själv. Det läser oracle-, resultat- och rapportfilerna som den senaste scenariokörningen lämnade efter sig och skriver ut vilka scenarier som godkänns, vilka som misslyckas och vilka som ännu saknar rapport. Kör `./bin/test-regression` först. `--output report.json` skriver också rapporten som JSON. Det är rätt kommando att köra när du vill veta ”är den aktuella grenen redo för release?”.

## Arbetsflöde för testdriven utveckling

När du lägger till en funktion:

1. Skriv en scenariokatalog med korpus och flaggor som testar det nya beteendet.
2. Kör `./bin/oracle <scenario>` för att samla in det kanoniska verktygets utdata.
3. Implementera funktionen i `src/`.
4. Kör `./bin/test-scenario <scenario>` för att verifiera att Greph stämmer överens med oracle-resultatet.
5. Kör `./bin/test-regression --fast` för att säkerställa att inget annat har gått sönder.
6. Kör `composer verify` innan du checkar in.

När du åtgärdar en bugg:

1. Spara den felande indata som ett scenario.
2. Bekräfta att oracle-resultatet ger det förväntade utfallet.
3. Bekräfta att Greph inte gör det.
4. Åtgärda buggen.
5. Bekräfta att Greph nu stämmer överens med oracle-resultatet.
6. Kör `composer verify`.

Scenariot blir kvar i korpuset permanent, så buggen kan inte återkomma utan att `composer test:oracle` (och `composer verify`) misslyckas.
