
# オラクルテスト

Phasisにおける実装上のあらゆる判断は、1つの問いを基準にします。**V8は同じ出力を生成するか？**

JavaScriptには、`NaN !== NaN`、`-0 === 0`、`[1] + 1 === "11"`、プロパティ列挙の厳密な順序、`Promise`マイクロタスクの実行タイミングなど、微妙な意味論があります。仕様を読んでこれらを再導出するのは時間がかかり、間違いも起きやすくなります。Phasisは、Node.js（V8）をオラクルとして扱うことで、この手間を省きます。JSのシナリオを書いてV8で実行し、出力を正解として記録します。次にPhasisで実行して出力を記録し、差分を比較します。

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

## 2段階のテスト

### レベル1 — カスタムシナリオ

`scenarios/`の各シナリオは、出力が既知の小さなJSプログラムです。シナリオを1つ実行するには：

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

すべてのシナリオ、特定のカテゴリだけ、または並列で実行できます：

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

オラクルを更新するには（e.g。Node.jsのバージョン更新後）：

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

シナリオはECMAScriptの章に沿って整理されています。リテラル、演算子、変数、制御フロー、関数、オブジェクト、配列、クラス、組み込み機能、エラー、相互運用、エッジケースです。

### レベル2 — test262

TC39の公式適合性テストスイートは、`test262/`のgitサブモジュールとしてチェックアウトされます。各テストは自己検証型です。例外が発生しなければ合格し、発生すれば失敗します（`negative`テストでは逆になります）。各テストの前に、ハーネスが`assert.js`と`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
```

全テストスイートのスナップショットは[`COMPAT.md`](https://github.com/inline0/phasis/blob/main/COMPAT.md)にあり、`bin/compat-report`で再生成されます。CIでは`compat-matrix.yml`ワークフローがこれを複数のシャードに分けて実行し、結果をコミットします。このワークフローは手動で開始し、プッシュごとには実行しません。

## プッシュ前のローカルチェック

`./bin/verify-all`はCIで適用される品質ゲートを実行します：

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

これだけでは不十分です。パーサー、インタープリター、組み込み機能に変更を加えた場合は、test262もサンプル実行する必要があります。すべてのプルリクエストで、CIはPHPStan、PHPCS、ユニットスイート、オラクルのリグレッション検証を実行します。プルリクエストで`src/`またはそれらのフィクスチャが変更された場合は、WPTとpopular-packageスイートも実行されます。test262の全マトリクスはプルリクエストのCIに含まれないため、影響するカテゴリをローカルで選んで実行してください。

## この方法が有効な理由

V8を正解の基準にすることで、開発中に仕様を読む必要がほぼなくなります。V8との不一致は必ずPhasisのバグを示し、仕様が曖昧だと主張できる余地はありません。修正が取り込まれると、対応するtest262テストが恒久的なリグレッションテストになります。

この手順が100 %の合格率を支えています。すべてのプルリクエストをV8と照合し、CIはオラクル、WPT、popular-packageの各スイートでリグレッションを拒否します。test262のマトリクスは、実行時に全テストスイートの結果を確認します。
