Treci la conținut

Testare

Greph este validat prin trei niveluri de teste:

  1. Teste unitare pentru componente izolate (analizoare, parcurgătoare, codec-uri, opțiuni).
  2. Corpus de regresie oracle care compară rezultatul Greph cu binarele canonice grep, ripgrep și ast-grep pentru un set fix de scenarii.
  3. Matrice de funcționalități bazată pe probe care verifică suprafața confirmată a wrapper-elor rg și sg.

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.

Shell
git clone https://github.com/inline0/greph
cd greph
composer install

Rularea testelor

Shell
# 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:

  1. Oracle: grep, ripgrep sau ast-grep, capturat pentru corpusul de scenarii.
  2. Rezultat real: Greph, capturat pentru același corpus.
  3. 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:

Cod
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/.

Shell
# 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

Shell
# 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

Shell
./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:

  1. Scrieți un director de scenariu cu corpusul și flagurile care exercită noul comportament.
  2. Rulați ./bin/oracle <scenario> pentru a captura rezultatul instrumentului canonic.
  3. Implementați funcționalitatea în src/.
  4. Rulați ./bin/test-scenario <scenario> pentru a verifica dacă Greph corespunde oracle-ului.
  5. Rulați ./bin/test-regression --fast pentru a vă asigura că nimic altceva nu a regresat.
  6. Rulați composer verify înainte de a face commit.

Când remediați un bug:

  1. Capturați intrarea care eșuează ca scenariu.
  2. Confirmați că oracle-ul produce rezultatul așteptat.
  3. Confirmați că Greph nu îl produce.
  4. Remediați bugul.
  5. Confirmați că Greph corespunde acum oracle-ului.
  6. 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.