Keiko
稽古(Keiko):practice。 Web ゲームのための、速くて決定的なテストです。
Keiko はあなたの本物のゲームを Node 上で動かします。ブラウザは使わず、何も描画しません。時間・入力・乱数はテストが指示したときだけ進むので、何度実行しても同じ展開になり、一般的なテストは数十ミリ秒で終わります。
import { expect, play, test } from "keiko";
test("the player reaches top speed within a quarter second", async () => {
const game = await play();
game.press("ArrowRight");
expect(game.until((s) => s.player.vx >= 140)).toBeAtMost(15);
});はじめる · エンジン別レシピ · API リファレンス
なぜ Keiko なのか
ゲームのバグの多くは時間の経過に伴う振る舞いにまつわるものです。ジャンプが前より少し低い、敵の振り向きが 1 フレーム遅い、高速のダッシュが壁をすり抜ける、2 回プレイすると展開が違う。ブラウザ自動化はリアルタイムで動き、ゲームをステップ実行できないので、こうした疑問にうまく答えられません。ユニットテストも同じです。テストするのは関数であって、ゲームそのものではないからです。
Keiko はゲームそのものを 1 フレームずつプレイし、ゲームらしい問いを投げかけられるようにします。
- あとどれくらいで?
game.until((s) => s.player.onGround)はかかったステップ数を返します。 - 一度も起きない?
game.during("3s", (s) => s.player.x >= 0)は不変条件が破れたまさにそのステップで失敗します。 - どれくらい高く、どれくらい速く?
game.trace("player.y", "1s").min()で動きを測れます。 - 出荷するかもしれないすべての値で?
test.sweep(…, { "player.jumpSpeed": [260, 290, 320] }, …)。 - 毎回同じ?
test.deterministic(…)は異なるシードで 2 回プレイし、全ステップを比較します。
失敗したときは、その瞬間のゲームを見せてくれます。tick、シーン、ステート、テストの該当行、そしてコンソールです。
どんなエンジンでも
Keiko はエンジンの API ではなく Web プラットフォームを通して動きます。ゲームはヘッドレスなページで動き、requestAnimationFrame、タイマー、時計は仮想化され、入力は本物の DOM イベントとして届き、Canvas 2D と WebGL はあらゆる呼び出しを受け付けます。動作確認済みのエンジンは次のとおりです。
| エンジン | キーボード | ポインター | 決定的 |
|---|---|---|---|
| debuff | ✔ | ✔ | ✔ |
| Phaser 4 | ✔ | ✔ | ✔ |
| PixiJS 8 | ✔ | ✔ | ✔ |
| KAPLAY | ✔ | ✔ | ✔ |
| Excalibur | ✔ | ✔ | ✔ |
| three.js | ✔ | ✔ | ✔ |
| 手書きのループ | ✔ | ✔ | ✔ |
ゲームのステートを読むには、開発ビルドでスナップショットを公開します。ほとんどのゲームで必要な変更はこれだけです。
if (import.meta.env.DEV) window.__KEIKO__ = { state: () => ({ player: { x: player.x, y: player.y }, score }) };エージェントのためにも
Keiko の結果は構造化されています。npx keiko --json はすべての失敗を、メッセージ、ソースの行、ゲームのステートとともに報告します。コーディングエージェントは、テストを書いて失敗を確かめ、ゲームを直して直ったことを証明するまでを、ブラウザなしでこなせます。debuff プロジェクトでは、MCP サーバーの run_tests ツールから直接実行できます。
守備範囲
Keiko が扱うのはゲームが何をするかです。ピクセルは見ませんし、音も聞きません。そちらは debuff のシナリオのような、本物のブラウザでのスクリーンショットテストを使ってください。ほとんどのプロジェクトでは両方あるのが理想です。高速なロジックテストをたくさん、見た目のチェックを少し。
Keiko は MIT ライセンスで、debuff リポジトリで開発されています。