
# Tests

Greph est validé à l’aide de trois niveaux de tests :

1. **Tests unitaires** pour les composants isolés (analyseurs, parcours, codecs, options).
2. **Corpus de régression oracle** qui compare la sortie de Greph aux binaires canoniques `grep`, `ripgrep` et `ast-grep` sur un ensemble fixe de scénarios.
3. **Matrice de fonctionnalités fondée sur des sondes** qui vérifie le périmètre pris en charge par les wrappers `rg` et `sg`.

L’intégration continue s’exécute à chaque push vers `main` et à chaque demande de fusion (`.github/workflows/ci.yml`). Elle vérifie les normes de codage (`composer cs`), l’analyse statique (`composer analyse`), les suites de tests unitaires et d’intégration de PHPUnit (`composer test`) ainsi que `composer audit` sur PHP 8.4. Le corpus oracle (`composer test:oracle`) ne fait pas partie de l’intégration continue et la matrice de fonctionnalités est régénérée manuellement avec `php bin/feature-matrix`. La suite PHPUnit comprend un test qui génère la matrice en indiquant que `rg` et `sg` en amont sont indisponibles, puis vérifie la structure du rapport ; il n’échoue donc pas si une seule sonde régresse.

## Travailler à partir d’un clone

Tout ce qui figure sur cette page nécessite un clone du dépôt. Comme 0.2.3, le package Composer ne contient que `src/` et les quatre exécutables d’exécution ; `tests/`, `scenarios/`, `benchmarks/` et les scripts de développement de `bin/` en sont exclus.

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

## Exécuter les tests

```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` est une exigence pour toute version. S’il échoue, la modification n’est pas terminée.

## Modèle oracle

Greph suit un modèle de vérification piloté par oracle. Pour chaque scénario, trois commandes sont exécutées :

1. **Oracle** : `grep`, `ripgrep` ou `ast-grep`, exécuté sur le corpus de scénarios.
2. **Résultat réel** : Greph, exécuté sur le même corpus.
3. **Comparateur** : une comparaison structurée qui vérifie l’équivalence ligne par ligne ou sémantique.

Si Greph diverge de l’oracle, Greph est incorrect. Si `grep` et `rg` divergent l’un de l’autre, le scénario consigne la divergence sous `oracle_disagreement`, indique l’outil suivi par Greph dans `greph_follows` et définit la comparaison avec l’autre outil comme `skip`. Le corpus couvre les deux cas.

Les scénarios textuels sont comparés à `grep` et `rg`, les scénarios AST et de réécriture à `sg`. La sortie oracle est capturée une fois et enregistrée dans le répertoire `oracle/` de chaque scénario ; une exécution normale ne nécessite donc que PHP. Les outils externes ne sont nécessaires que pour capturer ou actualiser la sortie oracle.

L’implémentation se trouve sous `tests/Oracle/` et les scénarios sous `scenarios/text/`, `scenarios/ast/`, `scenarios/rewrite/` et `scenarios/edge/`.

## Organisation des scénarios

Chaque scénario est un répertoire autonome :

```
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` déclare le motif, les options et le chemin de recherche. Un objet `expectations` facultatif définit le mode de comparaison pour chaque oracle (`exact`, `semantic` ou `skip`) ; sans cet objet, les scénarios textuels comparent `grep` et `rg` exactement et `rg` JSON de manière sémantique, tandis que les scénarios AST et de réécriture comparent à `sg`.

## Exécuter un scénario unique

Le dépôt comprend un petit ensemble d’interfaces en ligne de commande pour travailler sur des scénarios individuels. Ce sont des outils de développement, pas des points d’entrée à l’exécution : ils se trouvent à côté des binaires d’exécution dans `bin/`, mais ne font pas partie du package Composer. Chacun prend le nom du scénario relatif à `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
```

## Exécuter toute la suite de régression

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

Les scénarios s’exécutent toujours un par un. `--jobs N` est accepté et repris dans la ligne de résumé, mais ne lance rien en parallèle ([#7](https://github.com/inline0/greph/issues/7)). Dans un clone vierge, `text/no-ignore` et `text/explicit-file-input` échouent, car leurs fichiers de données de test dans `setup/vendor/` ne sont pas enregistrés dans le dépôt ([#6](https://github.com/inline0/greph/issues/6)).

La suite de régression est le passage obligé pour tout nouveau comportement. Un nouvel indicateur, un nouveau cas limite ou une correction de bogue nécessite un scénario qui enregistre le comportement attendu à l’aide d’un oracle.

## Rapport de conformité

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

`verify-compliance` n’exécute rien lui-même. Il lit les fichiers oracle, résultat réel et rapport laissés par la dernière exécution de scénario, puis affiche les scénarios réussis, ceux qui ont échoué et ceux qui n’ont pas encore de rapport. Exécutez d’abord `./bin/test-regression`. `--output report.json` enregistre aussi le rapport sous JSON. C’est la commande à exécuter pour savoir si la branche actuelle est prête pour une version.

## Processus de développement piloté par les tests

Pour ajouter une fonctionnalité :

1. Écrivez un répertoire de scénario avec le corpus et les indicateurs qui exercent le nouveau comportement.
2. Exécutez `./bin/oracle <scenario>` pour capturer la sortie de l’outil canonique.
3. Implémentez la fonctionnalité dans `src/`.
4. Exécutez `./bin/test-scenario <scenario>` pour vérifier que Greph correspond à l’oracle.
5. Exécutez `./bin/test-regression --fast` pour vérifier qu’aucune autre fonctionnalité n’a régressé.
6. Exécutez `composer verify` avant de valider les modifications.

Pour corriger un bogue :

1. Enregistrez l’entrée qui échoue sous forme de scénario.
2. Confirmez que l’oracle produit la sortie attendue.
3. Confirmez que Greph ne le fait pas.
4. Corrigez le bogue.
5. Confirmez que Greph correspond désormais à l’oracle.
6. Exécutez `composer verify`.

Le scénario reste définitivement dans le corpus ; le bogue ne peut donc pas réapparaître sans faire échouer `composer test:oracle` (et `composer verify`).
