Перейти к основному содержанию
Справочник по тестовым утилитам, шаблонам и проверкам линтера для Plugin OpenClaw.
Ищете примеры тестов? Практические руководства включают проработанные примеры тестов: Тесты Plugin канала и Тесты Plugin провайдера.

Тестовые утилиты

Эти подпути тестовых помощников являются локальными для репозитория исходными точками входа для собственных тестов встроенных Plugin OpenClaw. Они не являются экспортами пакета для сторонних Plugin и могут импортировать Vitest или другие тестовые зависимости, используемые только в репозитории. Импорт мока API Plugin: 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 Внутри репозитория OpenClaw для новых тестов встроенных Plugin предпочитайте узконаправленные подпути ниже. Широкий barrel-экспорт openclaw/plugin-sdk/testing предназначен только для устаревшей совместимости. Ограничения репозитория отклоняют новые реальные импорты из plugin-sdk/testing и plugin-sdk/test-utils; эти имена остаются только как устаревшие поверхности совместимости для тестов записей совместимости.
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";

Доступные экспорты

ЭкспортНазначение
createTestPluginApiСоздает минимальный mock API Plugin для модульных тестов прямой регистрации. Импорт из plugin-sdk/plugin-test-api
AUTH_PROFILE_RUNTIME_CONTRACTОбщая фикстура контракта auth-profile для адаптеров среды выполнения нативного агента. Импорт из plugin-sdk/agent-runtime-test-contracts
DELIVERY_NO_REPLY_RUNTIME_CONTRACTОбщая фикстура контракта подавления доставки для адаптеров среды выполнения нативного агента. Импорт из plugin-sdk/agent-runtime-test-contracts
OUTCOME_FALLBACK_RUNTIME_CONTRACTОбщая фикстура контракта классификации fallback для адаптеров среды выполнения нативного агента. Импорт из 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Проверяет идентификаторы каталога каналов из функции списка каталогов. Импорт из 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Регистрирует один Plugin провайдера в smoke-тестах загрузчика. Импорт из plugin-sdk/plugin-test-runtime
registerProviderPluginЗахватывает все виды провайдеров из одного Plugin. Импорт из plugin-sdk/plugin-test-runtime
registerProviderPluginsЗахватывает регистрации провайдеров из нескольких Plugin. Импорт из plugin-sdk/plugin-test-runtime
requireRegisteredProviderПроверяет, что коллекция провайдеров содержит идентификатор. Импорт из plugin-sdk/plugin-test-runtime
createRuntimeEnvСоздает mock-окружение среды выполнения CLI/Plugin. Импорт из plugin-sdk/plugin-test-runtime
createPluginRuntimeMockСоздает mock-поверхность среды выполнения 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Запускает live-тест realtime STT-провайдера с общими аудиофикстурами. Импорт из plugin-sdk/provider-test-contracts
normalizeTranscriptForMatchНормализует вывод live-транскрипта перед нечеткими проверками. Импорт из 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Получает доступ к opt-in HTTP/auth mock Vitest для провайдеров. Импорт из plugin-sdk/provider-http-test-mocks
installProviderHttpMockCleanupСбрасывает HTTP/auth mock провайдеров после каждого теста. Импорт из plugin-sdk/provider-http-test-mocks
installCommonResolveTargetErrorCasesОбщие тестовые случаи для обработки ошибок разрешения цели. Импорт из plugin-sdk/channel-target-testing
shouldAckReactionПроверяет, должен ли канал добавить ack-реакцию. Импорт из plugin-sdk/channel-feedback
removeAckReactionAfterReplyУдаляет ack-реакцию после доставки ответа. Импорт из 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 с установленными хуками preconnect. Импорт из plugin-sdk/test-env
withEnv / withEnvAsyncВременно изменяет переменные окружения. Импорт из plugin-sdk/test-env
createTempHomeEnv / withTempHome / withTempDirСоздает изолированные тестовые фикстуры файловой системы. Импорт из plugin-sdk/test-env
createMockServerResponseСоздает минимальный mock ответа HTTP-сервера. Импорт из plugin-sdk/test-env
createCliRuntimeCaptureЗахватывает вывод среды выполнения CLI в тестах. Импорт из plugin-sdk/test-fixtures
importFreshModuleИмпортирует ESM-модуль со свежим query-токеном для обхода кэша модулей. Импорт из plugin-sdk/test-fixtures
bundledPluginRoot / bundledPluginFileРазрешает пути к фикстурам исходников или dist встроенного Plugin. Импорт из plugin-sdk/test-fixtures
mockNodeBuiltinModuleУстанавливает узкие mock Vitest для встроенных модулей Node. Импорт из plugin-sdk/test-node-mocks
createSandboxTestContextСоздает контексты тестирования sandbox. Импорт из 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Создает идентификаторы вариантов мастера провайдера для проверок
setProviderWizardProvidersResolverForTestВнедрить провайдеры мастера настройки провайдера для изолированных тестов
createProviderUsageFetchСоздать фикстуры fetch для использования провайдера
useFrozenTime / useRealTimeЗаморозить и восстановить таймеры для тестов, чувствительных ко времени. Импортируйте из plugin-sdk/test-env
createTestWizardPrompterСоздать имитированный prompter мастера настройки
createRuntimeTaskFlowСоздать изолированное состояние потока задач runtime
typedCasesСохранить литеральные типы для табличных тестов. Импортируйте из plugin-sdk/test-fixtures
Наборы контрактных тестов встроенных Plugin также используют тестовые подпути SDK для вспомогательных средств реестра, манифеста, публичных артефактов и runtime-фикстур, предназначенных только для тестов. Наборы только для ядра, которые зависят от встроенного инвентаря OpenClaw, остаются в src/plugins/contracts. Размещайте новые тесты расширений в документированном узконаправленном подпути SDK, таком как 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, вместо прямого импорта широкого совместимого barrel plugin-sdk/testing, файлов репозитория src/** или мостов репозитория test/helpers/*.

Типы

Узконаправленные тестовые подпути также повторно экспортируют типы, полезные в тестовых файлах:
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";

Разрешение тестовой цели

Используйте installCommonResolveTargetErrorCases, чтобы добавить стандартные случаи ошибок для разрешения цели канала:
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", () => {
    // ...
  });
});

Шаблоны тестирования

Тестирование контрактов регистрации

Модульные тесты, которые передают вручную написанный мок api в register(api), не проверяют шлюзы приемки загрузчика OpenClaw. Добавьте хотя бы один smoke-тест на основе загрузчика для каждой поверхности регистрации, от которой зависит ваш Plugin, особенно для хуков и эксклюзивных возможностей, таких как память. Реальный загрузчик завершает регистрацию Plugin с ошибкой, когда отсутствуют обязательные метаданные или Plugin вызывает API возможности, которой он не владеет. Например, api.registerHook(...) требует имя хука, а api.registerMemoryCapability(...) требует, чтобы манифест Plugin или экспортированная точка входа объявляли kind: "memory".

Тестирование доступа к конфигурации среды выполнения

Предпочитайте общий мок среды выполнения Plugin из openclaw/plugin-sdk/plugin-test-runtime. Его устаревшие моки runtime.config.loadConfig() и runtime.config.writeConfigFile(...) по умолчанию выбрасывают ошибку, чтобы тесты выявляли новое использование API совместимости. Переопределяйте эти моки только тогда, когда тест явно покрывает устаревшее поведение совместимости.

Модульное тестирование канального Plugin

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");
  });
});

Модульное тестирование провайдерского Plugin

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);
  });
});

Мокирование среды выполнения Plugin

Для кода, который использует createPluginRuntimeStore, мокируйте среду выполнения в тестах:
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 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();

Тестирование с заглушками на уровне экземпляра

Предпочитайте заглушки на уровне экземпляра вместо изменения прототипа:
// Preferred: per-instance stub
const client = new MyChannelClient();
client.sendMessage = vi.fn().mockResolvedValue({ id: "msg-1" });

// Avoid: prototype mutation
// 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.ts
pnpm test -- src/plugins/contracts/auth-choice.contract.test.ts
pnpm test -- src/plugins/contracts/runtime-seams.contract.test.ts

Проверка lint (Plugin внутри репозитория)

Для Plugin внутри репозитория pnpm check применяет три правила:
  1. Без монолитных корневых импортов — корневой barrel openclaw/plugin-sdk отклоняется
  2. Без прямых импортов src/ — Plugin не могут напрямую импортировать ../../src/
  3. Без самоимпортов — Plugin не могут импортировать собственный подпуть plugin-sdk/<name>
Внешние Plugin не подпадают под эти правила lint, но рекомендуется следовать тем же шаблонам.

Конфигурация тестов

OpenClaw использует Vitest с порогами покрытия V8. Для тестов 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

Связанные материалы