Tests
Greph est validé à l’aide de trois niveaux de tests :
- Tests unitaires pour les composants isolés (analyseurs, parcours, codecs, options).
- Corpus de régression oracle qui compare la sortie de Greph aux binaires canoniques
grep,ripgrepetast-grepsur un ensemble fixe de scénarios. - Matrice de fonctionnalités fondée sur des sondes qui vérifie le périmètre pris en charge par les wrappers
rgetsg.
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.
git clone https://github.com/inline0/greph
cd greph
composer install
Exécuter les tests
# 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 :
- Oracle :
grep,ripgrepouast-grep, exécuté sur le corpus de scénarios. - Résultat réel : Greph, exécuté sur le même corpus.
- 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/.
# 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
# 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). 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).
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é
./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é :
- Écrivez un répertoire de scénario avec le corpus et les indicateurs qui exercent le nouveau comportement.
- Exécutez
./bin/oracle <scenario>pour capturer la sortie de l’outil canonique. - Implémentez la fonctionnalité dans
src/. - Exécutez
./bin/test-scenario <scenario>pour vérifier que Greph correspond à l’oracle. - Exécutez
./bin/test-regression --fastpour vérifier qu’aucune autre fonctionnalité n’a régressé. - Exécutez
composer verifyavant de valider les modifications.
Pour corriger un bogue :
- Enregistrez l’entrée qui échoue sous forme de scénario.
- Confirmez que l’oracle produit la sortie attendue.
- Confirmez que Greph ne le fait pas.
- Corrigez le bogue.
- Confirmez que Greph correspond désormais à l’oracle.
- 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).