Testování
Greph se ověřuje ve třech vrstvách testů:
- Jednotkové testy izolovaných komponent (parserů, procházečů, kodeků a voleb).
- Regresní korpus oracle, který porovnává výstup Greph s kanonickými binárními soubory
grep,ripgrepaast-grepna pevné sadě scénářů. - Matice funkcí řízená sondami, která ověřuje dostupné funkce obalů
rgasg.
CI se spouští při každém odeslání změn do main a při každém požadavku na sloučení (.github/workflows/ci.yml). Spouští kontroly standardů kódu (composer cs), statickou analýzu (composer analyse), jednotkové a integrační sady PHPUnit (composer test) a composer audit na PHP 8.4. Korpus oracle (composer test:oracle) není součástí CI a matice funkcí se znovu generuje ručně pomocí php bin/feature-matrix. Sada PHPUnit obsahuje test, který vygeneruje matici s upstream nástroji rg a sg označenými jako nedostupné a ověří strukturu reportu, takže test neselže, když se zhorší výsledky jediné sondy.
Práce s klonem
Vše na této stránce vyžaduje klon repozitáře. Protože 0.2.3 balíček Composer obsahuje pouze src/ a čtyři spustitelné soubory za běhu; tests/, scenarios/, benchmarks/ a vývojové skripty v bin/ v něm chybí.
git clone https://github.com/inline0/greph
cd greph
composer install
Spouštění 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 je podmínkou každého vydání. Pokud neprojde, změna není hotová.
Model oracle
Greph se řídí modelem ověřování založeným na oracle. Pro každý scénář se spustí tři příkazy:
- Oracle:
grep,ripgrepneboast-grep, zachycený pro korpus scénářů. - Skutečný výstup: Greph, zachycený pro stejný korpus.
- Porovnávač: strukturovaný rozdíl, který kontroluje shodu řádek po řádku nebo sémantickou ekvivalenci.
Pokud se Greph neshoduje s oracle, Greph je chybný. Pokud se grep a rg neshodují, scénář zaznamená tento rozpor pod oracle_disagreement, uvede nástroj, jehož výstup Greph v greph_follows, a porovnání s druhým nástrojem nastaví na skip. V korpusu se vyskytují oba směry.
Textové scénáře se porovnávají s grep a rg, scénáře AST a přepisování s sg. Výstup oracle se zachytí jednou a uloží se do adresáře oracle/ každého scénáře, takže běžné spuštění potřebuje pouze PHP; externí nástroje jsou potřeba jen k zachycení nebo obnovení výstupu oracle.
Implementace je v tests/Oracle/ a scénáře jsou v scenarios/text/, scenarios/ast/, scenarios/rewrite/ a scenarios/edge/.
Struktura scénářů
Každý scénář je samostatný adresář:
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 deklaruje vzor, příznaky a cestu vyhledávání. Volitelný objekt expectations nastavuje režim porovnávání pro jednotlivé oracle (exact, semantic nebo skip); bez něj se textové scénáře porovnávají přesně podle grep a rg a sémanticky podle rg JSON, zatímco scénáře AST a přepisování se porovnávají s sg.
Spuštění jednoho scénáře
Repozitář obsahuje několik malých CLI nástrojů pro práci s jednotlivými scénáři. Jsou to vývojové nástroje, nikoli vstupní body běhového prostředí: nacházejí se vedle spustitelných souborů v bin/, ale nejsou součástí balíčku Composer. Každý z nich přijímá název scénáře relativně k 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
Spuštění celé regresní sady
# 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
Scénáře se vždy spouštějí jeden po druhém. --jobs N je přijímán a vypisován v souhrnném řádku, ale nic nespouští paralelně (#7). V novém klonu text/no-ignore a text/explicit-file-input selžou, protože jejich soubory fixture v setup/vendor/ nejsou commitnuté (#6).
Regresní sada je podmínkou pro nové chování. Nový příznak, okrajový případ nebo oprava chyby vyžaduje scénář, který zachytí očekávané chování podle oracle.
Reportování shody
./bin/verify-compliance
verify-compliance samo nic nespouští. Čte soubory oracle, skutečných výstupů a reportů, které po sobě zanechala poslední spuštěná sada scénářů, a vypisuje, které scénáře prošly, které selhaly a u kterých report zatím chybí. Nejprve spusťte ./bin/test-regression. --output report.json také zapisuje report jako JSON. Je to správný příkaz, pokud chcete zjistit, „je současná větev připravena k vydání?“.
Pracovní postup vývoje řízeného testy
Při přidávání funkce:
- Vytvořte adresář scénáře s korpusem a příznaky, které prověří nové chování.
- Spusťte
./bin/oracle <scenario>a zachyťte výstup kanonického nástroje. - Implementujte funkci v
src/. - Spusťte
./bin/test-scenario <scenario>a ověřte, že Greph odpovídá oracle. - Spusťte
./bin/test-regression --fasta zkontrolujte, že se nic dalšího nezhoršilo. - Před commitem spusťte
composer verify.
Při opravě chyby:
- Zachyťte vstup, který chybu vyvolává, jako scénář.
- Ověřte, že oracle vytvoří očekávaný výstup.
- Ověřte, že Greph jej nevytvoří.
- Opravte chybu.
- Ověřte, že Greph nyní odpovídá oracle.
- Spusťte
composer verify.
Scénář zůstane v korpusu natrvalo, takže se chyba nemůže vrátit, aniž by selhaly composer test:oracle (a composer verify).