
# Testowanie z użyciem wzorca referencyjnego

Każda decyzja implementacyjna w Phasis zależy od odpowiedzi na jedno pytanie: **czy V8 generuje takie same wyniki?**

JavaScript ma subtelną semantykę — `NaN !== NaN`, `-0 === 0`, `[1] + 1 === "11"`, dokładną kolejność wyliczania właściwości i moment wykonywania mikrozadań `Promise`. Odtwarzanie jej na podstawie specyfikacji jest powolne i podatne na błędy. Phasis upraszcza ten proces, traktując Node.js (V8) jako wzorzec referencyjny: przygotuj scenariusz JS, uruchom go w V8 i zapisz wynik jako prawidłowy; następnie uruchom go w Phasis, ponownie zapisz wynik i porównaj oba.

```
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
```

## Dwa poziomy testowania

### Poziom 1 — Własne scenariusze

Każdy scenariusz w `scenarios/` to mały program JS o znanym wyniku. Uruchom pojedynczy scenariusz:

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

Uruchom wszystkie scenariusze, wybraną kategorię albo wiele równolegle:

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

Odśwież wzorzec referencyjny (e.g, na przykład po aktualizacji wersji Node.js):

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

Scenariusze są uporządkowane według rozdziałów ECMAScript: literały, operatory, zmienne, przepływ sterowania, funkcje, obiekty, tablice, klasy, elementy wbudowane, błędy, współdziałanie i przypadki brzegowe.

### Poziom 2 — test262

Oficjalny zestaw testów zgodności TC39 jest pobierany jako podmoduł git w `test262/`. Każdy test weryfikuje się samodzielnie: zalicza się, jeśli nie zgłosi wyjątku, a nie zalicza, jeśli go zgłosi (lub odwrotnie w przypadku testów `negative`). Przed każdym testem środowisko testowe ładuje `assert.js` i `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
```

Pełny zrzut zestawu znajduje się w [`COMPAT.md`](https://github.com/inline0/phasis/blob/main/COMPAT.md); jest odtwarzany przez `bin/compat-report`. W CI workflow `compat-matrix.yml` uruchamia go w shardach i zatwierdza wynik; workflow jest uruchamiany ręcznie, a nie przy każdym pushu.

## Lokalna kontrola przed pushowaniem

`./bin/verify-all` uruchamia kontrolę jakości wymaganą przez CI:

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

Samo w sobie **nie** wystarcza — test262 trzeba również próbkować przy każdej zmianie parsera, interpretera lub funkcji wbudowanych. Przy każdym pull requeście CI uruchamia PHPStan, PHPCS, zestaw testów jednostkowych i testy regresji oracle; zestawy WPT i popularnych pakietów są uruchamiane, gdy pull request zmienia `src/` lub ich fixtures. Pełna macierz test262 nie jest częścią CI dla pull requestów, więc lokalnie przetestuj zmienione kategorie.

## Dlaczego to działa

Traktowanie V8 jako źródła prawdy eliminuje niemal całe czytanie specyfikacji z procesu tworzenia. Rozbieżność z V8 zawsze wskazuje na błąd Phasis — nigdy na niejasność specyfikacji, o którą można się spierać. Po wdrożeniu poprawki odpowiadające jej wpisy test262 stają się stałymi testami regresji.

Wskaźnik zaliczenia 100% jest wynikiem tej dyscypliny: każdy PR jest oceniany względem V8, CI odrzuca regresje w zestawach oracle, WPT i popularnych pakietów, a macierz test262 potwierdza wynik pełnego zestawu, gdy zostaje uruchomiona.
