オラクルテスト
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つ実行するには:
./bin/test-scenario operators/arithmetic
すべてのシナリオ、特定のカテゴリだけ、または並列で実行できます:
./bin/test-regression
./bin/test-regression --jobs 4
./bin/test-regression --category expressions
オラクルを更新するには(e.g。Node.jsのバージョン更新後):
./bin/oracle --refresh operators/arithmetic
シナリオはECMAScriptの章に沿って整理されています。リテラル、演算子、変数、制御フロー、関数、オブジェクト、配列、クラス、組み込み機能、エラー、相互運用、エッジケースです。
レベル2 — test262
TC39の公式適合性テストスイートは、test262/のgitサブモジュールとしてチェックアウトされます。各テストは自己検証型です。例外が発生しなければ合格し、発生すれば失敗します(negativeテストでは逆になります)。各テストの前に、ハーネスがassert.jsとsta.jsを読み込みます。
./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にあり、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のマトリクスは、実行時に全テストスイートの結果を確認します。