Plugin SDK reference
外掛測試
OpenClaw 外掛的測試公用程式、模式與 lint 強制規則參考。
測試公用程式
這些子路徑是 OpenClaw 自有內建外掛測試在存放庫本機使用的原始碼進入點。它們並非為第三方外掛發布的 package.json 匯出,且可能會匯入 Vitest 或其他僅限存放庫使用的測試相依套件。
shouldAckReaction, removeAckReactionAfterReply,} from "openclaw/plugin-sdk/channel-feedback"; bundledPluginRoot, createCliRuntimeCapture, typedCases,} from "openclaw/plugin-sdk/test-fixtures"; 內建外掛測試請使用這些聚焦的子路徑。先前的 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 |
建立最小化的外掛 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-sdk/plugin-test-contracts 匯入 |
registerSingleProviderPlugin |
在載入器冒煙測試中註冊一個供應商外掛。從 plugin-sdk/plugin-test-runtime 匯入 |
registerProviderPlugin |
從一個外掛擷取所有供應商種類。從 plugin-sdk/plugin-test-runtime 匯入 |
registerProviderPlugins |
擷取多個外掛的供應商註冊項目。從 plugin-sdk/plugin-test-runtime 匯入 |
requireRegisteredProvider |
斷言供應商集合包含某個 ID。從 plugin-sdk/plugin-test-runtime 匯入 |
createRuntimeEnv |
建立模擬的命令列介面/外掛執行階段環境。從 plugin-sdk/plugin-test-runtime 匯入 |
createPluginRuntimeMock |
建立模擬的外掛執行階段介面。從 plugin-sdk/plugin-test-runtime 匯入 |
createPluginSetupWizardStatus |
為頻道外掛建立設定狀態輔助工具。從 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-sdk/plugin-test-runtime 或 plugin-sdk/channel-test-helpers 匯入 |
createEmptyPluginRegistry |
建立空的外掛登錄測試資料。從 plugin-sdk/plugin-test-runtime 或 plugin-sdk/channel-test-helpers 匯入 |
setActivePluginRegistry |
為外掛執行階段測試安裝登錄測試資料。從 plugin-sdk/plugin-test-runtime 或 plugin-sdk/channel-test-helpers 匯入 |
createRequestCaptureJsonFetch |
在媒體輔助工具測試中擷取 JSON fetch 請求。從 plugin-sdk/test-media-understanding 匯入 |
isLiveTestEnabled |
控制選擇啟用的實機供應商測試。從 plugin-sdk/test-live 匯入 |
collectProviderApiKeys |
探索實機供應商測試的認證資訊。從 plugin-sdk/test-live-auth 匯入 |
parseProviderModelMap |
剖析音樂/影片實機測試的模型覆寫值。從 plugin-sdk/test-media-generation 匯入 |
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 匯入 |
createProviderUsageFetch |
建立供應商用量 fetch 測試資料。從 plugin-sdk/test-env 匯入 |
useFrozenTime / useRealTime |
凍結並還原計時器,用於時間敏感的測試。從 plugin-sdk/test-env 匯入 |
createCliRuntimeCapture |
在測試中擷取命令列介面執行階段輸出。從 plugin-sdk/test-fixtures 匯入 |
importFreshModule |
使用新的查詢權杖匯入 ESM 模組,以略過模組快取。從 plugin-sdk/test-fixtures 匯入 |
bundledPluginRoot / bundledPluginFile |
解析隨附外掛的原始碼或 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 匯入 |
內建外掛的合約測試套件也會使用這些 SDK 測試子路徑,取得僅供測試使用的登錄檔、資訊清單、公開成品與執行階段固定資料輔助工具。
依賴內建 OpenClaw 清單的僅限核心測試套件則仍放在
src/plugins/contracts 下。
型別
聚焦測試的子路徑也會重新匯出測試檔案中實用的型別:
ChannelAccountSnapshot, ChannelGatewayContext,} from "openclaw/plugin-sdk/channel-contract"; 測試目標解析
使用 installCommonResolveTargetErrorCases 為頻道目標解析新增標準錯誤案例:
describe("my-channel 目標解析", () => { installCommonResolveTargetErrorCases({ resolveTarget: ({ to, mode, allowFrom }) => { // 你的頻道目標解析邏輯 return myChannelResolveTarget({ to, mode, allowFrom }); }, implicitAllowFrom: ["user1", "user2"], }); // 新增頻道特定的測試案例 it("應解析 @username 目標", () => { // ... });});測試模式
測試註冊合約
將手寫的 api 模擬物件傳給 register(api) 的單元測試,不會
執行 OpenClaw 的載入器接受閘門。你的外掛所依賴的每個註冊介面都應至少新增一個由載入器支援的
冒煙測試,尤其是鉤子與記憶等專屬功能。
若缺少必要的中繼資料,或外掛呼叫不屬於自己的功能 API,真正的載入器會使外掛註冊失敗。例如,
api.registerHook(...) 需要鉤子名稱,而
api.registerMemoryCapability(...) 要求外掛資訊清單或匯出的
進入點宣告 kind: "memory"。
測試執行階段設定存取
優先使用
openclaw/plugin-sdk/plugin-test-runtime 的共用外掛執行階段模擬物件。其執行階段設定輔助工具會模擬
目前的快照與變更 API。
對頻道外掛進行單元測試
describe("my-channel 外掛", () => { it("應從設定解析帳號", () => { const cfg = { channels: { "my-channel": { token: "test-token", allowFrom: ["user1"], }, }, }; const account = myPlugin.setup.resolveAccount(cfg, undefined); expect(account.token).toBe("test-token"); }); it("應檢查帳號而不具現化機密", () => { 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"); });});對供應商外掛進行單元測試
describe("my-provider 外掛", () => { it("應解析動態模型", () => { 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("當 API 金鑰可用時應傳回目錄", async () => { const result = await myProvider.catalog.run({ resolveProviderApiKey: () => ({ apiKey: "test-key" }), // ... 情境 }); expect(result?.provider?.models).toHaveLength(2); });});模擬外掛執行階段
對於使用 createPluginRuntimeStore 的程式碼,請在測試中模擬執行階段:
const store = createPluginRuntimeStore<PluginRuntime>({ pluginId: "test-plugin", errorMessage: "測試執行階段尚未設定",}); // 在測試設定中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();合約測試(存放於儲存庫內的外掛)
內建外掛具有驗證註冊所有權的合約測試:
pnpm test src/plugins/contracts/這些測試會斷言:
- 哪些外掛註冊哪些供應商
- 哪些外掛註冊哪些語音供應商
- 註冊形式的正確性
- 執行階段合約遵循情況
執行限定範圍的測試
針對特定外掛:
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 強制檢查(存放於儲存庫內的外掛)
scripts/run-additional-boundary-checks.mjs 會在 CI 中執行一組 lint:plugins:*
匯入邊界檢查;每項檢查也可以在本機獨立執行:
| 命令 | 強制規則 |
|---|---|
pnpm run lint:plugins:no-monolithic-plugin-sdk-entry-imports |
內建外掛不得匯入單體式的 openclaw/plugin-sdk 根彙總模組。 |
pnpm run lint:plugins:no-extension-src-imports |
正式環境的擴充功能檔案不得直接匯入儲存庫的 src/** 樹狀結構(../../src/...)。 |
pnpm run lint:plugins:no-extension-test-core-imports |
擴充功能測試檔案不得匯入已移除的 SDK 測試別名或其他僅限核心使用的測試輔助工具。 |
外部外掛不受這些 lint 規則約束,但建議遵循相同的 模式。
測試設定
OpenClaw 使用 Vitest 4,並提供資訊用途的 V8 覆蓋率報告。針對外掛測試:
# 執行所有測試pnpm test # 執行特定外掛測試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