Test
Greph viene convalidato con tre livelli di test:
- Test unitari per componenti isolati (parser, walker, codec, opzioni).
- Corpus di regressione dell’oracolo, che confronta l’output di Greph con i binari canonici di
grep,ripgrepeast-grepsu un insieme fisso di scenari. - Matrice delle funzionalità basata su probe, che verifica le funzionalità disponibili nei wrapper
rgesg.
CI viene eseguita a ogni push su main e a ogni pull request (.github/workflows/ci.yml). Esegue gli standard di codifica (composer cs), l’analisi statica (composer analyse), le suite di test unitari e di integrazione di PHPUnit (composer test) e composer audit su PHP 8.4. Il corpus dell’oracolo (composer test:oracle) non fa parte di CI e la matrice delle funzionalità viene rigenerata manualmente con php bin/feature-matrix. La suite PHPUnit contiene un test che genera la matrice indicando come non disponibili rg e sg a monte, quindi verifica la struttura del report; in questo modo il test non fallisce se un singolo probe presenta una regressione.
Lavorare da un clone
Per tutto ciò che è descritto in questa pagina serve un clone del repository. Poiché 0.2.3 il pacchetto Composer contiene solo src/ e i quattro eseguibili runtime, ne sono esclusi tests/, scenarios/, benchmarks/ e gli script di sviluppo in bin/.
git clone https://github.com/inline0/greph
cd greph
composer install
Eseguire i test
# 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 è un requisito per ogni release. Se non viene superato, la modifica non è completa.
Il modello dell’oracolo
Greph segue un modello di verifica basato sull’oracolo. Per ogni scenario vengono eseguiti tre comandi:
- Oracolo:
grep,ripgrepoast-grep, eseguito sul corpus di scenari per acquisirne l’output. - Risultato effettivo: Greph, eseguito sullo stesso corpus per acquisirne l’output.
- Comparatore: un confronto strutturato che verifica l’equivalenza riga per riga o semantica.
Se Greph non concorda con l’oracolo, Greph è errato. Se grep e rg non concordano tra loro, lo scenario registra la discrepanza in oracle_disagreement, indica quale strumento Greph segue in greph_follows e imposta su skip il confronto con l’altro strumento. Nel corpus sono presenti entrambe le situazioni.
Gli scenari testuali vengono confrontati con grep e rg, mentre gli scenari AST e di riscrittura con sg. L’output dell’oracolo viene acquisito una volta e salvato nel repository nella directory oracle/ di ciascuno scenario, quindi per una normale esecuzione basta PHP; gli strumenti esterni servono solo per acquisire o aggiornare l’output dell’oracolo.
L’implementazione si trova in tests/Oracle/ e gli scenari in scenarios/text/, scenarios/ast/, scenarios/rewrite/ e scenarios/edge/.
Struttura degli scenari
Ogni scenario è una directory autonoma:
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 dichiara il pattern, i flag e il percorso di ricerca. Un oggetto expectations facoltativo imposta la modalità di confronto per ciascun oracolo (exact, semantic o skip); in sua assenza, gli scenari testuali confrontano grep e rg esattamente e rg JSON in modo semantico, mentre gli scenari AST e di riscrittura vengono confrontati con sg.
Eseguire un singolo scenario
Il repository include un piccolo insieme di CLI per lavorare con singoli scenari. Sono strumenti di sviluppo, non entry point runtime: si trovano accanto ai binari runtime in bin/, ma non fanno parte del pacchetto Composer. Ognuna accetta il nome dello scenario relativo a 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
Eseguire l’intera suite di regressione
# 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
Gli scenari vengono sempre eseguiti uno alla volta. --jobs N viene accettato e riportato nella riga di riepilogo, ma non esegue nulla in parallelo (#7). In un clone nuovo text/no-ignore e text/explicit-file-input falliscono, perché i relativi file fixture in setup/vendor/ non sono inclusi nel repository (#6).
La suite di regressione è il criterio di accesso per i nuovi comportamenti. Un nuovo flag, un nuovo caso limite o la correzione di un bug richiedono uno scenario che acquisisca il comportamento previsto rispetto a un oracolo.
Report di conformità
./bin/verify-compliance
verify-compliance non esegue nulla direttamente. Legge i file dell’oracolo, dei risultati effettivi e dei report lasciati dall’ultima esecuzione degli scenari, quindi indica quali scenari sono superati, quali falliscono e per quali non è ancora disponibile un report. Eseguite prima ./bin/test-regression. Anche --output report.json scrive il report in JSON. È il comando giusto per sapere «il branch corrente è pronto per il rilascio?».
Flusso di lavoro con sviluppo guidato dai test
Quando aggiungete una funzionalità:
- Scrivete una directory di scenario con il corpus e i flag necessari a verificare il nuovo comportamento.
- Eseguite
./bin/oracle <scenario>per acquisire l’output dello strumento canonico. - Implementate la funzionalità in
src/. - Eseguite
./bin/test-scenario <scenario>per verificare che Greph corrisponda all’oracolo. - Eseguite
./bin/test-regression --fastper assicurarvi che non ci siano altre regressioni. - Eseguite
composer verifyprima di creare il commit.
Quando correggete un bug:
- Acquisite l’input che causa il malfunzionamento in uno scenario.
- Verificate che l’oracolo produca l’output previsto.
- Verificate che Greph non lo produca.
- Correggete il bug.
- Verificate che ora Greph corrisponda all’oracolo.
- Eseguite
composer verify.
Lo scenario resta per sempre nel corpus, così il bug non può ripresentarsi senza far fallire composer test:oracle (e composer verify).