Plugins
Plugin テスト
OpenClaw Plugin のテストユーティリティ、パターン、lint 適用に関するリファレンス。
テストユーティリティ
Plugin API モックのインポート: openclaw/plugin-sdk/plugin-test-api
エージェントランタイムコントラクトのインポート: openclaw/plugin-sdk/agent-runtime-test-contracts
チャネルコントラクトのインポート: openclaw/plugin-sdk/channel-contract-testing
チャネルテストヘルパーのインポート: openclaw/plugin-sdk/channel-test-helpers
チャネルターゲットテストのインポート: openclaw/plugin-sdk/channel-target-testing
Plugin コントラクトのインポート: openclaw/plugin-sdk/plugin-test-contracts
Plugin ランタイムテストのインポート: openclaw/plugin-sdk/plugin-test-runtime
プロバイダーコントラクトのインポート: openclaw/plugin-sdk/provider-test-contracts
プロバイダー HTTP モックのインポート: openclaw/plugin-sdk/provider-http-test-mocks
環境/ネットワークテストのインポート: openclaw/plugin-sdk/test-env
汎用フィクスチャのインポート: openclaw/plugin-sdk/test-fixtures
Node 組み込みモックのインポート: openclaw/plugin-sdk/test-node-mocks
新しい Plugin テストでは、以下の焦点を絞ったサブパスを推奨します。広範な
openclaw/plugin-sdk/testing バレルは、レガシー互換性専用です。
リポジトリのガードレールは、plugin-sdk/testing と
plugin-sdk/test-utils からの新しい実インポートを拒否します。これらの名前は、外部 Plugin と互換性記録テスト向けの非推奨互換性サーフェスとしてのみ残ります。
shouldAckReaction,
removeAckReactionAfterReply,
} from "openclaw/plugin-sdk/channel-feedback";
bundledPluginRoot,
createCliRuntimeCapture,
typedCases,
} from "openclaw/plugin-sdk/test-fixtures";
利用可能なエクスポート
| エクスポート | 目的 |
|---|---|
createTestPluginApi |
直接登録のユニットテスト用に最小限の Plugin API モックを構築します。plugin-sdk/plugin-test-api からインポートします |
AUTH_PROFILE_RUNTIME_CONTRACT |
ネイティブエージェントランタイムアダプター用の共有認証プロファイル契約フィクスチャです。plugin-sdk/agent-runtime-test-contracts からインポートします |
DELIVERY_NO_REPLY_RUNTIME_CONTRACT |
ネイティブエージェントランタイムアダプター用の共有配信抑制契約フィクスチャです。plugin-sdk/agent-runtime-test-contracts からインポートします |
OUTCOME_FALLBACK_RUNTIME_CONTRACT |
ネイティブエージェントランタイムアダプター用の共有フォールバック分類契約フィクスチャです。plugin-sdk/agent-runtime-test-contracts からインポートします |
createParameterFreeTool |
ネイティブランタイム契約テスト用の動的ツールスキーマフィクスチャを構築します。plugin-sdk/agent-runtime-test-contracts からインポートします |
expectChannelInboundContextContract |
チャネル受信コンテキストの形状をアサートします。plugin-sdk/channel-contract-testing からインポートします |
installChannelOutboundPayloadContractSuite |
チャネル送信ペイロード契約ケースをインストールします。plugin-sdk/channel-contract-testing からインポートします |
createStartAccountContext |
チャネルアカウントライフサイクルコンテキストを構築します。plugin-sdk/channel-test-helpers からインポートします |
installChannelActionsContractSuite |
汎用チャネルメッセージアクション契約ケースをインストールします。plugin-sdk/channel-test-helpers からインポートします |
installChannelSetupContractSuite |
汎用チャネルセットアップ契約ケースをインストールします。plugin-sdk/channel-test-helpers からインポートします |
installChannelStatusContractSuite |
汎用チャネルステータス契約ケースをインストールします。plugin-sdk/channel-test-helpers からインポートします |
expectDirectoryIds |
ディレクトリ一覧関数から得られるチャネルディレクトリ ID をアサートします。plugin-sdk/channel-test-helpers からインポートします |
assertBundledChannelEntries |
バンドル済みチャネルエントリポイントが期待される公開契約を公開していることをアサートします。plugin-sdk/channel-test-helpers からインポートします |
formatEnvelopeTimestamp |
決定的なエンベロープタイムスタンプをフォーマットします。plugin-sdk/channel-test-helpers からインポートします |
expectPairingReplyText |
チャネルペアリング返信テキストをアサートし、そのコードを抽出します。plugin-sdk/channel-test-helpers からインポートします |
describePluginRegistrationContract |
Plugin 登録契約チェックをインストールします。plugin-sdk/plugin-test-contracts からインポートします |
registerSingleProviderPlugin |
ローダースモークテストで 1 つのプロバイダー Plugin を登録します。plugin-sdk/plugin-test-runtime からインポートします |
registerProviderPlugin |
1 つの Plugin からすべてのプロバイダー種別をキャプチャします。plugin-sdk/plugin-test-runtime からインポートします |
registerProviderPlugins |
複数の Plugin にまたがるプロバイダー登録をキャプチャします。plugin-sdk/plugin-test-runtime からインポートします |
requireRegisteredProvider |
プロバイダーコレクションに ID が含まれることをアサートします。plugin-sdk/plugin-test-runtime からインポートします |
createRuntimeEnv |
モック化された CLI/Plugin ランタイム環境を構築します。plugin-sdk/plugin-test-runtime からインポートします |
createPluginSetupWizardStatus |
チャネル Plugin 用のセットアップステータスヘルパーを構築します。plugin-sdk/plugin-test-runtime からインポートします |
describeOpenAIProviderRuntimeContract |
プロバイダーファミリーのランタイム契約チェックをインストールします。plugin-sdk/provider-test-contracts からインポートします |
expectPassthroughReplayPolicy |
プロバイダーのリプレイポリシーがプロバイダー所有のツールとメタデータをそのまま通すことをアサートします。plugin-sdk/provider-test-contracts からインポートします |
runRealtimeSttLiveTest |
共有音声フィクスチャでライブのリアルタイム STT プロバイダーテストを実行します。plugin-sdk/provider-test-contracts からインポートします |
normalizeTranscriptForMatch |
ファジーアサーションの前にライブ文字起こし出力を正規化します。plugin-sdk/provider-test-contracts からインポートします |
expectExplicitVideoGenerationCapabilities |
動画プロバイダーが明示的な生成モード機能を宣言していることをアサートします。plugin-sdk/provider-test-contracts からインポートします |
expectExplicitMusicGenerationCapabilities |
音楽プロバイダーが明示的な生成/編集機能を宣言していることをアサートします。plugin-sdk/provider-test-contracts からインポートします |
mockSuccessfulDashscopeVideoTask |
成功した DashScope 互換の動画タスクレスポンスをインストールします。plugin-sdk/provider-test-contracts からインポートします |
getProviderHttpMocks |
オプトインのプロバイダー HTTP/認証 Vitest モックにアクセスします。plugin-sdk/provider-http-test-mocks からインポートします |
installProviderHttpMockCleanup |
各テスト後にプロバイダー HTTP/認証モックをリセットします。plugin-sdk/provider-http-test-mocks からインポートします |
installCommonResolveTargetErrorCases |
ターゲット解決エラー処理の共有テストケースです。plugin-sdk/channel-target-testing からインポートします |
shouldAckReaction |
チャネルが確認リアクションを追加すべきかどうかを確認します。plugin-sdk/channel-feedback からインポートします |
removeAckReactionAfterReply |
返信配信後に確認リアクションを削除します。plugin-sdk/channel-feedback からインポートします |
createTestRegistry |
チャネル Plugin レジストリフィクスチャを構築します。plugin-sdk/plugin-test-runtime または plugin-sdk/channel-test-helpers からインポートします |
createEmptyPluginRegistry |
空の Plugin レジストリフィクスチャを構築します。plugin-sdk/plugin-test-runtime または plugin-sdk/channel-test-helpers からインポートします |
setActivePluginRegistry |
Plugin ランタイムテスト用のレジストリフィクスチャをインストールします。plugin-sdk/plugin-test-runtime または plugin-sdk/channel-test-helpers からインポートします |
createRequestCaptureJsonFetch |
メディアヘルパーテストで JSON fetch リクエストをキャプチャします。plugin-sdk/test-env からインポートします |
withServer |
破棄可能なローカル HTTP サーバーに対してテストを実行します。plugin-sdk/test-env からインポートします |
createMockIncomingRequest |
最小限の受信 HTTP リクエストオブジェクトを構築します。plugin-sdk/test-env からインポートします |
withFetchPreconnect |
プリコネクトフックをインストールした状態で fetch テストを実行します。plugin-sdk/test-env からインポートします |
withEnv / withEnvAsync |
環境変数を一時的にパッチします。plugin-sdk/test-env からインポートします |
createTempHomeEnv / withTempHome / withTempDir |
分離されたファイルシステムテストフィクスチャを作成します。plugin-sdk/test-env からインポートします |
createMockServerResponse |
最小限の HTTP サーバーレスポンスモックを作成します。plugin-sdk/test-env からインポートします |
createCliRuntimeCapture |
テストで CLI ランタイム出力をキャプチャします。plugin-sdk/test-fixtures からインポートします |
importFreshModule |
モジュールキャッシュをバイパスするため、新しいクエリトークンで ESM モジュールをインポートします。plugin-sdk/test-fixtures からインポートします |
bundledPluginRoot / bundledPluginFile |
バンドル済み Plugin のソースまたは dist フィクスチャパスを解決します。plugin-sdk/test-fixtures からインポートします |
mockNodeBuiltinModule |
狭い範囲の Node 組み込み Vitest モックをインストールします。plugin-sdk/test-node-mocks からインポートします |
createSandboxTestContext |
サンドボックステストコンテキストを構築します。plugin-sdk/test-fixtures からインポートします |
writeSkill |
Skills フィクスチャを書き込みます。plugin-sdk/test-fixtures からインポートします |
makeAgentAssistantMessage |
エージェントトランスクリプトメッセージフィクスチャを構築します。plugin-sdk/test-fixtures からインポートします |
peekSystemEvents / resetSystemEventsForTest |
システムイベントフィクスチャを検査およびリセットします。plugin-sdk/test-fixtures からインポートします |
sanitizeTerminalText |
アサーション用にターミナル出力をサニタイズします。plugin-sdk/test-fixtures からインポートします |
countLines / hasBalancedFences |
チャンク化出力の形状をアサートします。plugin-sdk/test-fixtures からインポートします |
runProviderCatalog |
テスト依存関係を使ってプロバイダーカタログフックを実行します |
resolveProviderWizardOptions |
契約テストでプロバイダーセットアップウィザードの選択肢を解決します |
resolveProviderModelPickerEntries |
契約テストでプロバイダーモデルピッカーエントリを解決します |
buildProviderPluginMethodChoice |
アサーション用にプロバイダーウィザード選択 ID を構築します |
setProviderWizardProvidersResolverForTest |
分離テスト用にプロバイダーウィザードプロバイダーを注入します |
createProviderUsageFetch |
プロバイダー使用状況取得フィクスチャを構築 |
useFrozenTime / useRealTime |
時間依存のテスト用にタイマーを固定し、復元します。plugin-sdk/test-env からインポートします |
createTestWizardPrompter |
モック化されたセットアップウィザードプロンプターを構築 |
createRuntimeTaskFlow |
分離されたランタイムのタスクフロー状態を作成 |
typedCases |
テーブル駆動テスト用にリテラル型を保持します。plugin-sdk/test-fixtures からインポートします |
バンドル Plugin のコントラクトスイートでも、テスト専用の
registry、manifest、public-artifact、runtime fixture ヘルパー向けに SDK testing サブパスを使用します。バンドルされた OpenClaw インベントリに依存する core-only
スイートは src/plugins/contracts 配下に残します。
新しい拡張テストでは、広範な plugin-sdk/testing 互換 barrel、repo の src/** ファイル、または repo の
test/helpers/* ブリッジを直接インポートするのではなく、
plugin-sdk/plugin-test-api、plugin-sdk/channel-contract-testing、
plugin-sdk/agent-runtime-test-contracts、plugin-sdk/channel-test-helpers、
plugin-sdk/plugin-test-contracts、plugin-sdk/plugin-test-runtime、
plugin-sdk/provider-test-contracts、plugin-sdk/provider-http-test-mocks、
plugin-sdk/test-env、または plugin-sdk/test-fixtures など、ドキュメント化された焦点の絞られた SDK サブパスを使用してください。
型
焦点の絞られた testing サブパスは、テストファイルで役立つ型も再エクスポートします。
ChannelAccountSnapshot,
ChannelGatewayContext,
} from "openclaw/plugin-sdk/channel-contract";
テスト対象の解決
channel ターゲット解決に標準エラーケースを追加するには、
installCommonResolveTargetErrorCases を使用します。
describe("my-channel target resolution", () => {
installCommonResolveTargetErrorCases({
resolveTarget: ({ to, mode, allowFrom }) => {
// Your channel's target resolution logic
return myChannelResolveTarget({ to, mode, allowFrom });
},
implicitAllowFrom: ["user1", "user2"],
});
// Add channel-specific test cases
it("should resolve @username targets", () => {
// ...
});
});
テストパターン
registration コントラクトのテスト
手書きの api モックを register(api) に渡す単体テストでは、
OpenClaw の loader 受け入れゲートは実行されません。Plugin が依存する各 registration サーフェス、特に hook や memory などの排他的な capability について、loader-backed の smoke test を少なくとも 1 つ追加してください。
実際の loader は、必須メタデータが欠落している場合や、Plugin が所有していない capability API を呼び出した場合に Plugin registration を失敗させます。たとえば、
api.registerHook(...) には hook 名が必要であり、
api.registerMemoryCapability(...) には Plugin manifest またはエクスポートされた entry が
kind: "memory" を宣言している必要があります。
runtime config アクセスのテスト
バンドルされた channel Plugin をテストする場合は、openclaw/plugin-sdk/channel-test-helpers
の共有 Plugin runtime モックを優先してください。非推奨の runtime.config.loadConfig() と
runtime.config.writeConfigFile(...) モックはデフォルトで throw するため、テストで互換 API の新しい使用を検出できます。これらのモックを上書きするのは、テストが legacy 互換動作を明示的に扱っている場合のみにしてください。
channel Plugin の単体テスト
describe("my-channel plugin", () => {
it("should resolve account from config", () => {
const cfg = {
channels: {
"my-channel": {
token: "test-token",
allowFrom: ["user1"],
},
},
};
const account = myPlugin.setup.resolveAccount(cfg, undefined);
expect(account.token).toBe("test-token");
});
it("should inspect account without materializing secrets", () => {
const cfg = {
channels: {
"my-channel": { token: "test-token" },
},
};
const inspection = myPlugin.setup.inspectAccount(cfg, undefined);
expect(inspection.configured).toBe(true);
expect(inspection.tokenStatus).toBe("available");
// No token value exposed
expect(inspection).not.toHaveProperty("token");
});
});
provider Plugin の単体テスト
describe("my-provider plugin", () => {
it("should resolve dynamic models", () => {
const model = myProvider.resolveDynamicModel({
modelId: "custom-model-v2",
// ... context
});
expect(model.id).toBe("custom-model-v2");
expect(model.provider).toBe("my-provider");
expect(model.api).toBe("openai-completions");
});
it("should return catalog when API key is available", async () => {
const result = await myProvider.catalog.run({
resolveProviderApiKey: () => ({ apiKey: "test-key" }),
// ... context
});
expect(result?.provider?.models).toHaveLength(2);
});
});
Plugin runtime のモック
createPluginRuntimeStore を使用するコードでは、テスト内で runtime をモックします。
const store = createPluginRuntimeStore<PluginRuntime>({
pluginId: "test-plugin",
errorMessage: "test runtime not set",
});
// In test setup
const mockRuntime = {
agent: {
resolveAgentDir: vi.fn().mockReturnValue("/tmp/agent"),
// ... other mocks
},
config: {
current: vi.fn(() => ({}) as const),
mutateConfigFile: vi.fn(),
replaceConfigFile: vi.fn(),
},
// ... other namespaces
} as unknown as PluginRuntime;
store.setRuntime(mockRuntime);
// After tests
store.clearRuntime();
インスタンスごとの stub を使ったテスト
prototype mutation よりもインスタンスごとの stub を優先してください。
// Preferred: per-instance stub
const client = new MyChannelClient();
client.sendMessage = vi.fn().mockResolvedValue({ id: "msg-1" });
// Avoid: prototype mutation
// MyChannelClient.prototype.sendMessage = vi.fn();
コントラクトテスト(repo 内 Plugin)
バンドル Plugin には、registration ownership を検証するコントラクトテストがあります。
pnpm test -- src/plugins/contracts/
これらのテストは次を assert します。
- どの Plugin がどの provider を登録するか
- どの Plugin がどの speech provider を登録するか
- registration 形状の正しさ
- runtime コントラクトへの準拠
scoped test の実行
特定の Plugin の場合:
pnpm test -- <bundled-plugin-root>/my-channel/
コントラクトテストのみの場合:
pnpm test -- src/plugins/contracts/shape.contract.test.ts
pnpm test -- src/plugins/contracts/auth-choice.contract.test.ts
pnpm test -- src/plugins/contracts/runtime-seams.contract.test.ts
lint 適用(repo 内 Plugin)
repo 内 Plugin に対して、pnpm check により 3 つのルールが適用されます。
- monolithic root import なし --
openclaw/plugin-sdkroot barrel は拒否されます - 直接の
src/import なし -- Plugin は../../src/を直接 import できません - self-import なし -- Plugin は自身の
plugin-sdk/<name>サブパスを import できません
外部 Plugin にはこれらの lint ルールは適用されませんが、同じパターンに従うことを推奨します。
テスト設定
OpenClaw は V8 coverage しきい値付きで Vitest を使用します。Plugin テストの場合:
# Run all tests
pnpm test
# Run specific plugin tests
pnpm test -- <bundled-plugin-root>/my-channel/src/channel.test.ts
# Run with a specific test name filter
pnpm test -- <bundled-plugin-root>/my-channel/ -t "resolves account"
# Run with coverage
pnpm test:coverage
ローカル実行でメモリ圧迫が発生する場合:
OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test
関連
- SDK の概要 -- import 規約
- SDK channel Plugin -- channel Plugin インターフェイス
- SDK provider Plugin -- provider Plugin hook
- Plugin の構築 -- はじめにガイド