Plugin SDK reference
Plugin のテスト
OpenClaw Plugin向けのテストユーティリティ、パターン、lint適用に関するリファレンスです。
テストユーティリティ
これらのサブパスは、OpenClaw独自のバンドル済みPluginテスト向けの、リポジトリローカルなソースエントリポイントです。サードパーティPlugin向けに公開されたpackage.jsonのエクスポートではなく、Vitestやその他のリポジトリ専用テスト依存関係をインポートする場合があります。
shouldAckReaction, removeAckReactionAfterReply,} from "openclaw/plugin-sdk/channel-feedback"; bundledPluginRoot, createCliRuntimeCapture, typedCases,} from "openclaw/plugin-sdk/test-fixtures"; 新しいバンドル済みPluginのテストでは、これらの目的別サブパスを優先してください。広範なopenclaw/plugin-sdk/testingバレルとopenclaw/plugin-sdk/test-utilsエイリアスは、レガシー互換性専用です。pnpm run lint:plugins:no-extension-test-core-imports(scripts/check-no-extension-test-core-imports.ts)は、拡張機能のテストファイルからこれらのいずれかを新たにインポートすることを拒否し、どちらも互換性記録テストのためだけに残されています。
利用可能なエクスポート
| エクスポート | 目的 |
|---|---|
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からインポートします |
createPluginRuntimeMock |
モック化されたPluginランタイムサーフェスを構築します。plugin-sdk/plugin-test-runtimeからインポートします |
createPluginSetupWizardStatus |
チャネルPlugin用のセットアップステータスヘルパーを構築します。plugin-sdk/plugin-test-runtimeからインポートします |
createTestWizardPrompter |
モック化されたセットアップウィザードのプロンプターを構築します。plugin-sdk/plugin-test-runtimeからインポートします |
createRuntimeTaskFlow |
分離されたランタイムTaskFlow状態を作成します。plugin-sdk/plugin-test-runtimeからインポートします |
runProviderCatalog |
テスト依存関係を使用してプロバイダーカタログフックを実行します。plugin-sdk/plugin-test-runtimeからインポートします |
resolveProviderWizardOptions |
契約テストでプロバイダーセットアップウィザードの選択肢を解決します。plugin-sdk/plugin-test-runtimeからインポートします |
resolveProviderModelPickerEntries |
契約テストでプロバイダーのモデル選択項目を解決します。plugin-sdk/plugin-test-runtimeからインポートします |
buildProviderPluginMethodChoice |
アサーション用にプロバイダーウィザードの選択肢IDを構築します。plugin-sdk/plugin-test-runtimeからインポートします |
setProviderWizardProvidersResolverForTest |
分離テスト用にプロバイダーウィザードのプロバイダーを注入します。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 |
preconnectフックを導入した状態でfetchテストを実行します。plugin-sdk/test-envからインポートします |
withEnv / withEnvAsync |
環境変数を一時的に変更します。plugin-sdk/test-envからインポートします |
createTempHomeEnv / withTempHome / withTempDir |
分離されたファイルシステムテストフィクスチャを作成します。plugin-sdk/test-envからインポートします |
createMockServerResponse |
最小限のHTTPサーバーレスポンスモックを作成します。plugin-sdk/test-envからインポートします |
createProviderUsageFetch |
プロバイダー使用量のfetchフィクスチャを構築します。plugin-sdk/test-envからインポートします |
useFrozenTime / useRealTime |
時間依存テスト用にタイマーを固定し、元に戻します。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 からインポートします |
typedCases |
テーブル駆動テスト用にリテラル型を保持します。plugin-sdk/test-fixtures からインポートします |
バンドル済みPluginのコントラクトスイートでも、テスト専用のレジストリ、マニフェスト、公開アーティファクト、ランタイムフィクスチャのヘルパーとして、これらのSDKテスト用サブパスを使用します。
一方、バンドル済みOpenClawインベントリに依存するコア専用スイートは、引き続き
src/plugins/contracts に配置します。
型
特定用途向けのテスト用サブパスでは、テストファイルで役立つ型も再エクスポートされます。
ChannelAccountSnapshot, ChannelGatewayContext,} from "openclaw/plugin-sdk/channel-contract"; テスト対象の解決
チャンネルの対象解決に標準的なエラーケースを追加するには、installCommonResolveTargetErrorCases を使用します。
describe("my-channel target resolution", () => { installCommonResolveTargetErrorCases({ resolveTarget: ({ to, mode, allowFrom }) => { // チャンネル固有の対象解決ロジック return myChannelResolveTarget({ to, mode, allowFrom }); }, implicitAllowFrom: ["user1", "user2"], }); // チャンネル固有のテストケースを追加 it("should resolve @username targets", () => { // ... });});テストパターン
登録コントラクトのテスト
手書きの api モックを register(api) に渡すユニットテストでは、OpenClawのローダー受け入れゲートを検証できません。Pluginが依存する各登録サーフェスに対して、ローダー経由のスモークテストを少なくとも1つ追加してください。特に、フックやメモリなどの排他的な機能では重要です。
必要なメタデータが欠けている場合や、Pluginが所有していない機能APIを呼び出した場合、実際のローダーではPluginの登録に失敗します。たとえば、
api.registerHook(...) にはフック名が必要であり、
api.registerMemoryCapability(...) には、Pluginマニフェストまたはエクスポートされたエントリで kind: "memory" を宣言する必要があります。
ランタイム設定アクセスのテスト
openclaw/plugin-sdk/plugin-test-runtime の共有Pluginランタイムモックを推奨します。
その runtime.config.loadConfig() および runtime.config.writeConfigFile(...)
のモックはデフォルトで例外をスローするため、非推奨の互換性APIが新たに使用されるとテストで検出できます。テストがレガシー互換動作を明示的に検証する場合にのみ、これらのモックをオーバーライドしてください。
チャンネル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"); // トークン値は公開されない expect(inspection).not.toHaveProperty("token"); });});プロバイダーPluginのユニットテスト
describe("my-provider plugin", () => { it("should resolve dynamic models", () => { const model = myProvider.resolveDynamicModel({ modelId: "custom-model-v2", // ... コンテキスト }); 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" }), // ... コンテキスト }); expect(result?.provider?.models).toHaveLength(2); });});Pluginランタイムのモック
createPluginRuntimeStore を使用するコードでは、テスト内でランタイムをモックします。
const store = createPluginRuntimeStore<PluginRuntime>({ pluginId: "test-plugin", errorMessage: "test runtime not set",}); // テストのセットアップ内const mockRuntime = { agent: { resolveAgentDir: vi.fn().mockReturnValue("/tmp/agent"), // ... その他のモック }, config: { current: vi.fn(() => ({}) as const), mutateConfigFile: vi.fn(), replaceConfigFile: vi.fn(), }, // ... その他の名前空間} as unknown as PluginRuntime; store.setRuntime(mockRuntime); // テスト後store.clearRuntime();インスタンス単位のスタブを使用したテスト
プロトタイプの変更よりも、インスタンス単位のスタブを推奨します。
// 推奨: インスタンス単位のスタブconst client = new MyChannelClient();client.sendMessage = vi.fn().mockResolvedValue({ id: "msg-1" }); // 非推奨: プロトタイプの変更// MyChannelClient.prototype.sendMessage = vi.fn();コントラクトテスト(リポジトリ内Plugin)
バンドル済みPluginには、登録の所有権を検証するコントラクトテストがあります。
pnpm test src/plugins/contracts/これらのテストでは、次の項目を検証します。
- どのPluginがどのプロバイダーを登録するか
- どのPluginがどの音声プロバイダーを登録するか
- 登録形式の正しさ
- ランタイムコントラクトへの準拠
スコープを限定したテストの実行
特定のPluginの場合:
pnpm test <bundled-plugin-root>/my-channel/コントラクトテストのみの場合:
pnpm test src/plugins/contracts/shape.contract.test.tspnpm test src/plugins/contracts/auth-choice.contract.test.tspnpm test src/plugins/contracts/runtime-seams.contract.test.tslintによる適用(リポジトリ内Plugin)
scripts/run-additional-boundary-checks.mjs は、CIで一連の lint:plugins:*
インポート境界チェックを実行します。各チェックはローカルでも単独で実行できます。
| コマンド | 適用内容 |
|---|---|
pnpm run lint:plugins:no-monolithic-plugin-sdk-entry-imports |
バンドル済みPluginは、モノリシックな openclaw/plugin-sdk ルートバレルをインポートできません。 |
pnpm run lint:plugins:no-extension-src-imports |
本番用拡張ファイルは、リポジトリの src/** ツリーを直接インポートできません(../../src/...)。 |
pnpm run lint:plugins:no-extension-test-core-imports |
拡張のテストファイルは、openclaw/plugin-sdk/testing、plugin-sdk/test-utils、その他のコア専用テストヘルパーをインポートできません。 |
外部Pluginにはこれらのlintルールは適用されませんが、同じパターンに従うことを推奨します。
テスト設定
OpenClawは、参考情報としてV8カバレッジを報告するVitest 4を使用します。Pluginのテストでは、次のコマンドを使用します。
# すべてのテストを実行pnpm test # 特定のPluginテストを実行pnpm test <bundled-plugin-root>/my-channel/src/channel.test.ts # 特定のテスト名フィルターを指定して実行pnpm test <bundled-plugin-root>/my-channel/ -t "resolves account" # カバレッジ付きで実行pnpm test:coverageローカル実行によってメモリ負荷が高くなる場合:
OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test関連項目
- SDKの概要 -- インポート規約
- SDKチャンネルPlugin -- チャンネルPluginインターフェース
- SDKプロバイダーPlugin -- プロバイダーPluginフック
- Pluginの構築 -- はじめにガイド