Plugin testing
기준일: 2026-07-26
공식 기준: Plugin testing
Plugin testing 문서는 OpenClaw 공식 문서(plugins/sdk-testing)를 한국어로 정리한 가이드입니다. Testing utilities and patterns for OpenClaw plugins 명령·설정 키·코드 예시는 공식 문서를 그대로 보존하며, 해석과 절차 안내는 한국어로 제공합니다. 최종 동작은 설치된 CLI 버전과 공식 원문을 확인하세요.
핵심 요약
Testing utilities and patterns for OpenClaw plugins
한국어 가이드 범위: plugins/sdk-testing 경로의 설정·명령·제약·예시를 학습용으로 재구성합니다.
문서 구성
공식 문서의 주요 섹션은 다음과 같습니다.
- Test utilities
- Available exports
- Types
- Testing target resolution
- Testing patterns
- Testing registration contracts
- Testing runtime config access
- Unit testing a channel plugin
- Unit testing a provider plugin
- Mocking the plugin runtime
- Testing with per-instance stubs
- Contract tests (in-repo plugins)
- Running scoped tests
- Lint enforcement (in-repo plugins)
- Test configuration
- Run all tests
- Run specific plugin tests
- Run with a specific test name filter
- Run with coverage
- 관련 문서
상세 내용
본문
Reference for test utilities, patterns, and lint enforcement for OpenClaw plugins.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Test utilities
These subpaths are repo-local source entrypoints for OpenClaw's own bundled plugin tests. They are not published package.json exports for third-party plugins, and they may import Vitest or other repo-only test dependencies.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
shouldAckReaction,
removeAckReactionAfterReply,
} from "openclaw/plugin-sdk/channel-feedback";
bundledPluginRoot,
createCliRuntimeCapture,
typedCases,
} from "openclaw/plugin-sdk/test-fixtures";
Available exports
Bundled-plugin contract suites also use these SDK testing subpaths for test-only registry, manifest, public-artifact, and runtime fixture helpers. Core-only suites that depend on bundled OpenClaw inventory stay under src/plugins/contracts instead.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
| Export | Purpose |
|---|---|
createTestPluginApi |
Build a minimal plugin API mock for direct registration unit tests. Import from plugin-sdk/plugin-test-api |
AUTH_PROFILE_RUNTIME_CONTRACT |
Shared auth-profile contract fixture for native agent runtime adapters. Import from plugin-sdk/agent-runtime-test-contracts |
DELIVERY_NO_REPLY_RUNTIME_CONTRACT |
Shared delivery suppression contract fixture for native agent runtime adapters. Import from plugin-sdk/agent-runtime-test-contracts |
OUTCOME_FALLBACK_RUNTIME_CONTRACT |
Shared fallback-classification contract fixture for native agent runtime adapters. Import from plugin-sdk/agent-runtime-test-contracts |
createParameterFreeTool |
Build dynamic-tool schema fixtures for native runtime contract tests. Import from plugin-sdk/agent-runtime-test-contracts |
expectChannelInboundContextContract |
Assert channel inbound context shape. Import from plugin-sdk/channel-contract-testing |
installChannelOutboundPayloadContractSuite |
Install channel outbound payload contract cases. Import from plugin-sdk/channel-contract-testing |
createStartAccountContext |
Build channel account lifecycle contexts. Import from plugin-sdk/channel-test-helpers |
installChannelActionsContractSuite |
Install generic channel message-action contract cases. Import from plugin-sdk/channel-test-helpers |
installChannelSetupContractSuite |
Install generic channel setup contract cases. Import from plugin-sdk/channel-test-helpers |
installChannelStatusContractSuite |
Install generic channel status contract cases. Import from plugin-sdk/channel-test-helpers |
expectDirectoryIds |
Assert channel directory ids from a directory-list function. Import from plugin-sdk/channel-test-helpers |
assertBundledChannelEntries |
Assert bundled channel entrypoints expose the expected public contract. Import from plugin-sdk/channel-test-helpers |
formatEnvelopeTimestamp |
Format deterministic envelope timestamps. Import from plugin-sdk/channel-test-helpers |
expectPairingReplyText |
Assert channel pairing reply text and extract its code. Import from plugin-sdk/channel-test-helpers |
describePluginRegistrationContract |
Install plugin registration contract checks. Import from plugin-sdk/plugin-test-contracts |
registerSingleProviderPlugin |
Register one provider plugin in loader smoke tests. Import from plugin-sdk/plugin-test-runtime |
registerProviderPlugin |
Capture all provider kinds from one plugin. Import from plugin-sdk/plugin-test-runtime |
registerProviderPlugins |
Capture provider registrations across multiple plugins. Import from plugin-sdk/plugin-test-runtime |
requireRegisteredProvider |
Assert that a provider collection contains an id. Import from plugin-sdk/plugin-test-runtime |
createRuntimeEnv |
Build a mocked CLI/plugin runtime environment. Import from plugin-sdk/plugin-test-runtime |
createPluginRuntimeMock |
Build a mocked plugin runtime surface. Import from plugin-sdk/plugin-test-runtime |
createPluginSetupWizardStatus |
Build setup status helpers for channel plugins. Import from plugin-sdk/plugin-test-runtime |
createTestWizardPrompter |
Build a mocked setup wizard prompter. Import from plugin-sdk/plugin-test-runtime |
createRuntimeTaskFlow |
Create isolated runtime task-flow state. Import from plugin-sdk/plugin-test-runtime |
runProviderCatalog |
Execute a provider catalog hook with test dependencies. Import from plugin-sdk/plugin-test-runtime |
resolveProviderWizardOptions |
Resolve provider setup wizard choices in contract tests. Import from plugin-sdk/plugin-test-runtime |
resolveProviderModelPickerEntries |
Resolve provider model-picker entries in contract tests. Import from plugin-sdk/plugin-test-runtime |
buildProviderPluginMethodChoice |
Build provider wizard choice ids for assertions. Import from plugin-sdk/plugin-test-runtime |
setProviderWizardProvidersResolverForTest |
Inject provider wizard providers for isolated tests. Import from plugin-sdk/plugin-test-runtime |
describeOpenAIProviderRuntimeContract |
Install provider-family runtime contract checks. Import from plugin-sdk/provider-test-contracts |
expectPassthroughReplayPolicy |
Assert provider replay policies pass through provider-owned tools and metadata. Import from plugin-sdk/provider-test-contracts |
runRealtimeSttLiveTest |
Run a live realtime STT provider test with shared audio fixtures. Import from plugin-sdk/provider-test-contracts |
normalizeTranscriptForMatch |
Normalize live transcript output before fuzzy assertions. Import from plugin-sdk/provider-test-contracts |
expectExplicitVideoGenerationCapabilities |
Assert video providers declare explicit generation mode capabilities. Import from plugin-sdk/provider-test-contracts |
expectExplicitMusicGenerationCapabilities |
Assert music providers declare explicit generation/edit capabilities. Import from plugin-sdk/provider-test-contracts |
mockSuccessfulDashscopeVideoTask |
Install a successful DashScope-compatible video task response. Import from plugin-sdk/provider-test-contracts |
getProviderHttpMocks |
Access opt-in provider HTTP/auth Vitest mocks. Import from plugin-sdk/provider-http-test-mocks |
installProviderHttpMockCleanup |
Reset provider HTTP/auth mocks after each test. Import from plugin-sdk/provider-http-test-mocks |
installCommonResolveTargetErrorCases |
Shared test cases for target resolution error handling. Import from plugin-sdk/channel-target-testing |
shouldAckReaction |
Check whether a channel should add an ack reaction. Import from plugin-sdk/channel-feedback |
removeAckReactionAfterReply |
Remove ack reaction after reply delivery. Import from plugin-sdk/channel-feedback |
createTestRegistry |
Build a channel plugin registry fixture. Import from plugin-sdk/plugin-test-runtime or plugin-sdk/channel-test-helpers |
createEmptyPluginRegistry |
Build an empty plugin registry fixture. Import from plugin-sdk/plugin-test-runtime or plugin-sdk/channel-test-helpers |
setActivePluginRegistry |
Install a registry fixture for plugin runtime tests. Import from plugin-sdk/plugin-test-runtime or plugin-sdk/channel-test-helpers |
createRequestCaptureJsonFetch |
Capture JSON fetch requests in media helper tests. Import from plugin-sdk/test-media-understanding |
isLiveTestEnabled |
Gate opt-in live provider tests. Import from plugin-sdk/test-live |
collectProviderApiKeys |
Discover credentials for live provider tests. Import from plugin-sdk/test-live-auth |
parseProviderModelMap |
Parse music/video live-test model overrides. Import from plugin-sdk/test-media-generation |
withServer |
Run tests against a disposable local HTTP server. Import from plugin-sdk/test-env |
createMockIncomingRequest |
Build a minimal incoming HTTP request object. Import from plugin-sdk/test-env |
withFetchPreconnect |
Run fetch tests with preconnect hooks installed. Import from plugin-sdk/test-env |
withEnv / withEnvAsync |
Temporarily patch environment variables. Import from plugin-sdk/test-env |
createTempHomeEnv / withTempHome / withTempDir |
Create isolated filesystem test fixtures. Import from plugin-sdk/test-env |
createMockServerResponse |
Create a minimal HTTP server response mock. Import from plugin-sdk/test-env |
createProviderUsageFetch |
Build provider usage fetch fixtures. Import from plugin-sdk/test-env |
useFrozenTime / useRealTime |
Freeze and restore timers for time-sensitive tests. Import from plugin-sdk/test-env |
createCliRuntimeCapture |
Capture CLI runtime output in tests. Import from plugin-sdk/test-fixtures |
importFreshModule |
Import an ESM module with a fresh query token to bypass module cache. Import from plugin-sdk/test-fixtures |
bundledPluginRoot / bundledPluginFile |
Resolve bundled plugin source or dist fixture paths. Import from plugin-sdk/test-fixtures |
mockNodeBuiltinModule |
Install narrow Node builtin Vitest mocks. Import from plugin-sdk/test-node-mocks |
createSandboxTestContext |
Build sandbox test contexts. Import from plugin-sdk/test-fixtures |
writeSkill |
Write skill fixtures. Import from plugin-sdk/test-fixtures |
makeAgentAssistantMessage |
Build agent transcript message fixtures. Import from plugin-sdk/test-fixtures |
peekSystemEvents / resetSystemEventsForTest |
Inspect and reset system event fixtures. Import from plugin-sdk/test-fixtures |
sanitizeTerminalText |
Sanitize terminal output for assertions. Import from plugin-sdk/test-fixtures |
countLines / hasBalancedFences |
Assert chunking output shape. Import from plugin-sdk/test-fixtures |
typedCases |
Preserve literal types for table-driven tests. Import from plugin-sdk/test-fixtures |
Types
Focused testing subpaths also re-export types useful in test files:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
ChannelAccountSnapshot,
ChannelGatewayContext,
} from "openclaw/plugin-sdk/channel-contract";
Testing target resolution
Use installCommonResolveTargetErrorCases to add standard error cases for channel target resolution:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
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", () => {
// ...
});
});
Testing patterns
이 섹션의 세부 항목은 공식 문서 Testing patterns를 참고하세요.
Testing registration contracts
Unit tests that pass a hand-written api mock to register(api) do not exercise OpenClaw's loader acceptance gates. Add at least one loader-backed smoke test for each registration surface your plugin depends on, especially hooks and exclusive capabilities such as memory.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Testing runtime config access
Prefer the shared plugin runtime mock from openclaw/plugin-sdk/plugin-test-runtime. Its runtime config helpers model the current snapshot and mutation APIs.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Unit testing a 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");
});
});
Unit testing a 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);
});
});
Mocking the plugin runtime
For code that uses createPluginRuntimeStore, mock the runtime in tests:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
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();
Testing with per-instance stubs
Prefer per-instance stubs over prototype mutation:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
// Preferred: per-instance stub
const client = new MyChannelClient();
client.sendMessage = vi.fn().mockResolvedValue({ id: "msg-1" });
// Avoid: prototype mutation
// MyChannelClient.prototype.sendMessage = vi.fn();
Contract tests (in-repo plugins)
Bundled plugins have contract tests that verify registration ownership:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- Which plugins register which providers
- Which plugins register which speech providers
- Registration shape correctness
- Runtime contract compliance
pnpm test src/plugins/contracts/
Running scoped tests
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 enforcement (in-repo plugins)
scripts/run-additional-boundary-checks.mjs runs a set of lint:plugins:* import-boundary checks in CI; each can also be run standalone locally:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
| Command | Enforces |
|---|---|
pnpm run lint:plugins:no-monolithic-plugin-sdk-entry-imports |
Bundled plugins cannot import the monolithic openclaw/plugin-sdk root barrel. |
pnpm run lint:plugins:no-extension-src-imports |
Production extension files cannot import the repo src/** tree directly (../../src/...). |
pnpm run lint:plugins:no-extension-test-core-imports |
Extension test files cannot import removed SDK test aliases or other core-only test helpers. |
Test configuration
OpenClaw uses Vitest 4 with informational V8 coverage reporting. For plugin tests:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Run all tests
pnpm test
Run specific plugin tests
pnpm test /my-channel/src/channel.test.ts
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Run with a specific test name filter
pnpm test /my-channel/ -t "resolves account"
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Run with coverage
pnpm test:coverage bash OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test ```
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
If local runs cause memory pressure:
관련 문서
주요 항목:
- SDK Overview -- import conventions
- SDK Channel Plugins -- channel plugin interface
- SDK Provider Plugins -- provider plugin hooks
- Building Plugins -- getting started guide
실습 체크리스트
- 공식 문서와 로컬 버전을 대조합니다:
https://docs.openclaw.ai/plugins/sdk-testing - 관련 CLI는
openclaw --help및 하위 명령--help로 옵션을 확인합니다. - 설정 변경 시
openclaw config/openclaw doctor로 유효성을 검사합니다. - Gateway·채널·플러그인 변경 후에는 필요 시 Gateway를 재시작합니다.
자주 쓰는 명령·설정 예시
shouldAckReaction,
removeAckReactionAfterReply,
} from "openclaw/plugin-sdk/channel-feedback";
bundledPluginRoot,
createCliRuntimeCapture,
typedCases,
} from "openclaw/plugin-sdk/test-fixtures";
ChannelAccountSnapshot,
ChannelGatewayContext,
} from "openclaw/plugin-sdk/channel-contract";
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", () => {
// ...
});
});
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");
});
});
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);
});
});
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();
관련 링크
- 공식 원문: plugins/sdk-testing
- OpenClaw 문서 홈
이 가이드는 공식 문서를 한국어 학습용으로 재구성한 것입니다. 옵션 기본값·플래그 이름은 설치 버전에 따라 달라질 수 있습니다.