
# Testování pomocí referenční implementace

Každé rozhodnutí při implementaci Phasis závisí na jediné otázce: **vytváří V8 stejný výstup?**

JavaScript má jemné sémantické nuance — `NaN !== NaN`, `-0 === 0`, `[1] + 1 === "11"`, přesné pořadí výčtu vlastností a načasování úloh fronty microtasků `Promise`. Odvozovat je znovu čtením specifikace je pomalé a náchylné k chybám. Phasis tento problém obchází tím, že Node.js (V8) považuje za referenční implementaci: napíšete scénář JS, spustíte ho přes V8 a výstup uložíte jako správný výsledek; poté jej spustíte přes Phasis, znovu zachytíte výstup a porovnáte je.

```
1. SETUP    → a JavaScript source file or snippet
2. ORACLE   → Node.js executes it, output captured as truth
3. ACTUAL   → Phasis executes it, output captured
4. COMPARE  → oracle vs actual, diff measures the gap
```

## Dvě úrovně testování

### Úroveň 1 — Vlastní scénáře

Každý scénář v `scenarios/` je krátký program JS se známým výstupem. Spusťte jeden scénář:

```bash
./bin/test-scenario operators/arithmetic
```

Spusťte všechny scénáře, jen jednu kategorii nebo je spusťte paralelně:

```bash
./bin/test-regression
./bin/test-regression --jobs 4
./bin/test-regression --category expressions
```

Obnovte referenční výstupy (e.g, například po aktualizaci verze Node.js):

```bash
./bin/oracle --refresh operators/arithmetic
```

Scénáře jsou uspořádány podle kapitol ECMAScriptu: literály, operátory, proměnné, řízení toku, funkce, objekty, pole, třídy, vestavěné funkce, chyby, interoperabilita a okrajové případy.

### Úroveň 2 — test262

Oficiální sada testů shody TC39 je připojena jako git submodul pod `test262/`. Každý test ověřuje sám sebe: projde, pokud nevyvolá chybu, a selže, pokud ji vyvolá (u testů `negative` je to naopak). Testovací prostředí před každým testem načte `assert.js` a `sta.js`.

```bash
./bin/test262                                    # full suite
./bin/test262 --category built-ins/Array         # subset
./bin/test262 --jobs 4                           # parallel
./bin/test262 --failures                         # one line per failing test
./bin/compat-report                              # full COMPAT.md + compat.json
```

Snímek celé sady testů je v souboru [`COMPAT.md`](https://github.com/inline0/phasis/blob/main/COMPAT.md) a znovu jej vytvoří `bin/compat-report`. V CI jej pracovní postup `compat-matrix.yml` spouští po částech a ukládá výsledek; tento postup se spouští ručně, nikoli při každém pushi.

## Lokální kontrola před odesláním změn

`./bin/verify-all` spouští kontrolu kvality vyžadovanou CI:

```
=== PHPStan ===                  level 6, zero errors
=== Code Standards ===           PHPCS, zero warnings
=== PHPUnit ===                  unit suite passes
=== Oracle Regression ===        scenarios under `scenarios/` pass
```

Sama o sobě **nestačí** — při každé změně parseru, interpretu nebo vestavěných funkcí je nutné otestovat i vybrané testy test262. Při každém pull requestu CI spouští PHPStan, PHPCS, unit testy a regresní test referenční implementace; sady WPT a popular se spouští při změnách v `src/` nebo v jejich přípravcích. Úplná matice test262 není součástí CI pro pull requesty, proto lokálně vyberte dotčené kategorie.

## Proč to funguje

Když V8 považujeme za zdroj pravdy, vývojový cyklus téměř nevyžaduje čtení specifikace. Neshoda s V8 vždy ukazuje na chybu v Phasis, nikdy na sporný výklad specifikace. Po vydání opravy se příslušné testy test262 stanou trvalými regresními testy.

Míra úspěšnosti 100 % je výsledkem tohoto přístupu: každý PR se hodnotí vůči V8, CI odmítá regrese v testech referenční implementace, WPT a popular a matice test262 potvrzuje výsledek celé sady, když se spustí.
