Skip to main content

Tests

  • Full testing kit (suites, live, Docker): Testing
  • pnpm test:force: Kills any lingering gateway process holding the default control port, then runs the full Vitest suite with an isolated gateway port so server tests don’t collide with a running instance. Use this when a prior gateway run left port 18789 occupied.
  • pnpm test:coverage: Runs the unit suite with V8 coverage (via vitest.unit.config.ts). Global thresholds are 70% lines/branches/functions/statements. Coverage excludes integration-heavy entrypoints (CLI wiring, gateway/telegram bridges, webchat static server) to keep the target focused on unit-testable logic.
  • pnpm test runs two stages: first pnpm test:scripts (node --test "scripts/**/*.test.mjs", the release/CI policy suites), and only if that passes, node scripts/test-parallel.mjs. A test:scripts failure short-circuits the && and no Vitest lane runs at all.
  • scripts/test-parallel.mjs then runs the enabled lanes in two groups. Parallel: unit, core, channels, extensions, and gateway (gateway is serial unless OPENCLAW_TEST_PARALLEL_GATEWAY=1 or a high-memory local host). Serial, after the parallel group: e2e, plus gateway when it is not parallelized. Every lane is default-on; set OPENCLAW_TEST_INCLUDE_CORE=0, OPENCLAW_TEST_INCLUDE_CHANNELS=0, OPENCLAW_TEST_INCLUDE_EXTENSIONS=0, OPENCLAW_TEST_INCLUDE_GATEWAY=0, or OPENCLAW_TEST_INCLUDE_E2E=0 to skip one. The parallel lanes all run to completion, then the runner exits with the first nonzero lane code before starting the serial group. So a failing run with no e2e output either failed test:scripts before any lane started, or failed in the parallel group — e2e was never reached, not skipped.
  • Dedicated commands still exist for a single lane: pnpm test:channels, pnpm test:extensions, pnpm test:gateway, pnpm test:e2e.
  • pnpm test:e2e (also the serial e2e lane inside pnpm test): gateway end-to-end smoke (multi-instance WS/HTTP/node pairing). vitest.e2e.config.ts uses pool: "forks" — not vmForks, because vmForks leaked the vi.mock module registry across files in a shared worker — with 1 worker locally and at most 2 in CI, silent unless OPENCLAW_E2E_VERBOSE=1. Tune with OPENCLAW_E2E_WORKERS=<n> (capped at 16). Files come from test/**, src/**, and extensions/** matching *.e2e.test.ts.
  • pnpm test on Node 24+: OpenClaw auto-disables Vitest vmForks and uses forks to avoid ERR_VM_MODULE_LINK_FAILURE / module is already linked. You can force behavior with OPENCLAW_TEST_VM_FORKS=0|1.
  • pnpm test:live: Runs provider live tests (minimax/zai). Requires API keys and LIVE=1 (or provider-specific *_LIVE_TEST=1) to unskip.

Local PR gate

For local PR land/gate checks, run:
  • pnpm check
  • pnpm build
  • pnpm test
  • pnpm check:docs
If pnpm test flakes on a loaded host, rerun once before treating it as a regression, then isolate with pnpm vitest run <path/to/test>. For memory-constrained hosts, use:
  • OPENCLAW_TEST_PROFILE=low OPENCLAW_TEST_SERIAL_GATEWAY=1 pnpm test

Model latency bench (local keys)

Script: scripts/bench-model.ts Usage:
  • source ~/.profile && pnpm tsx scripts/bench-model.ts --runs 10
  • Optional env: MINIMAX_API_KEY, MINIMAX_BASE_URL, MINIMAX_MODEL, ANTHROPIC_API_KEY
  • Default prompt: “Reply with a single word: ok. No punctuation or extra text.”
Last run (2025-12-31, 20 runs):
  • minimax median 1279ms (min 1114, max 2431)
  • opus median 2454ms (min 1224, max 3170)

CLI startup bench

Script: scripts/bench-cli-startup.ts Usage:
  • pnpm tsx scripts/bench-cli-startup.ts
  • pnpm tsx scripts/bench-cli-startup.ts --runs 12
  • pnpm tsx scripts/bench-cli-startup.ts --entry dist/entry.js --timeout-ms 45000
This benchmarks these commands:
  • --version
  • --help
  • health --json
  • status --json
  • status
Output includes avg, p50, p95, min/max, and exit-code/signal distribution for each command.

Onboarding E2E (Docker)

Docker is optional; this is only needed for containerized onboarding smoke tests. Full cold-start flow in a clean Linux container:
This script drives the interactive wizard via a pseudo-tty, verifies config/workspace/session files, then starts the gateway and runs openclaw health.

QR import smoke (Docker)

Ensures qrcode-terminal loads under Node 24+ in Docker: