Testen
Greph wordt gevalideerd met drie testlagen:
- Unit-tests voor geïsoleerde componenten (parsers, walkers, codecs, opties).
- Regressiecorpus van het orakel dat de uitvoer van Greph vergelijkt met de canonieke binaire bestanden van
grep,ripgrepenast-grepaan de hand van een vaste reeks scenario's. - Functiematrix op basis van probes die het geverifieerde oppervlak van de wrappers
rgensgcontroleert.
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.
git clone https://github.com/inline0/greph
cd greph
composer install
De tests uitvoeren
# 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:
- Orakel:
grep,ripgrepofast-grep, vastgelegd voor het scenariocorpus. - Werkelijk: Greph, vastgelegd voor hetzelfde corpus.
- 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/.
# 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
# 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). In een nieuwe kloon mislukken text/no-ignore en text/explicit-file-input, omdat hun fixturebestanden in setup/vendor/ niet zijn opgeslagen (#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
./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:
- Schrijf een scenariomap met het corpus en de flags die het nieuwe gedrag testen.
- Voer
./bin/oracle <scenario>uit om de uitvoer van de canonieke tool vast te leggen. - Implementeer de functie in
src/. - Voer
./bin/test-scenario <scenario>uit om te controleren of Greph overeenkomt met het orakel. - Voer
./bin/test-regression --fastuit om te controleren of er niets anders is verslechterd. - Voer
composer verifyuit voordat u commit.
Bij het oplossen van een bug:
- Leg de mislukte invoer vast als scenario.
- Controleer of het orakel de verwachte uitvoer produceert.
- Controleer of Greph dat niet doet.
- Los de bug op.
- Controleer of Greph nu overeenkomt met het orakel.
- Voer
composer verifyuit.
Het scenario blijft permanent in het corpus, zodat de bug niet terug kan komen zonder dat composer test:oracle (en composer verify) mislukken.