Test de plugin
Référence pour les utilitaires de test, les modèles et l’application des règles de lint pour les plugins OpenClaw.
Utilitaires de test
Section intitulée « Utilitaires de test »Ces sous-chemins d’aide aux tests sont des points d’entrée source locaux au dépôt pour les propres tests de plugins intégrés d’OpenClaw. Ils ne sont pas des exportations de package pour les plugins tiers.
Import du simulacre d’API de plugin : APIopenclaw/plugin-sdk/plugin-test-api
Import du contrat de runtime de l’agent : openclaw/plugin-sdk/agent-runtime-test-contracts
Import du contrat de canal : openclaw/plugin-sdk/channel-contract-testing
Import de l’aide aux tests de canal : openclaw/plugin-sdk/channel-test-helpers
Import du test de cible de canal : openclaw/plugin-sdk/channel-target-testing
Import du contrat de plugin : openclaw/plugin-sdk/plugin-test-contracts
Import du test de runtime de plugin : openclaw/plugin-sdk/plugin-test-runtime
Import du contrat de fournisseur : openclaw/plugin-sdk/provider-test-contracts
Import du simulacre HTTP de fournisseur : openclaw/plugin-sdk/provider-http-test-mocks
Import du test d’environnement/réseau : openclaw/plugin-sdk/test-env
Import de fixture générique : openclaw/plugin-sdk/test-fixtures
Import du simulacle intégré Node : openclaw/plugin-sdk/test-node-mocks
Privilégiez les sous-chemins ciblés ci-dessous pour les nouveaux tests de plugins. Le module général openclaw/plugin-sdk/testing n’est qu’une compatibilité héritée.
Les garde-fous du dépôt rejettent les nouveaux imports réels de plugin-sdk/testing et plugin-sdk/test-utils ; ces noms ne demeurent que comme surfaces de compatibilité dépréciées pour les tests d’enregistrement de compatibilité.
import { shouldAckReaction, removeAckReactionAfterReply } from "openclaw/plugin-sdk/channel-feedback";import { installCommonResolveTargetErrorCases } from "openclaw/plugin-sdk/channel-target-testing";import { AUTH_PROFILE_RUNTIME_CONTRACT } from "openclaw/plugin-sdk/agent-runtime-test-contracts";import { createTestPluginApi } from "openclaw/plugin-sdk/plugin-test-api";import { expectChannelInboundContextContract } from "openclaw/plugin-sdk/channel-contract-testing";import { createStartAccountContext } from "openclaw/plugin-sdk/channel-test-helpers";import { describePluginRegistrationContract } from "openclaw/plugin-sdk/plugin-test-contracts";import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/plugin-test-runtime";import { describeOpenAIProviderRuntimeContract } from "openclaw/plugin-sdk/provider-test-contracts";import { getProviderHttpMocks } from "openclaw/plugin-sdk/provider-http-test-mocks";import { withEnv, withFetchPreconnect, withServer } from "openclaw/plugin-sdk/test-env";import { bundledPluginRoot, createCliRuntimeCapture, typedCases } from "openclaw/plugin-sdk/test-fixtures";import { mockNodeBuiltinModule } from "openclaw/plugin-sdk/test-node-mocks";Exportations disponibles
Section intitulée « Exportations disponibles »| Exportation | Objectif |
|---|---|
createTestPluginApi | Construit un simulacre minimal de l’API de plugin pour les tests unitaires d’enregistrement direct. Importer depuis APIplugin-sdk/plugin-test-api |
AUTH_PROFILE_RUNTIME_CONTRACT | Fixture de contrat de profil d’authentification partagée pour les adaptateurs de runtime d’agent natif. Importer depuis plugin-sdk/agent-runtime-test-contracts |
DELIVERY_NO_REPLY_RUNTIME_CONTRACT | Fixture de contrat de suppression de livraison partagée pour les adaptateurs de runtime d’agent natif. Importer depuis plugin-sdk/agent-runtime-test-contracts |
OUTCOME_FALLBACK_RUNTIME_CONTRACT | Fixture de contrat de classification de repli partagée pour les adaptateurs de runtime d’agent natif. Importer depuis plugin-sdk/agent-runtime-test-contracts |
createParameterFreeTool | Construit des fixtures de schéma d’outil dynamique pour les tests de contrat de runtime natif. Importer depuis 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 |
createPluginSetupWizardStatus | Build setup status helpers for channel plugins. Import from plugin-sdk/plugin-test-runtime |
describeOpenAIProviderRuntimeContract | Installer les vérifications de contrat d’exécution pour la famille de providers. Importer depuis plugin-sdk/provider-test-contracts |
expectPassthroughReplayPolicy | Affirmer que les stratégies de relecture du provider traversent les outils et les métadonnées appartenant au provider. Importer depuis plugin-sdk/provider-test-contracts |
runRealtimeSttLiveTest | Exécuter un test STT provider temps réel en direct avec des fixtures audio partagées. Importer depuis plugin-sdk/provider-test-contracts |
normalizeTranscriptForMatch | Normaliser la sortie de la transcription en direct avant les assertions floues. Importer depuis plugin-sdk/provider-test-contracts |
expectExplicitVideoGenerationCapabilities | Affirmer que les providers vidéo déclarent des capacités de mode de génération explicites. Importer depuis plugin-sdk/provider-test-contracts |
expectExplicitMusicGenerationCapabilities | Affirmer que les providers de musique déclarent des capacités de génération/édition explicites. Importer depuis plugin-sdk/provider-test-contracts |
mockSuccessfulDashscopeVideoTask | Installer une réponse de tâche vidéo compatible DashScope réussie. Importer depuis plugin-sdk/provider-test-contracts |
getProviderHttpMocks | Accéder aux mocks Vitest HTTP/auth opt-in du provider. Importer depuis plugin-sdk/provider-http-test-mocks |
installProviderHttpMockCleanup | Réinitialiser les mocks HTTP/auth du provider après chaque test. Importer depuis plugin-sdk/provider-http-test-mocks |
installCommonResolveTargetErrorCases | Cas de test partagés pour la gestion des erreurs de résolution de cible. Importer depuis plugin-sdk/channel-target-testing |
shouldAckReaction | Vérifier si un channel doit ajouter une réaction d’accusé de réception. Importer depuis plugin-sdk/channel-feedback |
removeAckReactionAfterReply | Supprimer la réaction d’accusé de réception après la livraison de la réponse. Importer depuis plugin-sdk/channel-feedback |
createTestRegistry | Construire une fixture de registre de plugins de channel. Importer depuis plugin-sdk/plugin-test-runtime ou plugin-sdk/channel-test-helpers |
createEmptyPluginRegistry | Construire une fixture de registre de plugins vide. Importer depuis plugin-sdk/plugin-test-runtime ou plugin-sdk/channel-test-helpers |
setActivePluginRegistry | Installer une fixture de registre pour les tests d’exécution de plugins. Importer depuis plugin-sdk/plugin-test-runtime ou plugin-sdk/channel-test-helpers |
createRequestCaptureJsonFetch | Capture JSON fetch requests in media helper tests. Import from plugin-sdk/test-env |
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 |
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 | Affirmer la forme de la sortie du chunking. Importer depuis plugin-sdk/test-fixtures |
runProviderCatalog | Exécuter un hook de catalogue de fournisseur avec des dépendances de test |
resolveProviderWizardOptions | Résoudre les choix de l’assistant de configuration du fournisseur dans les tests contractuels |
resolveProviderModelPickerEntries | Résoudre les entrées du sélecteur de modèle du fournisseur dans les tests contractuels |
buildProviderPluginMethodChoice | Construire les identifiants des choix de l’assistant du fournisseur pour les assertions |
setProviderWizardProvidersResolverForTest | Injecter les fournisseurs de l’assistant du fournisseur pour des tests isolés |
createProviderUsageFetch | Construire des fixtures de récupération d’utilisation du fournisseur |
useFrozenTime / useRealTime | Geler et restaurer les minuteurs pour les tests sensibles au temps. Importer depuis plugin-sdk/test-env |
createTestWizardPrompter | Construire un assistant de configuration de test simulé |
createRuntimeTaskFlow | Créer un état isolé du flux de tâches d’exécution |
typedCases | Préserver les types littéraux pour les tests basés sur des tableaux. Importer depuis plugin-sdk/test-fixtures |
Les suites de tests contractuels de plugins groupés utilisent également des sous-chemins de test du SDK pour les assistants de registre, de manifeste, d’artefact public et de fixture d’exécution réservés aux tests. Les suites exclusivement au cœur qui dépendent de l’inventaire OpenClaw groupé restent sous src/plugins/contracts.
Gardez les nouveaux tests d’extension sur un sous-chemin SDK ciblé documenté tel que
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, ou plugin-sdk/test-fixtures plutôt que d’importer le
baril de compatibilité large plugin-sdk/testing, les fichiers src/** du dépôt, ou les
ponts test/helpers/* du dépôt directement.
Les sous-chemins de test ciblés réexportent également des types utiles dans les fichiers de test :
import type { ChannelAccountSnapshot, ChannelGatewayContext } from "openclaw/plugin-sdk/channel-contract";import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";import type { MockFn, PluginRuntime, RuntimeEnv } from "openclaw/plugin-sdk/plugin-test-runtime";Test de résolution de la cible
Section intitulée « Test de résolution de la cible »Utilisez installCommonResolveTargetErrorCases pour ajouter des cas d’erreur standard pour
la résolution de la cible du channel :
import { describe } from "vitest";import { installCommonResolveTargetErrorCases } from "openclaw/plugin-sdk/channel-target-testing";
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", () => { // ... });});Modèles de test
Section intitulée « Modèles de test »Test des contrats d’enregistrement
Section intitulée « Test des contrats d’enregistrement »Les tests unitaires qui passent un api mock écrit à la main à register(api) n’exercent pas les barrières d’acceptation du chargeur d’OpenClaw. Ajoutez au moins un test de fumée (smoke test) soutenu par le chargeur pour chaque surface d’enregistrement dont dépend votre plugin, en particulier les hooks et les capacités exclusives telles que la mémoire.
Le vrai chargeur échoue l’enregistrement du plugin lorsque les métadonnées requises sont manquantes ou qu’un plugin appelle une API de capacité qu’il ne possède pas. Par exemple, api.registerHook(...) nécessite un nom de hook, et api.registerMemoryCapability(...) nécessite que le manifeste du plugin ou l’entrée exportée déclare kind: "memory".
Test de l’accès à la configuration d’exécution
Section intitulée « Test de l’accès à la configuration d’exécution »Préférez le mock partagé du runtime de plugin à partir de openclaw/plugin-sdk/channel-test-helpers lors des tests des plugins channel regroupés. Ses mocks obsolètes runtime.config.loadConfig() et runtime.config.writeConfigFile(...) lancent des exceptions par défaut afin que les tests détectent toute nouvelle utilisation des API de compatibilité. Ne substituez ces mocks que lorsque le test couvre explicitement le comportement de compatibilité hérité.
Test unitaire d’un plugin channel
Section intitulée « Test unitaire d’un plugin channel »import { describe, it, expect, vi } from "vitest";
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"); });});Test unitaire d’un plugin provider
Section intitulée « Test unitaire d’un plugin provider »import { describe, it, expect } from "vitest";
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); });});Mock du runtime du plugin
Section intitulée « Mock du runtime du plugin »Pour le code qui utilise createPluginRuntimeStore, mockez le runtime dans les tests :
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";import type { PluginRuntime } from "openclaw/plugin-sdk/runtime-store";
const store = createPluginRuntimeStore<PluginRuntime>({ pluginId: "test-plugin", errorMessage: "test runtime not set",});
// In test setupconst 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 testsstore.clearRuntime();Test avec des stubs par instance
Section intitulée « Test avec des stubs par instance »Préférez les stubs par instance à la mutation du prototype :
// Preferred: per-instance stubconst client = new MyChannelClient();client.sendMessage = vi.fn().mockResolvedValue({ id: "msg-1" });
// Avoid: prototype mutation// MyChannelClient.prototype.sendMessage = vi.fn();Tests de contrat (plugins dans le dépôt)
Section intitulée « Tests de contrat (plugins dans le dépôt) »Les plugins regroupés disposent de tests de contrat qui vérifient la propriété de l’enregistrement :
pnpm test -- src/plugins/contracts/Ces tests affirment :
- Quels plugins enregistrent quels providers
- Quels plugins enregistrent quels providers de synthèse vocale
- Correction de la forme de l’enregistrement
- Conformité du contrat d’exécution
Exécution de tests étendus
Section intitulée « Exécution de tests étendus »Pour un plugin spécifique :
pnpm test -- <bundled-plugin-root>/my-channel/Pour les tests de contrat uniquement :
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.tsApplication des règles de lint (plugins dans le dépôt)
Section intitulée « Application des règles de lint (plugins dans le dépôt) »Trois règles sont appliquées par pnpm check pour les plugins dans le dépôt :
- Pas d’imports racine monolithiques — le barrel racine de
openclaw/plugin-sdkest rejeté - Pas d’imports directs
src/— les plugins ne peuvent pas importer../../src/directement - Pas d’auto-imports — les plugins ne peuvent pas importer leur propre sous-chemin
plugin-sdk/<name>
Les plugins externes ne sont pas soumis à ces règles de lint, mais il est recommandé de suivre les mêmes modèles.
Configuration des tests
Section intitulée « Configuration des tests »OpenClaw utilise Vitest avec des seuils de couverture V8. Pour les tests de plugins :
# Run all testspnpm test
# Run specific plugin testspnpm test -- <bundled-plugin-root>/my-channel/src/channel.test.ts
# Run with a specific test name filterpnpm test -- <bundled-plugin-root>/my-channel/ -t "resolves account"
# Run with coveragepnpm test:coverageSi les exécutions locales provoquent une pression sur la mémoire :
OPENCLAW_VITEST_MAX_WORKERS=1 pnpm testConnexes
Section intitulée « Connexes »- Vue d’ensemble du SDK — conventions d’importation
- Plugins de canal SDK — interface du plugin de canal
- Plugins de fournisseur SDK — hooks du plugin de fournisseur
- Création de plugins — guide de démarrage