Testare
Greph este validat prin trei niveluri de teste:
- Teste unitare pentru componente izolate (analizoare, parcurgătoare, codec-uri, opțiuni).
- Corpus de regresie oracle care compară rezultatul Greph cu binarele canonice
grep,ripgrepșiast-greppentru un set fix de scenarii. - Matrice de funcționalități bazată pe probe care verifică suprafața confirmată a wrapper-elor
rgșisg.
CI rulează la fiecare push către main și la fiecare cerere de pull (.github/workflows/ci.yml). Rulează verificările standardelor de cod (composer cs), analiza statică (composer analyse), suitele de teste unitare și de integrare PHPUnit (composer test) și composer audit pe PHP 8.4. Corpusul oracle (composer test:oracle) nu face parte din CI, iar matricea de funcționalități este regenerată manual cu php bin/feature-matrix. Suita PHPUnit conține un test care generează matricea cu rg și sg din amonte marcate ca indisponibile și verifică structura raportului, astfel că nu eșuează când o singură probă are o regresie.
Lucrul cu o clonă
Tot ce se află pe această pagină necesită o clonă a depozitului. Deoarece 0.2.3, pachetul Composer conține doar src/ și cele patru executabile pentru runtime; tests/, scenarios/, benchmarks/ și scripturile de dezvoltare din bin/ sunt excluse din acesta.
git clone https://github.com/inline0/greph
cd greph
composer install
Rularea testelor
# 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 este criteriul pentru orice versiune. Dacă nu trece, modificarea nu este gata.
Modelul oracle
Greph folosește un model de verificare bazat pe oracle. Pentru fiecare scenariu se execută trei comenzi:
- Oracle:
grep,ripgrepsauast-grep, capturat pentru corpusul de scenarii. - Rezultat real: Greph, capturat pentru același corpus.
- Comparator: o comparație structurată care verifică echivalența linie cu linie sau semantică.
Dacă Greph nu corespunde oracle-ului, Greph este greșit. Dacă grep și rg nu corespund, scenariul consemnează dezacordul sub oracle_disagreement, numește instrumentul urmat de Greph în greph_follows și setează comparația cu celălalt instrument la skip. În corpus există ambele direcții.
Scenariile text sunt comparate cu grep și rg, iar scenariile AST și de rescriere cu sg. Rezultatul oracle este capturat o singură dată și comis în directorul oracle/ al fiecărui scenariu, astfel că o rulare obișnuită necesită doar PHP; instrumentele externe sunt necesare doar pentru capturarea sau reîmprospătarea rezultatului oracle.
Implementarea se află în tests/Oracle/, iar scenariile se află în scenarios/text/, scenarios/ast/, scenarios/rewrite/ și scenarios/edge/.
Structura scenariilor
Fiecare scenariu este un director autonom:
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 declară tiparul, opțiunile și calea de căutare. Un obiect expectations opțional setează modul de comparare pentru fiecare oracle (exact, semantic sau skip); în lipsa lui, scenariile text compară exact grep și rg, iar rg JSON semantic, în timp ce scenariile AST și de rescriere compară cu sg.
Rularea unui singur scenariu
Depozitul are un set restrâns de CLI-uri pentru lucrul cu scenarii individuale. Acestea sunt instrumente de dezvoltare, nu puncte de intrare pentru runtime: se află alături de binarele runtime în bin/, dar nu fac parte din pachetul Composer. Fiecare primește numele scenariului relativ la 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
Rularea întregii suite de regresie
# 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
Scenariile rulează întotdeauna unul câte unul. --jobs N este acceptat și afișat în linia de rezumat, dar nu rulează nimic în paralel (#7). Într-o clonă nouă, text/no-ignore și text/explicit-file-input eșuează deoarece fișierele fixture din setup/vendor/ nu sunt comise (#6).
Suita de regresie este criteriul de acceptare pentru funcționalități noi. Un nou flag, un caz-limită nou sau o remediere nouă de bug necesită un scenariu care surprinde comportamentul așteptat față de un oracle.
Raportare de conformitate
./bin/verify-compliance
verify-compliance nu execută nimic de unul singur. Citește fișierele oracle, de rezultat real și de raport lăsate de ultima rulare a scenariilor și afișează scenariile care trec, cele care eșuează și cele pentru care încă nu există raport. Rulați mai întâi ./bin/test-regression. --output report.json scrie și raportul ca JSON. Este comanda potrivită când vreți să aflați „este ramura curentă gata de lansare?”
Flux de lucru pentru dezvoltarea bazată pe teste
Când adăugați o funcționalitate:
- Scrieți un director de scenariu cu corpusul și flagurile care exercită noul comportament.
- Rulați
./bin/oracle <scenario>pentru a captura rezultatul instrumentului canonic. - Implementați funcționalitatea în
src/. - Rulați
./bin/test-scenario <scenario>pentru a verifica dacă Greph corespunde oracle-ului. - Rulați
./bin/test-regression --fastpentru a vă asigura că nimic altceva nu a regresat. - Rulați
composer verifyînainte de a face commit.
Când remediați un bug:
- Capturați intrarea care eșuează ca scenariu.
- Confirmați că oracle-ul produce rezultatul așteptat.
- Confirmați că Greph nu îl produce.
- Remediați bugul.
- Confirmați că Greph corespunde acum oracle-ului.
- Rulați
composer verify.
Scenariul rămâne permanent în corpus, astfel încât bugul nu poate reapărea fără ca composer test:oracle (și composer verify) să eșueze.