Testing
การทดสอบ
OpenClaw มีชุดทดสอบ Vitest สามชุด (unit/integration, e2e, live) และชุด Docker runner ขนาดเล็ก เอกสารนี้เป็นคู่มือ "วิธีที่เราทดสอบ":
- แต่ละชุดครอบคลุมอะไรบ้าง (และตั้งใจ ไม่ ครอบคลุมอะไรบ้าง)
- คำสั่งที่ควรรันสำหรับเวิร์กโฟลว์ทั่วไป (local, pre-push, การดีบัก)
- วิธีที่การทดสอบ live ค้นพบข้อมูลรับรองและเลือกโมเดล/ผู้ให้บริการ
- วิธีเพิ่มรีเกรสชันสำหรับปัญหาโมเดล/ผู้ให้บริการในโลกจริง
เริ่มต้นอย่างรวดเร็ว
ส่วนใหญ่ในแต่ละวัน:
- เกตเต็มรูปแบบ (คาดหวังก่อน push):
pnpm build && pnpm check && pnpm check:test-types && pnpm test - การรันชุดทดสอบเต็มในเครื่องที่เร็วขึ้นบนเครื่องที่มีทรัพยากรมาก:
pnpm test:max - ลูป watch ของ Vitest โดยตรง:
pnpm test:watch - การระบุไฟล์โดยตรงตอนนี้ส่งต่อเส้นทาง extension/channel ด้วย:
pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts - ให้เลือกการรันแบบเจาะจงก่อนเมื่อคุณกำลังวนแก้ข้อผิดพลาดเดียว
- ไซต์ QA ที่รองรับด้วย Docker:
pnpm qa:lab:up - QA lane ที่รองรับด้วย Linux VM:
pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline
เมื่อคุณแก้ไขการทดสอบหรือต้องการความมั่นใจเพิ่มเติม:
- Coverage gate:
pnpm test:coverage - ชุด E2E:
pnpm test:e2e
เมื่อดีบักผู้ให้บริการ/โมเดลจริง (ต้องใช้ข้อมูลรับรองจริง):
- ชุด live (โมเดล + การ probe เครื่องมือ/รูปภาพของ Gateway):
pnpm test:live - ระบุไฟล์ live หนึ่งไฟล์แบบเงียบ:
pnpm test:live -- src/agents/models.profiles.live.test.ts - รายงานประสิทธิภาพรันไทม์: dispatch
OpenClaw Performanceพร้อมlive_gpt54=trueสำหรับ agent turn จริงของopenai/gpt-5.4หรือdeep_profile=trueสำหรับอาร์ติแฟกต์ CPU/heap/trace ของ Kova การรันตามกำหนดรายวัน จะเผยแพร่อาร์ติแฟกต์ lane ของ mock-provider, deep-profile และ GPT 5.4 ไปยังopenclaw/clawgrit-reportsเมื่อมีการกำหนดค่าCLAWGRIT_REPORTS_TOKENรายงาน mock-provider ยังรวมตัวเลขระดับซอร์สของ gateway boot, หน่วยความจำ, plugin-pressure, fake-model hello-loop ซ้ำ และการเริ่มต้น CLI ด้วย - การ sweep โมเดล live ด้วย Docker:
pnpm test:docker:live-models- ตอนนี้แต่ละโมเดลที่เลือกจะรัน text turn พร้อม probe ขนาดเล็กแบบอ่านไฟล์
โมเดลที่เมตาดาตาระบุว่ารองรับอินพุต
imageจะรัน image turn ขนาดเล็กด้วย ปิด probe เพิ่มเติมด้วยOPENCLAW_LIVE_MODEL_FILE_PROBE=0หรือOPENCLAW_LIVE_MODEL_IMAGE_PROBE=0เมื่อต้องการแยกความล้มเหลวของผู้ให้บริการ - ความครอบคลุมใน CI:
OpenClaw Scheduled Live And E2E ChecksรายวันและOpenClaw Release Checksแบบ manual ต่างเรียก reusable live/E2E workflow ด้วยinclude_live_suites: trueซึ่งรวมงาน Docker live model matrix แยกต่างหาก ที่ shard ตามผู้ให้บริการ - สำหรับการรัน CI ซ้ำแบบโฟกัส ให้ dispatch
OpenClaw Live And E2E Checks (Reusable)ด้วยinclude_live_suites: trueและlive_models_only: true - เพิ่ม secret ของผู้ให้บริการที่มีสัญญาณสูงรายการใหม่ไปยัง
scripts/ci-hydrate-live-auth.shรวมถึง.github/workflows/openclaw-live-and-e2e-checks-reusable.ymlและตัวเรียก scheduled/release ของ workflow นั้น
- ตอนนี้แต่ละโมเดลที่เลือกจะรัน text turn พร้อม probe ขนาดเล็กแบบอ่านไฟล์
โมเดลที่เมตาดาตาระบุว่ารองรับอินพุต
- smoke แชตแบบ bound ของ Native Codex:
pnpm test:docker:live-codex-bind- รัน Docker live lane กับเส้นทาง Codex app-server, ผูก Slack DM สังเคราะห์ด้วย
/codex bind, ทดสอบ/codex fastและ/codex permissions, จากนั้นตรวจสอบคำตอบแบบธรรมดาและเส้นทางไฟล์แนบรูปภาพ ผ่านการผูก Plugin แบบ native แทน ACP
- รัน Docker live lane กับเส้นทาง Codex app-server, ผูก Slack DM สังเคราะห์ด้วย
- smoke harness ของ Codex app-server:
pnpm test:docker:live-codex-harness- รัน gateway agent turn ผ่าน harness ของ Codex app-server ที่ Plugin เป็นเจ้าของ,
ตรวจสอบ
/codex statusและ/codex models, และโดยค่าเริ่มต้นจะทดสอบ probe ของ image, cron MCP, sub-agent และ Guardian ปิด probe ของ sub-agent ด้วยOPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0เมื่อต้องการแยกความล้มเหลวอื่นของ Codex app-server สำหรับการตรวจ sub-agent แบบโฟกัส ให้ปิด probe อื่น:OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=1 pnpm test:docker:live-codex-harnessคำสั่งนี้จะออกหลังจาก probe ของ sub-agent เว้นแต่ตั้งค่าOPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0
- รัน gateway agent turn ผ่าน harness ของ Codex app-server ที่ Plugin เป็นเจ้าของ,
ตรวจสอบ
- smoke คำสั่ง rescue ของ Crestodian:
pnpm test:live:crestodian-rescue-channel- การตรวจแบบ opt-in ที่รัดกุมเป็นพิเศษสำหรับพื้นผิวคำสั่ง rescue ของช่องทางข้อความ
คำสั่งนี้ทดสอบ
/crestodian status, จัดคิวการเปลี่ยนโมเดลแบบถาวร, ตอบกลับ/crestodian yes, และตรวจสอบเส้นทางการเขียน audit/config
- การตรวจแบบ opt-in ที่รัดกุมเป็นพิเศษสำหรับพื้นผิวคำสั่ง rescue ของช่องทางข้อความ
คำสั่งนี้ทดสอบ
- smoke Docker ของ Crestodian planner:
pnpm test:docker:crestodian-planner- รัน Crestodian ในคอนเทนเนอร์ที่ไม่มี config พร้อม Claude CLI ปลอมบน
PATHและตรวจสอบว่า fallback ของ fuzzy planner แปลเป็นการเขียน config แบบ typed ที่มีการ audit
- รัน Crestodian ในคอนเทนเนอร์ที่ไม่มี config พร้อม Claude CLI ปลอมบน
- smoke Docker สำหรับการรันครั้งแรกของ Crestodian:
pnpm test:docker:crestodian-first-run- เริ่มจากไดเรกทอรีสถานะ OpenClaw ที่ว่างเปล่า, ส่ง
openclawเปล่าไปยัง Crestodian, ใช้การเขียน setup/model/agent/Discord Plugin + SecretRef, ตรวจสอบ config, และตรวจสอบรายการ audit เส้นทาง setup Ring 0 เดียวกันนี้ ยังครอบคลุมใน QA Lab ด้วยpnpm openclaw qa suite --scenario crestodian-ring-zero-setup
- เริ่มจากไดเรกทอรีสถานะ OpenClaw ที่ว่างเปล่า, ส่ง
- smoke ต้นทุน Moonshot/Kimi: เมื่อตั้งค่า
MOONSHOT_API_KEYแล้ว ให้รันopenclaw models list --provider moonshot --json, จากนั้นรันopenclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --jsonแบบแยกกับmoonshot/kimi-k2.6ตรวจสอบว่า JSON รายงาน Moonshot/K2.6 และ transcript ของผู้ช่วยเก็บusage.costที่ normalize แล้ว
runner เฉพาะ QA
คำสั่งเหล่านี้อยู่ข้างชุดทดสอบหลักเมื่อคุณต้องการความสมจริงของ QA-lab:
CI รัน QA Lab ใน workflow เฉพาะ Agentic parity ซ้อนอยู่ภายใต้
QA-Lab - All Lanes และ release validation ไม่ใช่ workflow ของ PR แบบ standalone
การตรวจสอบแบบกว้างควรใช้ Full Release Validation พร้อม
rerun_group=qa-parity หรือกลุ่ม QA ของ release-checks การตรวจ release
แบบ stable/default จะเก็บ live/Docker soak แบบครอบคลุมไว้หลัง run_release_soak=true;
โปรไฟล์ full จะบังคับเปิด soak QA-Lab - All Lanes
รันทุกคืนบน main และจาก manual dispatch โดยมี mock parity lane, live
Matrix lane, live Telegram lane ที่จัดการด้วย Convex และ live Discord
lane ที่จัดการด้วย Convex เป็นงานขนาน Scheduled QA และ release checks ส่ง Matrix
--profile fast อย่างชัดเจน ขณะที่ค่าเริ่มต้นของ Matrix CLI และ input ของ manual workflow
ยังคงเป็น all; manual dispatch สามารถ shard all เป็นงาน transport,
media, e2ee-smoke, e2ee-deep และ e2ee-cli ได้ OpenClaw Release Checks รัน parity พร้อม Matrix แบบ fast และ Telegram lane ก่อนการอนุมัติ release
โดยใช้ mock-openai/gpt-5.5 สำหรับการตรวจ release transport เพื่อให้คง determinism
และหลีกเลี่ยงการเริ่มต้น provider-plugin ตามปกติ Gateway ของ live transport เหล่านี้
ปิด memory search; พฤติกรรม memory ยังคงครอบคลุมโดยชุด QA parity
shard ของ live media สำหรับ full release ใช้
ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04 ซึ่งมี
ffmpeg และ ffprobe อยู่แล้ว shard ของ Docker live model/backend ใช้ image
ghcr.io/openclaw/openclaw-live-test:<sha> ร่วมกันที่สร้างหนึ่งครั้งต่อ commit
ที่เลือก จากนั้น pull ด้วย OPENCLAW_SKIP_DOCKER_BUILD=1 แทนการ rebuild
ภายในทุก shard
pnpm openclaw qa suite- รันสถานการณ์ QA ที่อิงกับรีโปโดยตรงบนโฮสต์
- รันสถานการณ์ที่เลือกไว้หลายรายการแบบขนานเป็นค่าเริ่มต้นด้วยตัวทำงาน
gateway แบบแยกกัน
qa-channelมีค่าเริ่มต้นของ concurrency เป็น 4 (จำกัดตาม จำนวนสถานการณ์ที่เลือก) ใช้--concurrency <count>เพื่อปรับจำนวนตัวทำงาน หรือ--concurrency 1สำหรับเลนแบบอนุกรมเดิม - ออกด้วยค่าที่ไม่ใช่ศูนย์เมื่อสถานการณ์ใดล้มเหลว ใช้
--allow-failuresเมื่อคุณ ต้องการอาร์ติแฟกต์โดยไม่มีรหัสออกที่ล้มเหลว - รองรับโหมด provider
live-frontier,mock-openaiและaimockaimockเริ่มเซิร์ฟเวอร์ provider ภายในเครื่องที่อิงกับ AIMock สำหรับการครอบคลุม fixture และ protocol-mock แบบทดลอง โดยไม่แทนที่เลนmock-openaiที่รู้บริบทของสถานการณ์
pnpm test:plugins:kitchen-sink-live- รันชุดทดสอบหนักของ OpenAI Kitchen Sink Plugin แบบสดผ่าน QA Lab โดยจะ
ติดตั้งแพ็กเกจ Kitchen Sink ภายนอก ตรวจสอบ inventory ของพื้นผิว plugin SDK
probe
/healthzและ/readyzบันทึกหลักฐาน CPU/RSS ของ gateway รันเทิร์น OpenAI แบบสดหนึ่งครั้ง และตรวจสอบ diagnostics เชิงโจมตี ต้องมี auth ของ OpenAI แบบสด เช่นOPENAI_API_KEYในเซสชัน Testbox ที่เติมข้อมูลแล้ว ระบบจะ source โปรไฟล์ live-auth ของ Testbox โดยอัตโนมัติเมื่อมี helperopenclaw-testbox-env
- รันชุดทดสอบหนักของ OpenAI Kitchen Sink Plugin แบบสดผ่าน QA Lab โดยจะ
ติดตั้งแพ็กเกจ Kitchen Sink ภายนอก ตรวจสอบ inventory ของพื้นผิว plugin SDK
probe
pnpm test:gateway:cpu-scenarios- รัน bench การเริ่มต้น gateway พร้อมชุดสถานการณ์ mock QA Lab ขนาดเล็ก
(
channel-chat-baseline,memory-failure-fallback,gateway-restart-inflight-run) และเขียนสรุปการสังเกต CPU แบบรวม ไว้ใต้.artifacts/gateway-cpu-scenarios/ - โดยค่าเริ่มต้น flag เฉพาะการสังเกต CPU ร้อนที่ต่อเนื่อง (
--cpu-core-warnร่วมกับ--hot-wall-warn-ms) ดังนั้น burst สั้น ๆ ตอนเริ่มต้นจะถูกบันทึกเป็นเมตริก โดยไม่ดูเหมือน regression ที่ gateway ใช้ CPU เต็มหลายนาที - ใช้อาร์ติแฟกต์
distที่ build แล้ว; รัน build ก่อนเมื่อ checkout ยังไม่มี output runtime ที่สดใหม่
- รัน bench การเริ่มต้น gateway พร้อมชุดสถานการณ์ mock QA Lab ขนาดเล็ก
(
pnpm openclaw qa suite --runner multipass- รันชุด QA เดียวกันภายใน Multipass Linux VM แบบใช้แล้วทิ้ง
- คงพฤติกรรมการเลือกสถานการณ์แบบเดียวกับ
qa suiteบนโฮสต์ - ใช้ flag การเลือก provider/model ชุดเดียวกับ
qa suite - การรันแบบสดจะ forward อินพุต auth ของ QA ที่รองรับและใช้งานได้จริงสำหรับ guest:
provider key ที่อิงกับ env, path config provider แบบสดของ QA และ
CODEX_HOMEเมื่อมีอยู่ - ไดเรกทอรี output ต้องอยู่ใต้รากรีโปเพื่อให้ guest เขียนกลับผ่าน workspace ที่ mount ได้
- เขียนรายงาน QA และสรุปปกติพร้อม log ของ Multipass ไว้ใต้
.artifacts/qa-e2e/...
pnpm qa:lab:up- เริ่มไซต์ QA ที่อิงกับ Docker สำหรับงาน QA แบบ operator
pnpm test:docker:npm-onboard-channel-agent- Build tarball ของ npm จาก checkout ปัจจุบัน ติดตั้งแบบ global ใน Docker รัน onboarding แบบไม่โต้ตอบด้วย OpenAI API key ตั้งค่า Telegram เป็นค่าเริ่มต้น ตรวจสอบว่า runtime ของ Plugin ที่แพ็กแล้วโหลดได้โดยไม่ต้องซ่อม dependency ตอนเริ่มต้น รัน doctor และรันเทิร์น agent ภายในเครื่องหนึ่งครั้งกับ endpoint OpenAI ที่ mock
- ใช้
OPENCLAW_NPM_ONBOARD_CHANNEL=discordเพื่อรันเลน packaged-install เดียวกันกับ Discord
pnpm test:docker:session-runtime-context- รัน Docker smoke ของ built-app แบบ deterministic สำหรับ transcript ของ embedded runtime context
โดยตรวจสอบว่า runtime context ของ OpenClaw ที่ซ่อนอยู่ถูก persist เป็นข้อความ custom
ที่ไม่แสดงผลแทนที่จะรั่วเข้าไปในเทิร์นผู้ใช้ที่มองเห็น จากนั้น seed JSONL ของ session
ที่เสียซึ่งได้รับผลกระทบ และตรวจสอบว่า
openclaw doctor --fixเขียนใหม่ไปยัง active branch พร้อม backup
- รัน Docker smoke ของ built-app แบบ deterministic สำหรับ transcript ของ embedded runtime context
โดยตรวจสอบว่า runtime context ของ OpenClaw ที่ซ่อนอยู่ถูก persist เป็นข้อความ custom
ที่ไม่แสดงผลแทนที่จะรั่วเข้าไปในเทิร์นผู้ใช้ที่มองเห็น จากนั้น seed JSONL ของ session
ที่เสียซึ่งได้รับผลกระทบ และตรวจสอบว่า
pnpm test:docker:npm-telegram-live- ติดตั้ง package candidate ของ OpenClaw ใน Docker รัน onboarding ของ installed-package ตั้งค่า Telegram ผ่าน CLI ที่ติดตั้งแล้ว จากนั้นนำเลน Telegram QA แบบสดมาใช้ซ้ำ โดยใช้แพ็กเกจที่ติดตั้งนั้นเป็น SUT Gateway
- ค่าเริ่มต้นคือ
OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta; ตั้งค่าOPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgzหรือOPENCLAW_CURRENT_PACKAGE_TGZเพื่อทดสอบ tarball ภายในเครื่องที่ resolve แล้วแทนการ ติดตั้งจาก registry - ใช้ credential env ของ Telegram หรือแหล่ง credential ของ Convex เดียวกับ
pnpm openclaw qa telegramสำหรับ automation ของ CI/release ให้ตั้งค่าOPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convexพร้อมOPENCLAW_QA_CONVEX_SITE_URLและ role secret หากOPENCLAW_QA_CONVEX_SITE_URLและ role secret ของ Convex มีอยู่ใน CI wrapper ของ Docker จะเลือก Convex โดยอัตโนมัติ - wrapper ตรวจสอบ env credential ของ Telegram หรือ Convex บนโฮสต์ก่อน
งาน build/install ของ Docker ตั้งค่า
OPENCLAW_NPM_TELEGRAM_SKIP_CREDENTIAL_PREFLIGHT=1เฉพาะเมื่อจงใจ debug การตั้งค่าก่อน credential OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintaineroverrideOPENCLAW_QA_CREDENTIAL_ROLEที่ใช้ร่วมกันสำหรับเลนนี้เท่านั้น- GitHub Actions เปิดเผยเลนนี้เป็น workflow แบบ manual สำหรับ maintainer
NPM Telegram Beta E2Eโดยจะไม่รันเมื่อ merge workflow ใช้ environmentqa-live-sharedและ lease credential CI ของ Convex
- GitHub Actions ยังเปิดเผย
Package Acceptanceสำหรับหลักฐานผลิตภัณฑ์แบบ side-run กับ candidate package หนึ่งรายการ โดยรับ trusted ref, npm spec ที่ publish แล้ว, URL tarball HTTPS พร้อม SHA-256 หรืออาร์ติแฟกต์ tarball จากการรันอื่น อัปโหลดopenclaw-current.tgzที่ normalize แล้วเป็นpackage-under-testจากนั้นรัน scheduler Docker E2E ที่มีอยู่ด้วยโปรไฟล์เลน smoke, package, product, full หรือ custom ตั้งค่าtelegram_mode=mock-openaiหรือlive-frontierเพื่อรัน workflow Telegram QA กับอาร์ติแฟกต์package-under-testเดียวกัน- หลักฐานผลิตภัณฑ์ beta ล่าสุด:
gh workflow run package-acceptance.yml --ref main \
-f source=npm \
-f package_spec=openclaw@beta \
-f suite_profile=product \
-f telegram_mode=mock-openai
- หลักฐาน URL tarball แบบเจาะจงต้องมี digest:
gh workflow run package-acceptance.yml --ref main \
-f source=url \
-f package_url=https://registry.npmjs.org/openclaw/-/openclaw-VERSION.tgz \
-f package_sha256=<sha256> \
-f suite_profile=package
- หลักฐานอาร์ติแฟกต์จะดาวน์โหลดอาร์ติแฟกต์ tarball จากการรัน Actions อื่น:
gh workflow run package-acceptance.yml --ref main \
-f source=artifact \
-f artifact_run_id=<run-id> \
-f artifact_name=<artifact-name> \
-f suite_profile=smoke
-
pnpm test:docker:plugins- แพ็กและติดตั้ง build ปัจจุบันของ OpenClaw ใน Docker เริ่ม Gateway โดยตั้งค่า OpenAI แล้วเปิดใช้ channel/Plugin ที่ bundled ผ่านการแก้ไข config
- ตรวจสอบว่า setup discovery เว้น Plugin ที่ดาวน์โหลดได้ซึ่งยังไม่ได้ตั้งค่าไว้ ให้ไม่ปรากฏ การซ่อม doctor ครั้งแรกที่ตั้งค่าไว้จะติดตั้ง Plugin ที่ดาวน์โหลดได้ แต่ละรายการที่หายไปอย่างชัดเจน และการ restart ครั้งที่สองจะไม่รันการซ่อม dependency ที่ซ่อนอยู่
- ติดตั้ง baseline npm รุ่นเก่าที่ทราบด้วย เปิดใช้ Telegram ก่อนรัน
openclaw update --tag <candidate>และตรวจสอบว่า doctor หลังอัปเดตของ candidate ล้างเศษ dependency ของ Plugin รุ่นเก่าโดยไม่มีการซ่อม postinstall ฝั่ง harness
-
pnpm test:parallels:npm-update-
รัน smoke การอัปเดต packaged-install แบบ native ข้าม guest ของ Parallels แต่ละ platform ที่เลือกจะติดตั้ง baseline package ที่ร้องขอก่อน จากนั้นรันคำสั่ง
openclaw updateที่ติดตั้งแล้วใน guest เดียวกัน และตรวจสอบเวอร์ชันที่ติดตั้ง สถานะการอัปเดต ความพร้อมของ gateway และเทิร์น agent ภายในเครื่องหนึ่งครั้ง -
ใช้
--platform macos,--platform windowsหรือ--platform linuxระหว่าง iterate กับ guest หนึ่งรายการ ใช้--jsonสำหรับ path อาร์ติแฟกต์สรุปและ สถานะต่อเลน -
เลน OpenAI ใช้
openai/gpt-5.5สำหรับหลักฐานเทิร์น agent แบบสดเป็น ค่าเริ่มต้น ส่ง--model <provider/model>หรือตั้งค่าOPENCLAW_PARALLELS_OPENAI_MODELเมื่อจงใจตรวจสอบ OpenAI model อื่น -
ห่อการรันภายในเครื่องที่ยาวด้วย timeout ของโฮสต์ เพื่อไม่ให้ Parallels transport stall ใช้เวลาทดสอบที่เหลือทั้งหมด:
timeout --foreground 150m pnpm test:parallels:npm-update -- --json timeout --foreground 90m pnpm test:parallels:npm-update -- --platform windows --json -
สคริปต์เขียน log ของเลนแบบซ้อนใต้
/tmp/openclaw-parallels-npm-update.*ตรวจสอบwindows-update.log,macos-update.logหรือlinux-update.logก่อนสันนิษฐานว่า outer wrapper ค้าง -
การอัปเดต Windows อาจใช้เวลา 10 ถึง 15 นาทีในงาน doctor หลังอัปเดตและงาน อัปเดตแพ็กเกจบน guest ที่ยังเย็นอยู่ ซึ่งยังถือว่าปกติเมื่อ log debug ของ npm แบบซ้อนยังเดินหน้าอยู่
-
อย่ารัน wrapper แบบรวมนี้พร้อมกันกับเลน smoke ของ Parallels รายตัวสำหรับ macOS, Windows หรือ Linux เพราะใช้ state ของ VM ร่วมกันและอาจชนกันที่ snapshot restore, package serving หรือ state ของ gateway ใน guest
-
หลักฐานหลังอัปเดตรันพื้นผิว Plugin ที่ bundled ตามปกติ เพราะ facade ของ capability เช่น speech, image generation และ media understanding ถูกโหลดผ่าน runtime API ที่ bundled แม้ว่าเทิร์น agent เองจะตรวจเพียงคำตอบข้อความง่าย ๆ
-
-
pnpm openclaw qa aimock- เริ่มเฉพาะเซิร์ฟเวอร์ provider AIMock ภายในเครื่องสำหรับการทดสอบ protocol smoke โดยตรง
-
pnpm openclaw qa matrix- รันเลน Matrix QA แบบสดกับ Tuwunel homeserver แบบใช้แล้วทิ้งที่อิงกับ Docker เฉพาะ source-checkout เท่านั้น - packaged install ไม่ได้ ship
qa-lab - CLI แบบเต็ม, catalog ของ profile/scenario, env vars และ layout ของอาร์ติแฟกต์: Matrix QA
- รันเลน Matrix QA แบบสดกับ Tuwunel homeserver แบบใช้แล้วทิ้งที่อิงกับ Docker เฉพาะ source-checkout เท่านั้น - packaged install ไม่ได้ ship
-
pnpm openclaw qa telegram- รันเลน Telegram QA แบบสดกับกลุ่ม private จริงโดยใช้ token ของ driver และ SUT bot จาก env
- ต้องมี
OPENCLAW_QA_TELEGRAM_GROUP_ID,OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKENและOPENCLAW_QA_TELEGRAM_SUT_BOT_TOKENgroup id ต้องเป็น Telegram chat id แบบตัวเลข - รองรับ
--credential-source convexสำหรับ credential แบบ pooled ที่ใช้ร่วมกัน ใช้โหมด env เป็นค่าเริ่มต้น หรือตั้งค่าOPENCLAW_QA_CREDENTIAL_SOURCE=convexเพื่อเลือกใช้ pooled lease - ออกด้วยค่าที่ไม่ใช่ศูนย์เมื่อสถานการณ์ใดล้มเหลว ใช้
--allow-failuresเมื่อคุณ ต้องการอาร์ติแฟกต์โดยไม่มีรหัสออกที่ล้มเหลว - ต้องมี bot สองตัวที่แตกต่างกันในกลุ่ม private เดียวกัน โดย SUT bot ต้องเปิดเผย username ของ Telegram
- เพื่อการสังเกต bot-to-bot ที่เสถียร ให้เปิดใช้ Bot-to-Bot Communication Mode ใน
@BotFatherสำหรับ bot ทั้งสองตัว และตรวจสอบให้แน่ใจว่า driver bot สังเกต traffic ของ bot ในกลุ่มได้ - เขียนรายงาน Telegram QA, สรุป และอาร์ติแฟกต์ observed-messages ไว้ใต้
.artifacts/qa-e2e/...สถานการณ์ที่ตอบกลับจะรวม RTT ตั้งแต่คำขอส่งของ driver จนถึงการสังเกตคำตอบของ SUT
เลน transport แบบสดใช้ contract มาตรฐานเดียวกันร่วมกัน เพื่อไม่ให้ transport ใหม่เบี่ยงเบน เมทริกซ์การครอบคลุมต่อเลนอยู่ใน ภาพรวม QA → การครอบคลุม transport แบบสด qa-channel คือชุด synthetic แบบกว้าง และไม่เป็นส่วนหนึ่งของเมทริกซ์นั้น
Credential ของ Telegram ที่ใช้ร่วมกันผ่าน Convex (v1)
เมื่อเปิดใช้ --credential-source convex (หรือ OPENCLAW_QA_CREDENTIAL_SOURCE=convex) สำหรับ
openclaw qa telegram แล้ว QA lab จะรับ lease แบบ exclusive จาก pool ที่อิงกับ Convex, Heartbeat
lease นั้นขณะเลนกำลังรัน และปล่อย lease เมื่อ shutdown
scaffold อ้างอิงของโปรเจกต์ Convex:
qa/convex-credential-broker/
env vars ที่ต้องมี:
OPENCLAW_QA_CONVEX_SITE_URL(เช่นhttps://your-deployment.convex.site)- secret หนึ่งรายการสำหรับ role ที่เลือก:
OPENCLAW_QA_CONVEX_SECRET_MAINTAINERสำหรับmaintainerOPENCLAW_QA_CONVEX_SECRET_CIสำหรับci
- การเลือก role ของ credential:
- CLI:
--credential-role maintainer|ci - ค่าเริ่มต้นของ Env:
OPENCLAW_QA_CREDENTIAL_ROLE(มีค่าเริ่มต้นเป็นciใน CI, ไม่เช่นนั้นเป็นmaintainer)
- CLI:
env vars แบบไม่บังคับ:
OPENCLAW_QA_CREDENTIAL_LEASE_TTL_MS(ค่าเริ่มต้น1200000)OPENCLAW_QA_CREDENTIAL_HEARTBEAT_INTERVAL_MS(ค่าเริ่มต้น30000)OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS(ค่าเริ่มต้น90000)OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS(ค่าเริ่มต้น15000)OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX(ค่าเริ่มต้น/qa-credentials/v1)OPENCLAW_QA_CREDENTIAL_OWNER_ID(trace id แบบไม่บังคับ)OPENCLAW_QA_ALLOW_INSECURE_HTTP=1อนุญาต URL ของ Convex แบบ loopbackhttp://สำหรับการพัฒนาเฉพาะภายในเครื่องเท่านั้น
OPENCLAW_QA_CONVEX_SITE_URL ควรใช้ https:// ในการทำงานปกติ
คำสั่งผู้ดูแลสำหรับ maintainer (pool add/remove/list) ต้องใช้
OPENCLAW_QA_CONVEX_SECRET_MAINTAINER โดยเฉพาะ
ตัวช่วย CLI สำหรับ maintainer:
pnpm openclaw qa credentials doctor
pnpm openclaw qa credentials add --kind telegram --payload-file qa/telegram-credential.json
pnpm openclaw qa credentials list --kind telegram
pnpm openclaw qa credentials remove --credential-id <credential-id>
ใช้ doctor ก่อนการรันแบบ live เพื่อตรวจสอบ URL ของไซต์ Convex, ความลับของ broker,
คำนำหน้า endpoint, HTTP timeout และการเข้าถึง admin/list โดยไม่พิมพ์
ค่าความลับ ใช้ --json สำหรับเอาต์พุตที่เครื่องอ่านได้ในสคริปต์และยูทิลิตี CI
สัญญา endpoint เริ่มต้น (OPENCLAW_QA_CONVEX_SITE_URL + /qa-credentials/v1):
POST /acquire- คำขอ:
{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs } - สำเร็จ:
{ status: "ok", credentialId, leaseToken, payload, leaseTtlMs?, heartbeatIntervalMs? } - หมด/ลองใหม่ได้:
{ status: "error", code: "POOL_EXHAUSTED" | "NO_CREDENTIAL_AVAILABLE", ... }
- คำขอ:
POST /heartbeat- คำขอ:
{ kind, ownerId, actorRole, credentialId, leaseToken, leaseTtlMs } - สำเร็จ:
{ status: "ok" }(หรือ2xxว่าง)
- คำขอ:
POST /release- คำขอ:
{ kind, ownerId, actorRole, credentialId, leaseToken } - สำเร็จ:
{ status: "ok" }(หรือ2xxว่าง)
- คำขอ:
POST /admin/add(ความลับของ maintainer เท่านั้น)- คำขอ:
{ kind, actorId, payload, note?, status? } - สำเร็จ:
{ status: "ok", credential }
- คำขอ:
POST /admin/remove(ความลับของ maintainer เท่านั้น)- คำขอ:
{ credentialId, actorId } - สำเร็จ:
{ status: "ok", changed, credential } - ตัวป้องกัน lease ที่ใช้งานอยู่:
{ status: "error", code: "LEASE_ACTIVE", ... }
- คำขอ:
POST /admin/list(ความลับของ maintainer เท่านั้น)- คำขอ:
{ kind?, status?, includePayload?, limit? } - สำเร็จ:
{ status: "ok", credentials, count }
- คำขอ:
รูปทรง payload สำหรับชนิด Telegram:
{ groupId: string, driverToken: string, sutToken: string }groupIdต้องเป็นสตริงรหัสแชต Telegram แบบตัวเลขadmin/addตรวจสอบรูปทรงนี้สำหรับkind: "telegram"และปฏิเสธ payload ที่ผิดรูปแบบ
การเพิ่มช่องทางเข้า QA
สถาปัตยกรรมและชื่อ scenario-helper สำหรับ adapter ช่องทางใหม่อยู่ใน ภาพรวม QA → การเพิ่มช่องทาง เกณฑ์ขั้นต่ำ: ใช้งาน transport runner บน seam โฮสต์ qa-lab ที่ใช้ร่วมกัน, ประกาศ qaRunners ใน manifest ของ plugin, เมานต์เป็น openclaw qa <runner> และเขียน scenario ภายใต้ qa/scenarios/
ชุดทดสอบ (อะไรทำงานที่ไหน)
ให้มองชุดทดสอบเป็น "ความสมจริงที่เพิ่มขึ้น" (และความไม่เสถียร/ต้นทุนที่เพิ่มขึ้น):
Unit / integration (ค่าเริ่มต้น)
- คำสั่ง:
pnpm test - คอนฟิก: การรันแบบไม่เจาะจงเป้าหมายใช้ชุด shard
vitest.full-*.config.tsและอาจขยาย shard แบบหลายโปรเจกต์เป็นคอนฟิกต่อโปรเจกต์เพื่อการจัดตารางแบบขนาน - ไฟล์: inventory ของ core/unit ภายใต้
src/**/*.test.ts,packages/**/*.test.tsและtest/**/*.test.ts; การทดสอบ unit ของ UI ทำงานใน shardunit-uiเฉพาะ - ขอบเขต:
- การทดสอบ unit ล้วน
- การทดสอบ integration ในโปรเซส (การยืนยันตัวตน Gateway, การกำหนดเส้นทาง, tooling, การแยกวิเคราะห์, คอนฟิก)
- regression ที่กำหนดผลได้สำหรับบั๊กที่รู้จัก
- ความคาดหวัง:
- ทำงานใน CI
- ไม่ต้องใช้คีย์จริง
- ควรเร็วและเสถียร
- การทดสอบ resolver และ public-surface loader ต้องพิสูจน์พฤติกรรม fallback ของ
api.jsและruntime-api.jsในวงกว้างด้วย fixture plugin ขนาดเล็กที่สร้างขึ้น ไม่ใช่ API ของซอร์ส plugin ที่ bundled จริง การโหลด API ของ plugin จริงควรอยู่ใน ชุด contract/integration ที่ plugin เป็นเจ้าของ
Projects, shards, and scoped lanes
pnpm testแบบไม่เจาะจงเป้าหมายรันคอนฟิก shard ขนาดเล็กสิบสองชุด (core-unit-fast,core-unit-src,core-unit-security,core-unit-ui,core-unit-support,core-support-boundary,core-contracts,core-bundled,core-runtime,agentic,auto-reply,extensions) แทนโปรเซส root-project แบบ native ขนาดยักษ์ชุดเดียว วิธีนี้ลด RSS สูงสุดบนเครื่องที่มีโหลด และป้องกันไม่ให้งาน auto-reply/extension เบียดชุดทดสอบที่ไม่เกี่ยวข้องpnpm test --watchยังคงใช้กราฟโปรเจกต์vitest.config.tsroot แบบ native เพราะ loop watch แบบหลาย shard ไม่เหมาะกับการใช้งานจริงpnpm test,pnpm test:watchและpnpm test:perf:importsส่งเป้าหมายไฟล์/ไดเรกทอรีที่ระบุชัดผ่าน lane แบบ scoped ก่อน ดังนั้นpnpm test extensions/discord/src/monitor/message-handler.preflight.test.tsจะไม่ต้องจ่ายต้นทุนการเริ่มต้นของ root project ทั้งหมดpnpm test:changedขยาย path ของ git ที่เปลี่ยนเป็น lane แบบ scoped ที่ประหยัดตามค่าเริ่มต้น: การแก้ไข test โดยตรง, ไฟล์ sibling*.test.ts, การแมปซอร์สที่ระบุชัด และ dependent ใน import-graph ภายในเครื่อง การแก้ไข config/setup/package จะไม่รันการทดสอบแบบกว้าง เว้นแต่คุณจะใช้OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changedอย่างชัดเจนpnpm check:changedคือ gate การตรวจสอบภายในเครื่องแบบ smart ตามปกติสำหรับงานแคบ มันจำแนก diff เป็น core, การทดสอบ core, extensions, การทดสอบ extension, apps, docs, metadata ของ release, tooling สำหรับ Docker แบบ live และ tooling จากนั้นรันคำสั่ง typecheck, lint และ guard ที่ตรงกัน มันไม่รันการทดสอบ Vitest; ให้เรียกpnpm test:changedหรือpnpm test <target>ที่ระบุชัดสำหรับหลักฐานการทดสอบ การ bump เวอร์ชันที่เป็น metadata ของ release เท่านั้นจะรันการตรวจสอบเวอร์ชัน/config/root-dependency แบบเจาะจง พร้อม guard ที่ปฏิเสธการเปลี่ยนแปลง package นอกฟิลด์เวอร์ชันระดับบนสุด- การแก้ไข harness ACP ของ Docker แบบ live จะรันการตรวจสอบที่โฟกัส: syntax ของ shell สำหรับสคริปต์ auth ของ Docker แบบ live และ dry-run ของ scheduler Docker แบบ live การเปลี่ยนแปลง
package.jsonจะถูกรวมเฉพาะเมื่อ diff จำกัดอยู่ที่scripts["test:docker:live-*"]; การแก้ไข dependency, export, version และพื้นผิว package อื่นยังคงใช้ guard ที่กว้างกว่า - การทดสอบ unit แบบ import-light จาก agents, commands, plugins, ตัวช่วย auto-reply,
plugin-sdkและพื้นที่ยูทิลิตีล้วนที่คล้ายกัน จะถูกส่งผ่าน laneunit-fastซึ่งข้ามtest/setup-openclaw-runtime.ts; ไฟล์ที่มี stateful/runtime-heavy ยังคงอยู่บน lane เดิม - ไฟล์ซอร์สตัวช่วย
plugin-sdkและcommandsที่เลือกไว้บางไฟล์ยังแมปการรัน changed-mode ไปยังการทดสอบ sibling ที่ระบุชัดใน lane เบาเหล่านั้นด้วย ดังนั้นการแก้ไขตัวช่วยจะหลีกเลี่ยงการรันชุดทดสอบหนักทั้งหมดของไดเรกทอรีนั้นซ้ำ auto-replyมี bucket เฉพาะสำหรับตัวช่วย core ระดับบนสุด, การทดสอบ integrationreply.*ระดับบนสุด และ subtreesrc/auto-reply/reply/**CI ยังแยก subtree reply เป็น shard ของ agent-runner, dispatch และ commands/state-routing เพิ่มเติม เพื่อไม่ให้ bucket ที่ import หนักหนึ่งชุดเป็นเจ้าของ tail ของ Node ทั้งหมด- CI สำหรับ PR/main ปกติจงใจข้าม extension batch sweep และ shard
agentic-pluginsที่ใช้เฉพาะ release การตรวจสอบ Full Release Validation จะ dispatch workflow ลูกPlugin Prereleaseแยกต่างหากสำหรับชุดทดสอบที่หนักด้าน plugin/extension เหล่านั้นบน release candidate
Embedded runner coverage
- เมื่อคุณเปลี่ยน input สำหรับการค้นพบ message-tool หรือ context runtime ของ compaction ให้คง coverage ทั้งสองระดับไว้
- เพิ่ม regression ของตัวช่วยที่โฟกัสสำหรับขอบเขต routing และ normalization แบบล้วน
- รักษาชุด integration ของ embedded runner ให้ทำงานดี:
src/agents/pi-embedded-runner/compact.hooks.test.ts,src/agents/pi-embedded-runner/run.overflow-compaction.test.tsและsrc/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts - ชุดเหล่านั้นตรวจสอบว่า scoped ids และพฤติกรรม compaction ยังคงไหล
ผ่าน path
run.ts/compact.tsจริง; การทดสอบเฉพาะตัวช่วย ไม่ใช่สิ่งทดแทนที่เพียงพอสำหรับ path integration เหล่านั้น
Vitest pool and isolation defaults
- คอนฟิก Vitest พื้นฐานตั้งค่าเริ่มต้นเป็น
threads - คอนฟิก Vitest ที่ใช้ร่วมกันกำหนด
isolate: falseและใช้ runner แบบไม่ isolated ทั่วทั้งโปรเจกต์ root, e2e และคอนฟิก live - lane UI ของ root คง setup และ optimizer
jsdomไว้ แต่ก็รันบน runner แบบไม่ isolated ที่ใช้ร่วมกันเช่นกัน - shard
pnpm testแต่ละชุดสืบทอดค่าเริ่มต้นthreads+isolate: falseเดียวกันจากคอนฟิก Vitest ที่ใช้ร่วมกัน scripts/run-vitest.mjsเพิ่ม--no-maglevสำหรับโปรเซส Node ลูกของ Vitest ตามค่าเริ่มต้นเพื่อลด V8 compile churn ระหว่างการรันภายในเครื่องขนาดใหญ่ ตั้งค่าOPENCLAW_VITEST_ENABLE_MAGLEV=1เพื่อเปรียบเทียบกับพฤติกรรม V8 มาตรฐาน
Fast local iteration
pnpm changed:lanesแสดงว่า diff เรียก lane สถาปัตยกรรมใดบ้าง- hook pre-commit ทำเฉพาะ formatting เท่านั้น มัน stage ไฟล์ที่จัดรูปแบบแล้วใหม่ และ ไม่รัน lint, typecheck หรือการทดสอบ
- รัน
pnpm check:changedอย่างชัดเจนก่อน handoff หรือ push เมื่อคุณ ต้องใช้ gate การตรวจสอบภายในเครื่องแบบ smart pnpm test:changedส่งผ่าน lane แบบ scoped ที่ประหยัดตามค่าเริ่มต้น ใช้OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changedเฉพาะเมื่อ agent ตัดสินว่าการแก้ไข harness, config, package หรือ contract ต้องการ coverage ของ Vitest ที่กว้างกว่าจริงๆpnpm test:maxและpnpm test:changed:maxคงพฤติกรรม routing เดิมไว้ เพียงแต่มี worker cap ที่สูงกว่า- การปรับขนาด worker ภายในเครื่องโดยอัตโนมัตินั้นตั้งใจให้ conservative และลดระดับลง เมื่อ load average ของโฮสต์สูงอยู่แล้ว ดังนั้นการรัน Vitest หลายชุดพร้อมกัน จึงสร้างผลกระทบน้อยลงตามค่าเริ่มต้น
- คอนฟิก Vitest พื้นฐานกำหนด projects/config files เป็น
forceRerunTriggersเพื่อให้การรันซ้ำ changed-mode ยังคงถูกต้องเมื่อ wiring ของ test เปลี่ยน - คอนฟิกคง
OPENCLAW_VITEST_FS_MODULE_CACHEให้เปิดใช้งานบนโฮสต์ที่รองรับ ตั้งค่าOPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/pathหากคุณต้องการ ตำแหน่ง cache ที่ระบุชัดหนึ่งตำแหน่งสำหรับการ profiling โดยตรง
Perf debugging
pnpm test:perf:importsเปิดใช้รายงาน import-duration ของ Vitest พร้อม เอาต์พุต import-breakdownpnpm test:perf:imports:changedจำกัดขอบเขตมุมมอง profiling เดียวกันไปยัง ไฟล์ที่เปลี่ยนตั้งแต่origin/main- ข้อมูล timing ของ shard ถูกเขียนไปที่
.artifacts/vitest-shard-timings.jsonการรันทั้งคอนฟิกใช้ path ของคอนฟิกเป็น key; shard ของ CI แบบ include-pattern จะต่อท้ายชื่อ shard เพื่อให้ติดตาม shard ที่ถูกกรองได้ แยกกัน - เมื่อการทดสอบที่ร้อนหนึ่งรายการยังคงใช้เวลาส่วนใหญ่กับ startup imports
ให้เก็บ dependency ที่หนักไว้หลัง seam
*.runtime.tsภายในเครื่องที่แคบ และ mock seam นั้นโดยตรงแทนการ deep-import ตัวช่วย runtime เพียง เพื่อส่งต่อผ่านvi.mock(...) pnpm test:perf:changed:bench -- --ref <git-ref>เปรียบเทียบtest:changedที่ routed กับ path root-project แบบ native สำหรับ diff ที่ commit แล้วนั้น และพิมพ์ wall time พร้อม RSS สูงสุดบน macOSpnpm test:perf:changed:bench -- --worktreebenchmark tree ปัจจุบัน ที่ยัง dirty โดย routing รายการไฟล์ที่เปลี่ยนผ่านscripts/test-projects.mjsและคอนฟิก Vitest ของ rootpnpm test:perf:profile:mainเขียน CPU profile ของ main-thread สำหรับ overhead การเริ่มต้นและ transform ของ Vitest/Vitepnpm test:perf:profile:runnerเขียน CPU+heap profiles ของ runner สำหรับ ชุด unit โดยปิด file parallelism
Stability (gateway)
- คำสั่ง:
pnpm test:stability:gateway - คอนฟิก:
vitest.gateway.config.ts, บังคับให้ใช้ worker หนึ่งตัว - ขอบเขต:
- เริ่ม Gateway แบบ loopback จริงพร้อมเปิด diagnostics ตามค่าเริ่มต้น
- ขับ churn ของข้อความ Gateway สังเคราะห์, memory และ large-payload ผ่าน path เหตุการณ์ diagnostic
- query
diagnostics.stabilityผ่าน Gateway WS RPC - ครอบคลุมตัวช่วย persistence ของ diagnostic stability bundle
- assert ว่า recorder ยังคงมีขอบเขต, ตัวอย่าง RSS สังเคราะห์อยู่ต่ำกว่า pressure budget และ queue depth ต่อ session ระบายกลับเป็นศูนย์
- ความคาดหวัง:
- ปลอดภัยสำหรับ CI และไม่ต้องใช้คีย์
- lane แคบสำหรับการติดตาม stability-regression ไม่ใช่ตัวแทนของชุด Gateway เต็ม
E2E (gateway smoke)
- คำสั่ง:
pnpm test:e2e - Config:
vitest.e2e.config.ts - ไฟล์:
src/**/*.e2e.test.ts,test/**/*.e2e.test.tsและการทดสอบ E2E ของ bundled-Plugin ภายใต้extensions/ - ค่าเริ่มต้นของ Runtime:
- ใช้ Vitest
threadsพร้อมisolate: falseให้ตรงกับส่วนอื่นของ repo - ใช้ worker แบบปรับตามสภาพแวดล้อม (CI: สูงสุด 2, local: ค่าเริ่มต้น 1)
- ทำงานในโหมดเงียบเป็นค่าเริ่มต้นเพื่อลด overhead ของ console I/O
- ใช้ Vitest
- override ที่มีประโยชน์:
OPENCLAW_E2E_WORKERS=<n>เพื่อบังคับจำนวน worker (จำกัดสูงสุดที่ 16)OPENCLAW_E2E_VERBOSE=1เพื่อเปิดใช้ output ของ console แบบละเอียดอีกครั้ง
- ขอบเขต:
- พฤติกรรม end-to-end ของ Gateway หลาย instance
- พื้นผิว WebSocket/HTTP, การจับคู่ Node และ networking ที่หนักขึ้น
- ความคาดหวัง:
- ทำงานใน CI (เมื่อเปิดใช้ใน pipeline)
- ไม่ต้องใช้ key จริง
- มีส่วนที่เคลื่อนไหวมากกว่าการทดสอบ unit (อาจช้ากว่า)
E2E: smoke ของ backend OpenShell
- คำสั่ง:
pnpm test:e2e:openshell - ไฟล์:
extensions/openshell/src/backend.e2e.test.ts - ขอบเขต:
- เริ่ม Gateway OpenShell แบบแยก isolated บน host ผ่าน Docker
- สร้าง sandbox จาก Dockerfile local ชั่วคราว
- ทดสอบ backend OpenShell ของ OpenClaw ผ่าน
sandbox ssh-configจริง + SSH exec - ตรวจสอบพฤติกรรม filesystem แบบ remote-canonical ผ่าน sandbox fs bridge
- ความคาดหวัง:
- ใช้แบบ opt-in เท่านั้น; ไม่เป็นส่วนหนึ่งของการรัน
pnpm test:e2eค่าเริ่มต้น - ต้องมี CLI
openshellในเครื่องพร้อม Docker daemon ที่ใช้งานได้ - ใช้
HOME/XDG_CONFIG_HOMEแบบ isolated แล้วทำลาย Gateway และ sandbox สำหรับการทดสอบ
- ใช้แบบ opt-in เท่านั้น; ไม่เป็นส่วนหนึ่งของการรัน
- override ที่มีประโยชน์:
OPENCLAW_E2E_OPENSHELL=1เพื่อเปิดใช้การทดสอบเมื่อรันชุด e2e ที่กว้างขึ้นด้วยตนเองOPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshellเพื่อชี้ไปยัง binary หรือ wrapper script ของ CLI ที่ไม่ใช่ค่าเริ่มต้น
Live (ผู้ให้บริการจริง + โมเดลจริง)
- คำสั่ง:
pnpm test:live - Config:
vitest.live.config.ts - ไฟล์:
src/**/*.live.test.ts,test/**/*.live.test.tsและการทดสอบ live ของ bundled-Plugin ภายใต้extensions/ - ค่าเริ่มต้น: เปิดใช้ โดย
pnpm test:live(ตั้งค่าOPENCLAW_LIVE_TEST=1) - ขอบเขต:
- "ผู้ให้บริการ/โมเดลนี้ใช้งานได้จริง วันนี้ ด้วยข้อมูลรับรองจริงหรือไม่?"
- ตรวจจับการเปลี่ยนแปลง format ของผู้ให้บริการ, พฤติกรรมเฉพาะของ tool-calling, ปัญหา auth และพฤติกรรม rate limit
- ความคาดหวัง:
- ตั้งใจให้ไม่เสถียรสำหรับ CI (network จริง, policy จริงของผู้ให้บริการ, quota, outage)
- มีค่าใช้จ่าย / ใช้ rate limit
- ควรรัน subset ที่แคบลงแทน "ทุกอย่าง"
- การรัน live จะ source
~/.profileเพื่อดึง API key ที่ขาดอยู่ - โดยค่าเริ่มต้น การรัน live ยังคง isolate
HOMEและคัดลอก config/auth material ไปยัง test home ชั่วคราว เพื่อให้ fixture ของ unit ไม่สามารถแก้ไข~/.openclawจริงของคุณได้ - ตั้งค่า
OPENCLAW_LIVE_USE_REAL_HOME=1เฉพาะเมื่อคุณตั้งใจให้การทดสอบ live ใช้ home directory จริงของคุณ - ตอนนี้
pnpm test:liveใช้โหมดที่เงียบขึ้นเป็นค่าเริ่มต้น: ยังคง output ความคืบหน้า[live] ...ไว้ แต่ซ่อน notice เพิ่มเติมของ~/.profileและ mute log bootstrap ของ Gateway/ข้อความ Bonjour ตั้งค่าOPENCLAW_LIVE_TEST_QUIET=0หากต้องการ log startup แบบเต็มกลับมา - การหมุนเวียน API key (เฉพาะผู้ให้บริการ): ตั้งค่า
*_API_KEYSด้วยรูปแบบ comma/semicolon หรือ*_API_KEY_1,*_API_KEY_2(เช่นOPENAI_API_KEYS,ANTHROPIC_API_KEYS,GEMINI_API_KEYS) หรือ override ต่อ live ผ่านOPENCLAW_LIVE_*_KEY; การทดสอบจะ retry เมื่อได้รับ response ของ rate limit - output ความคืบหน้า/Heartbeat:
- ตอนนี้ชุด live จะ emit บรรทัดความคืบหน้าไปยัง stderr เพื่อให้เห็นว่า call ไปยังผู้ให้บริการที่ใช้เวลานานยัง active อยู่ แม้การ capture console ของ Vitest จะเงียบ
vitest.live.config.tsปิดการดัก console ของ Vitest เพื่อให้บรรทัดความคืบหน้าของผู้ให้บริการ/Gateway stream ทันทีระหว่างการรัน live- ปรับ Heartbeat ของ direct-model ด้วย
OPENCLAW_LIVE_HEARTBEAT_MS - ปรับ Heartbeat ของ Gateway/probe ด้วย
OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS
ควรรันชุดใด?
ใช้ตารางตัดสินใจนี้:
- แก้ logic/tests: รัน
pnpm test(และpnpm test:coverageหากคุณเปลี่ยนเยอะ) - แตะ Gateway networking / WS protocol / pairing: เพิ่ม
pnpm test:e2e - debug "บอทของฉันล่ม" / failure เฉพาะผู้ให้บริการ / tool calling: รัน
pnpm test:liveแบบแคบลง
การทดสอบ Live (แตะ network)
สำหรับ matrix ของโมเดล live, smoke ของ backend CLI, smoke ของ ACP, harness ของ Codex app-server และการทดสอบ live ของ media-provider ทั้งหมด (Deepgram, BytePlus, ComfyUI, image, music, video, media harness) - รวมถึงการจัดการ credential สำหรับการรัน live - ดู การทดสอบชุด live สำหรับ checklist เฉพาะด้านการอัปเดตและ การตรวจสอบ Plugin ดู การทดสอบการอัปเดตและ Plugin
Docker runner (การตรวจสอบ "ใช้งานได้ใน Linux" แบบ optional)
Docker runner เหล่านี้แบ่งเป็นสองกลุ่ม:
- runner โมเดล live:
test:docker:live-modelsและtest:docker:live-gatewayรันเฉพาะไฟล์ live ที่ตรงกับ profile-key ของตัวเองภายใน Docker image ของ repo (src/agents/models.profiles.live.test.tsและsrc/gateway/gateway-models.profiles.live.test.ts) โดย mount config dir และ workspace local ของคุณ (และ source~/.profileหาก mount ไว้) entrypoint local ที่ตรงกันคือtest:live:models-profilesและtest:live:gateway-profiles - Docker live runner ใช้ smoke cap ที่เล็กกว่าเป็นค่าเริ่มต้นเพื่อให้การ sweep Docker แบบเต็มยังใช้งานได้จริง:
test:docker:live-modelsใช้ค่าเริ่มต้นเป็นOPENCLAW_LIVE_MAX_MODELS=12และtest:docker:live-gatewayใช้ค่าเริ่มต้นเป็นOPENCLAW_LIVE_GATEWAY_SMOKE=1,OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8,OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000และOPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000override env var เหล่านี้เมื่อคุณ ต้องการ scan ที่ใหญ่และครอบคลุมกว่าอย่างชัดเจน test:docker:allbuild Docker image สำหรับ live หนึ่งครั้งผ่านtest:docker:live-build, pack OpenClaw หนึ่งครั้งเป็น npm tarball ผ่านscripts/package-openclaw-for-docker.mjsจากนั้น build/reuse imagescripts/e2e/Dockerfileสองรายการ image แบบ bare เป็นเพียง runner Node/Git สำหรับ lane install/update/plugin-dependency; lane เหล่านั้น mount tarball ที่ build ไว้ล่วงหน้า image แบบ functional ติดตั้ง tarball เดียวกันลงใน/appสำหรับ lane ฟังก์ชันของแอปที่ build แล้ว definition ของ Docker lane อยู่ในscripts/lib/docker-e2e-scenarios.mjs; logic ของ planner อยู่ในscripts/lib/docker-e2e-plan.mjs;scripts/test-docker-all.mjsexecute plan ที่เลือก aggregate ใช้ scheduler local แบบ weighted:OPENCLAW_DOCKER_ALL_PARALLELISMควบคุม process slot ส่วน resource cap ป้องกันไม่ให้ lane ที่หนักอย่าง live, npm-install และ multi-service เริ่มพร้อมกันทั้งหมด หาก lane เดียวหนักกว่า cap ที่ active อยู่ scheduler ยังสามารถเริ่ม lane นั้นได้เมื่อ pool ว่าง แล้วให้รันเดี่ยวต่อไปจนกว่าจะมี capacity กลับมาอีกครั้ง ค่าเริ่มต้นคือ 10 slot,OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9,OPENCLAW_DOCKER_ALL_NPM_LIMIT=10และOPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7; ปรับOPENCLAW_DOCKER_ALL_WEIGHT_LIMITหรือOPENCLAW_DOCKER_ALL_DOCKER_LIMITเฉพาะเมื่อ host Docker มี headroom มากขึ้น runner จะทำ Docker preflight เป็นค่าเริ่มต้น, ลบ container OpenClaw E2E ที่ค้างอยู่, พิมพ์สถานะทุก 30 วินาที, เก็บ timing ของ lane ที่สำเร็จไว้ใน.artifacts/docker-tests/lane-timings.jsonและใช้ timing เหล่านั้นเพื่อเริ่ม lane ที่ยาวกว่าก่อนในการรันครั้งถัดไป ใช้OPENCLAW_DOCKER_ALL_DRY_RUN=1เพื่อพิมพ์ manifest ของ lane แบบ weighted โดยไม่ build หรือรัน Docker หรือใช้node scripts/test-docker-all.mjs --plan-jsonเพื่อพิมพ์ plan ของ CI สำหรับ lane ที่เลือก, ความต้องการ package/image และ credentialPackage Acceptanceคือ gate package แบบ GitHub-native สำหรับ "tarball ที่ติดตั้งได้นี้ใช้งานได้เป็น product หรือไม่?" โดย resolve candidate package หนึ่งรายการจากsource=npm,source=ref,source=urlหรือsource=artifact, upload เป็นpackage-under-testจากนั้นรัน lane Docker E2E ที่ reusable กับ tarball นั้นอย่างตรงตัว แทนการ repack ref ที่เลือก profile เรียงตามความกว้าง:smoke,package,productและfullดู การทดสอบการอัปเดตและ Plugin สำหรับ contract ของ package/update/Plugin, matrix ของ published-upgrade survivor, ค่าเริ่มต้นของ release และการ triage failure- การตรวจสอบ build และ release จะรัน
scripts/check-cli-bootstrap-imports.mjsหลัง tsdown guard จะเดิน graph ที่ build แล้วแบบ static จากdist/entry.jsและdist/cli/run-main.jsและ fail หาก startup ก่อน dispatch import dependency ของ package เช่น Commander, prompt UI, undici หรือ logging ก่อน command dispatch; นอกจากนี้ยังคุม chunk การรัน Gateway ที่ bundle แล้วให้อยู่ใน budget และปฏิเสธ static import ของ cold Gateway path ที่รู้จัก smoke ของ CLI แบบ packaged ยังครอบคลุม root help, onboard help, doctor help, status, config schema และคำสั่ง model-list - compatibility แบบ legacy ของ Package Acceptance ถูกจำกัดไว้ที่
2026.4.25(รวม2026.4.25-beta.*) จนถึง cutoff นั้น harness จะยอมรับเฉพาะช่องว่างของ metadata ใน package ที่เคย ship แล้ว: รายการ private QA inventory ที่ถูก omit, ไม่มีgateway install --wrapper, ไม่มีไฟล์ patch ใน git fixture ที่ derived จาก tarball, ไม่มีupdate.channelที่ persist ไว้, ตำแหน่ง legacy ของ plugin install-record, ไม่มีการ persist marketplace install-record และการ migrate config metadata ระหว่างplugins updateสำหรับ package หลัง2026.4.25path เหล่านั้นจะเป็น failure แบบเข้มงวด - runner smoke ของ container:
test:docker:openwebui,test:docker:onboard,test:docker:npm-onboard-channel-agent,test:docker:update-channel-switch,test:docker:upgrade-survivor,test:docker:published-upgrade-survivor,test:docker:session-runtime-context,test:docker:agents-delete-shared-workspace,test:docker:gateway-network,test:docker:browser-cdp-snapshot,test:docker:mcp-channels,test:docker:pi-bundle-mcp-tools,test:docker:cron-mcp-cleanup,test:docker:plugins,test:docker:plugin-update,test:docker:plugin-lifecycle-matrixและtest:docker:config-reloadboot container จริงหนึ่งตัวหรือมากกว่า และตรวจสอบ path integration ระดับสูง
Docker runner ของโมเดล live ยัง bind-mount เฉพาะ CLI auth home ที่จำเป็น (หรือทั้งหมดที่รองรับเมื่อการรันไม่ได้ถูกทำให้แคบลง) แล้วคัดลอกไปยัง home ของ container ก่อนการรัน เพื่อให้ OAuth ของ external-CLI refresh token ได้โดยไม่แก้ไข auth store ของ host:
- โมเดลโดยตรง:
pnpm test:docker:live-models(สคริปต์:scripts/test-live-models-docker.sh) - ACP bind smoke:
pnpm test:docker:live-acp-bind(สคริปต์:scripts/test-live-acp-bind-docker.sh; ครอบคลุม Claude, Codex และ Gemini ตามค่าเริ่มต้น พร้อมการครอบคลุม Droid/OpenCode แบบเข้มงวดผ่านpnpm test:docker:live-acp-bind:droidและpnpm test:docker:live-acp-bind:opencode) - CLI backend smoke:
pnpm test:docker:live-cli-backend(สคริปต์:scripts/test-live-cli-backend-docker.sh) - Codex app-server harness smoke:
pnpm test:docker:live-codex-harness(สคริปต์:scripts/test-live-codex-harness-docker.sh) - Gateway + เอเจนต์ dev:
pnpm test:docker:live-gateway(สคริปต์:scripts/test-live-gateway-models-docker.sh) - Observability smoke:
pnpm qa:otel:smokeเป็นเลน private QA source-checkout ตั้งใจไม่รวมไว้ในเลน Docker release ของแพ็กเกจ เพราะ npm tarball ไม่รวม QA Lab - Open WebUI live smoke:
pnpm test:docker:openwebui(สคริปต์:scripts/e2e/openwebui-docker.sh) - วิซาร์ด onboarding (TTY, การ scaffold เต็มรูปแบบ):
pnpm test:docker:onboard(สคริปต์:scripts/e2e/onboard-docker.sh) - Npm tarball onboarding/channel/agent smoke:
pnpm test:docker:npm-onboard-channel-agentติดตั้ง OpenClaw tarball ที่แพ็กแล้วแบบ global ใน Docker, กำหนดค่า OpenAI ผ่าน onboarding แบบ env-ref พร้อม Telegram ตามค่าเริ่มต้น, รัน doctor และรันหนึ่งเทิร์นเอเจนต์ OpenAI แบบ mock ใช้ tarball ที่สร้างไว้ล่วงหน้าซ้ำได้ด้วยOPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz, ข้ามการ rebuild บน host ด้วยOPENCLAW_NPM_ONBOARD_HOST_BUILD=0หรือเปลี่ยน channel ด้วยOPENCLAW_NPM_ONBOARD_CHANNEL=discordหรือOPENCLAW_NPM_ONBOARD_CHANNEL=slack - Update channel switch smoke:
pnpm test:docker:update-channel-switchติดตั้ง OpenClaw tarball ที่แพ็กแล้วแบบ global ใน Docker, สลับจากแพ็กเกจstableไปเป็น gitdev, ตรวจสอบ channel ที่ persist ไว้และการทำงานหลังอัปเดตของ plugin จากนั้นสลับกลับเป็นแพ็กเกจstableและตรวจสอบสถานะการอัปเดต - Upgrade survivor smoke:
pnpm test:docker:upgrade-survivorติดตั้ง OpenClaw tarball ที่แพ็กแล้วทับ fixture ผู้ใช้เก่าแบบ dirty ที่มีเอเจนต์, การกำหนดค่า channel, allowlist ของ plugin, สถานะ dependency ของ plugin ที่เก่า และไฟล์ workspace/session ที่มีอยู่ รันการอัปเดตแพ็กเกจพร้อม doctor แบบ non-interactive โดยไม่มี live provider หรือ channel keys จากนั้นเริ่ม Gateway แบบ loopback และตรวจสอบการคงไว้ของ config/state รวมถึง budget ของ startup/status - Published upgrade survivor smoke:
pnpm test:docker:published-upgrade-survivorติดตั้งopenclaw@latestตามค่าเริ่มต้น, seed ไฟล์ผู้ใช้เดิมที่สมจริง, กำหนดค่า baseline นั้นด้วย baked command recipe, ตรวจสอบ config ที่ได้, อัปเดต install ที่ publish แล้วนั้นไปยัง candidate tarball, รัน doctor แบบ non-interactive, เขียน.artifacts/upgrade-survivor/summary.jsonจากนั้นเริ่ม Gateway แบบ loopback และตรวจสอบ intent ที่กำหนดค่าไว้, การคงไว้ของ state, startup,/healthz,/readyzและ budget ของสถานะ RPC override baseline หนึ่งรายการได้ด้วยOPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC, ขอให้ aggregate scheduler ขยาย baseline local ที่เจาะจงด้วยOPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECSเช่น[email protected] [email protected] [email protected]และขยาย fixture ที่มีรูปร่างตาม issue ด้วยOPENCLAW_UPGRADE_SURVIVOR_SCENARIOSเช่นreported-issues; ชุด reported-issues รวมconfigured-plugin-installsสำหรับการซ่อมการติดตั้ง OpenClaw plugin ภายนอกโดยอัตโนมัติ Package Acceptance เปิดเผยสิ่งเหล่านี้เป็นpublished_upgrade_survivor_baseline,published_upgrade_survivor_baselinesและpublished_upgrade_survivor_scenarios, resolve โทเค็น meta baseline เช่นlast-stable-4หรือall-since-2026.4.23และ Full Release Validation ขยาย package gate แบบ release-soak เป็นlast-stable-4 2026.4.23 2026.5.2 2026.4.15พร้อมreported-issues - Session runtime context smoke:
pnpm test:docker:session-runtime-contextตรวจสอบการ persist transcript ของ hidden runtime context พร้อมการซ่อมโดย doctor สำหรับ branch prompt-rewrite ที่ซ้ำกันซึ่งได้รับผลกระทบ - Bun global install smoke:
bash scripts/e2e/bun-global-install-smoke.shแพ็ก tree ปัจจุบัน, ติดตั้งด้วยbun install -gใน home ที่แยกไว้ และตรวจสอบว่าopenclaw infer image providers --jsonส่งคืน bundled image providers แทนที่จะค้าง ใช้ tarball ที่สร้างไว้ล่วงหน้าซ้ำได้ด้วยOPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz, ข้าม host build ด้วยOPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0หรือคัดลอกdist/จาก Docker image ที่ build แล้วด้วยOPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local - Installer Docker smoke:
bash scripts/test-install-sh-docker.shใช้ npm cache เดียวร่วมกันระหว่างคอนเทนเนอร์ root, update และ direct-npm ของมัน Update smoke ใช้ค่าเริ่มต้นเป็น npmlatestเป็น stable baseline ก่อนอัปเกรดเป็น candidate tarball override ได้ด้วยOPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22ในเครื่อง หรือด้วย inputupdate_baseline_versionของ workflow Install Smoke บน GitHub การตรวจสอบ installer แบบ non-root เก็บ npm cache ที่แยกไว้ เพื่อไม่ให้รายการ cache ที่ root เป็นเจ้าของปิดบังพฤติกรรมการติดตั้งแบบ user-local ตั้งค่าOPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cacheเพื่อใช้ cache root/update/direct-npm ซ้ำในการรันซ้ำในเครื่อง - Install Smoke CI ข้ามการอัปเดต direct-npm global ที่ซ้ำกันด้วย
OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1; รันสคริปต์ในเครื่องโดยไม่มี env นั้นเมื่อจำเป็นต้องครอบคลุมการใช้npm install -gโดยตรง - Agents delete shared workspace CLI smoke:
pnpm test:docker:agents-delete-shared-workspace(สคริปต์:scripts/e2e/agents-delete-shared-workspace-docker.sh) build image จาก root Dockerfile ตามค่าเริ่มต้น, seed เอเจนต์สองตัวพร้อม workspace หนึ่งรายการใน container home ที่แยกไว้, รันagents delete --jsonและตรวจสอบ JSON ที่ถูกต้องพร้อมพฤติกรรมการเก็บ workspace ไว้ ใช้ image install-smoke ซ้ำด้วยOPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1 - เครือข่าย Gateway (สองคอนเทนเนอร์, WS auth + health):
pnpm test:docker:gateway-network(สคริปต์:scripts/e2e/gateway-network-docker.sh) - Browser CDP snapshot smoke:
pnpm test:docker:browser-cdp-snapshot(สคริปต์:scripts/e2e/browser-cdp-snapshot-docker.sh) build image E2E จาก source พร้อม layer ของ Chromium, เริ่ม Chromium ด้วย raw CDP, รันbrowser doctor --deepและตรวจสอบว่า snapshot ของ role จาก CDP ครอบคลุม URL ของลิงก์, clickable ที่ cursor-promoted, iframe refs และ metadata ของ frame - OpenAI Responses web_search minimal reasoning regression:
pnpm test:docker:openai-web-search-minimal(สคริปต์:scripts/e2e/openai-web-search-minimal-docker.sh) รันเซิร์ฟเวอร์ OpenAI แบบ mock ผ่าน Gateway, ตรวจสอบว่าweb_searchเพิ่มreasoning.effortจากminimalเป็นlowจากนั้นบังคับให้ provider schema reject และตรวจสอบว่ารายละเอียดดิบปรากฏใน log ของ Gateway - MCP channel bridge (seeded Gateway + stdio bridge + raw Claude notification-frame smoke):
pnpm test:docker:mcp-channels(สคริปต์:scripts/e2e/mcp-channels-docker.sh) - เครื่องมือ MCP ใน bundle ของ Pi (เซิร์ฟเวอร์ stdio MCP จริง + embedded Pi profile allow/deny smoke):
pnpm test:docker:pi-bundle-mcp-tools(สคริปต์:scripts/e2e/pi-bundle-mcp-tools-docker.sh) - Cron/subagent MCP cleanup (Gateway จริง + การ teardown ของ child stdio MCP หลังการรัน cron แบบ isolated และ subagent แบบ one-shot):
pnpm test:docker:cron-mcp-cleanup(สคริปต์:scripts/e2e/cron-mcp-cleanup-docker.sh) - Plugins (install/update smoke สำหรับ local path,
file:, npm registry ที่มี dependency แบบ hoisted, git moving refs, ClawHub kitchen-sink, marketplace updates และการ enable/inspect Claude-bundle):pnpm test:docker:plugins(สคริปต์:scripts/e2e/plugins-docker.sh) ตั้งค่าOPENCLAW_PLUGINS_E2E_CLAWHUB=0เพื่อข้ามบล็อก ClawHub หรือ override คู่ package/runtime แบบ kitchen-sink เริ่มต้นด้วยOPENCLAW_PLUGINS_E2E_CLAWHUB_SPECและOPENCLAW_PLUGINS_E2E_CLAWHUB_IDหากไม่มีOPENCLAW_CLAWHUB_URL/CLAWHUB_URLการทดสอบจะใช้เซิร์ฟเวอร์ fixture ClawHub ภายในที่แยกขาดจากภายนอก - Plugin update unchanged smoke:
pnpm test:docker:plugin-update(สคริปต์:scripts/e2e/plugin-update-unchanged-docker.sh) - Plugin lifecycle matrix smoke:
pnpm test:docker:plugin-lifecycle-matrixติดตั้ง OpenClaw tarball ที่แพ็กแล้วในคอนเทนเนอร์เปล่า, ติดตั้ง npm plugin, สลับ enable/disable, อัปเกรดและดาวน์เกรดผ่าน npm registry ในเครื่อง, ลบโค้ดที่ติดตั้งแล้ว จากนั้นตรวจสอบว่า uninstall ยังลบ stale state ได้ พร้อม log metric RSS/CPU สำหรับแต่ละช่วงของ lifecycle - Config reload metadata smoke:
pnpm test:docker:config-reload(สคริปต์:scripts/e2e/config-reload-source-docker.sh) - Plugins:
pnpm test:docker:pluginsครอบคลุม install/update smoke สำหรับ local path,file:, npm registry ที่มี dependency แบบ hoisted, git moving refs, fixture ของ ClawHub, marketplace updates และการ enable/inspect Claude-bundlepnpm test:docker:plugin-updateครอบคลุมพฤติกรรมการอัปเดตที่ไม่เปลี่ยนแปลงสำหรับ plugin ที่ติดตั้งแล้วpnpm test:docker:plugin-lifecycle-matrixครอบคลุมการติดตั้ง npm plugin พร้อมติดตาม resource, enable, disable, upgrade, downgrade และการ uninstall เมื่อโค้ดหายไป
เพื่อ prebuild และใช้ shared functional image ซ้ำด้วยตนเอง:
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local pnpm test:docker:e2e-build
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels
override image เฉพาะ suite เช่น OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE ยังมีผลเหนือกว่าเมื่อตั้งค่าไว้ เมื่อ OPENCLAW_SKIP_DOCKER_BUILD=1 ชี้ไปยัง remote shared image สคริปต์จะ pull image นั้นหากยังไม่มีในเครื่อง การทดสอบ Docker สำหรับ QR และ installer เก็บ Dockerfile ของตัวเองไว้ เพราะตรวจสอบพฤติกรรมของ package/install แทนที่จะเป็น runtime ของ built-app ที่ใช้ร่วมกัน
ตัวเรียกใช้ Docker สำหรับโมเดลสดจะ bind-mount checkout ปัจจุบันแบบอ่านอย่างเดียวด้วย และ
stage มันเข้าไปใน workdir ชั่วคราวภายในคอนเทนเนอร์ สิ่งนี้ทำให้ runtime
image มีขนาดเล็ก ขณะที่ยังคงรัน Vitest กับซอร์ส/คอนฟิกโลคัลที่ตรงกันของคุณ
ขั้นตอน staging จะข้ามแคชขนาดใหญ่ที่มีเฉพาะในเครื่องและเอาต์พุตการ build แอป เช่น
.pnpm-store, .worktrees, __openclaw_vitest__ และไดเรกทอรีเอาต์พุต .build เฉพาะแอปหรือ
Gradle เพื่อให้การรัน Docker live ไม่ใช้เวลาหลายนาทีไปกับการคัดลอก
artifact เฉพาะเครื่อง
นอกจากนี้ยังตั้งค่า OPENCLAW_SKIP_CHANNELS=1 เพื่อให้ gateway live probes ไม่เริ่ม
channel workers จริงของ Telegram/Discord/ฯลฯ ภายในคอนเทนเนอร์
test:docker:live-models ยังคงรัน pnpm test:live ดังนั้นให้ส่งผ่าน
OPENCLAW_LIVE_GATEWAY_* ด้วยเมื่อคุณต้องการจำกัดหรือยกเว้น gateway
live coverage จาก Docker lane นั้น
test:docker:openwebui เป็น smoke ความเข้ากันได้ระดับสูงกว่า: มันเริ่ม
คอนเทนเนอร์ OpenClaw gateway พร้อมเปิดใช้งาน HTTP endpoints ที่เข้ากันได้กับ OpenAI,
เริ่มคอนเทนเนอร์ Open WebUI เวอร์ชันที่ pin ไว้กับ gateway นั้น, ลงชื่อเข้าใช้ผ่าน
Open WebUI, ตรวจสอบว่า /api/models เปิดเผย openclaw/default, จากนั้นส่ง
คำขอแชทจริงผ่าน proxy /api/chat/completions ของ Open WebUI
การรันครั้งแรกอาจช้ากว่าอย่างเห็นได้ชัด เพราะ Docker อาจต้อง pull
image ของ Open WebUI และ Open WebUI อาจต้องตั้งค่า cold-start ของตัวเองให้เสร็จ
lane นี้คาดหวัง key โมเดลสดที่ใช้งานได้ และ OPENCLAW_PROFILE_FILE
(~/.profile โดยค่าเริ่มต้น) เป็นวิธีหลักในการจัดเตรียม key นั้นในการรันแบบ Dockerized
การรันที่สำเร็จจะพิมพ์ payload JSON ขนาดเล็ก เช่น { "ok": true, "model": "openclaw/default", ... }
test:docker:mcp-channels ตั้งใจให้กำหนดผลลัพธ์ได้แน่นอน และไม่ต้องใช้บัญชี
Telegram, Discord หรือ iMessage จริง มันบูตคอนเทนเนอร์ Gateway ที่ seed ไว้,
เริ่มคอนเทนเนอร์ที่สองซึ่ง spawn openclaw mcp serve, จากนั้นตรวจสอบ
การค้นหาบทสนทนาที่ route แล้ว, การอ่าน transcript, metadata ของ attachment,
พฤติกรรม live event queue, การ route การส่ง outbound และการแจ้งเตือน channel +
permission แบบ Claude ผ่านสะพาน stdio MCP จริง การตรวจสอบการแจ้งเตือน
ตรวจดูเฟรม stdio MCP ดิบโดยตรง ดังนั้น smoke จึงตรวจสอบสิ่งที่
bridge emit จริง ไม่ใช่แค่สิ่งที่ client SDK เฉพาะตัวหนึ่งบังเอิญแสดงออกมา
test:docker:pi-bundle-mcp-tools กำหนดผลลัพธ์ได้แน่นอนและไม่ต้องใช้ live
model key มัน build image Docker ของ repo, เริ่มเซิร์ฟเวอร์ probe MCP stdio จริง
ภายในคอนเทนเนอร์, materialize เซิร์ฟเวอร์นั้นผ่าน runtime MCP ของ Pi bundle
ที่ฝังอยู่, execute tool, จากนั้นตรวจสอบว่า coding และ messaging ยังคงเก็บ
tools bundle-mcp ไว้ ขณะที่ minimal และ tools.deny: ["bundle-mcp"] กรองออก
test:docker:cron-mcp-cleanup กำหนดผลลัพธ์ได้แน่นอนและไม่ต้องใช้ live model
key มันเริ่ม Gateway ที่ seed ไว้พร้อมเซิร์ฟเวอร์ probe MCP stdio จริง, รัน
cron turn แบบ isolated และ child turn แบบ one-shot ของ /subagents spawn, จากนั้นตรวจสอบว่า
process ลูก MCP exit หลังจากการรันแต่ละครั้ง
Manual ACP plain-language thread smoke (ไม่ใช่ CI):
bun scripts/dev/discord-acp-plain-language-smoke.ts --channel <discord-channel-id> ...- เก็บสคริปต์นี้ไว้สำหรับเวิร์กโฟลว์ regression/debug อาจต้องใช้อีกครั้งสำหรับการตรวจสอบ ACP thread routing ดังนั้นอย่าลบมัน
env vars ที่มีประโยชน์:
OPENCLAW_CONFIG_DIR=...(ค่าเริ่มต้น:~/.openclaw) mount ไปยัง/home/node/.openclawOPENCLAW_WORKSPACE_DIR=...(ค่าเริ่มต้น:~/.openclaw/workspace) mount ไปยัง/home/node/.openclaw/workspaceOPENCLAW_PROFILE_FILE=...(ค่าเริ่มต้น:~/.profile) mount ไปยัง/home/node/.profileและ source ก่อนรัน testsOPENCLAW_DOCKER_PROFILE_ENV_ONLY=1เพื่อตรวจสอบเฉพาะ env vars ที่ source จากOPENCLAW_PROFILE_FILEโดยใช้ไดเรกทอรี config/workspace ชั่วคราวและไม่มี external CLI auth mountsOPENCLAW_DOCKER_CLI_TOOLS_DIR=...(ค่าเริ่มต้น:~/.cache/openclaw/docker-cli-tools) mount ไปยัง/home/node/.npm-globalสำหรับการติดตั้ง CLI ที่ cache ไว้ภายใน Docker- ไดเรกทอรี/ไฟล์ auth ของ external CLI ภายใต้
$HOMEจะถูก mount แบบอ่านอย่างเดียวภายใต้/host-auth...แล้วคัดลอกเข้าไปใน/home/node/...ก่อนเริ่ม tests- ไดเรกทอรีเริ่มต้น:
.minimax - ไฟล์เริ่มต้น:
~/.codex/auth.json,~/.codex/config.toml,.claude.json,~/.claude/.credentials.json,~/.claude/settings.json,~/.claude/settings.local.json - การรัน provider ที่จำกัดขอบเขตจะ mount เฉพาะไดเรกทอรี/ไฟล์ที่จำเป็นซึ่งอนุมานจาก
OPENCLAW_LIVE_PROVIDERS/OPENCLAW_LIVE_GATEWAY_PROVIDERS - override ด้วยตนเองด้วย
OPENCLAW_DOCKER_AUTH_DIRS=all,OPENCLAW_DOCKER_AUTH_DIRS=noneหรือรายการคั่นด้วย comma เช่นOPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex
- ไดเรกทอรีเริ่มต้น:
OPENCLAW_LIVE_GATEWAY_MODELS=.../OPENCLAW_LIVE_MODELS=...เพื่อจำกัดการรันOPENCLAW_LIVE_GATEWAY_PROVIDERS=.../OPENCLAW_LIVE_PROVIDERS=...เพื่อกรอง providers ภายในคอนเทนเนอร์OPENCLAW_SKIP_DOCKER_BUILD=1เพื่อนำ imageopenclaw:local-liveที่มีอยู่มาใช้ซ้ำสำหรับการ rerun ที่ไม่ต้อง rebuildOPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1เพื่อให้แน่ใจว่า creds มาจาก profile store (ไม่ใช่ env)OPENCLAW_OPENWEBUI_MODEL=...เพื่อเลือกโมเดลที่ gateway เปิดเผยสำหรับ Open WebUI smokeOPENCLAW_OPENWEBUI_PROMPT=...เพื่อ override prompt ตรวจ nonce ที่ใช้โดย Open WebUI smokeOPENWEBUI_IMAGE=...เพื่อ override tag image Open WebUI ที่ pin ไว้
การตรวจสอบความสมเหตุสมผลของเอกสาร
รันการตรวจสอบเอกสารหลังจากแก้ไขเอกสาร: pnpm check:docs
รันการตรวจสอบ anchor ของ Mintlify แบบเต็มเมื่อคุณต้องการตรวจ heading ภายในหน้าด้วย: pnpm docs:check-links:anchors
Offline regression (ปลอดภัยสำหรับ CI)
รายการเหล่านี้คือ regression แบบ "real pipeline" โดยไม่มี providers จริง:
- Gateway tool calling (mock OpenAI, gateway จริง + agent loop):
src/gateway/gateway.test.ts(case: "runs a mock OpenAI tool call end-to-end via gateway agent loop") - Gateway wizard (WS
wizard.start/wizard.next, เขียน config + บังคับใช้ auth):src/gateway/gateway.test.ts(case: "runs wizard over ws and writes auth token config")
Agent reliability evals (skills)
เรามี tests ที่ปลอดภัยสำหรับ CI อยู่แล้วสองสามรายการซึ่งทำงานเหมือน "agent reliability evals":
- Mock tool-calling ผ่าน gateway จริง + agent loop (
src/gateway/gateway.test.ts) - Flow wizard แบบ end-to-end ที่ตรวจสอบ session wiring และผลของ config (
src/gateway/gateway.test.ts)
สิ่งที่ยังขาดสำหรับ Skills (ดู Skills):
- การตัดสินใจ: เมื่อมีการระบุ skills ใน prompt, agent เลือก skill ที่ถูกต้องหรือไม่ (หรือหลีกเลี่ยงอันที่ไม่เกี่ยวข้องหรือไม่)?
- การปฏิบัติตาม: agent อ่าน
SKILL.mdก่อนใช้และทำตามขั้นตอน/args ที่กำหนดหรือไม่? - สัญญาเวิร์กโฟลว์: สถานการณ์หลาย turn ที่ assert ลำดับ tool, การส่งต่อ session history และขอบเขต sandbox
evals ในอนาคตควรกำหนดผลลัพธ์ได้แน่นอนก่อน:
- scenario runner ที่ใช้ mock providers เพื่อ assert tool calls + order, การอ่านไฟล์ skill และ session wiring
- ชุดเล็กของสถานการณ์ที่เน้น skill (ใช้ vs หลีกเลี่ยง, gating, prompt injection)
- optional live evals (opt-in, gated ด้วย env) หลังจากมี suite ที่ปลอดภัยสำหรับ CI แล้วเท่านั้น
Contract tests (รูปร่างของ plugin และ channel)
Contract tests ตรวจสอบว่า plugin และ channel ทุกตัวที่ลงทะเบียนไว้สอดคล้องกับ
interface contract ของตัวเอง พวกมัน iterate ผ่าน plugins ทั้งหมดที่ค้นพบและรันชุด
assertions ด้าน shape และ behavior lane unit ของ pnpm test ค่าเริ่มต้นตั้งใจ
ข้าม shared seam และ smoke files เหล่านี้; ให้รันคำสั่ง contract โดยชัดเจน
เมื่อคุณแตะ shared channel หรือ provider surfaces
คำสั่ง
- contracts ทั้งหมด:
pnpm test:contracts - channel contracts เท่านั้น:
pnpm test:contracts:channels - provider contracts เท่านั้น:
pnpm test:contracts:plugins
Channel contracts
อยู่ใน src/channels/plugins/contracts/*.contract.test.ts:
- plugin - รูปร่างพื้นฐานของ plugin (id, name, capabilities)
- setup - contract ของ setup wizard
- session-binding - พฤติกรรม session binding
- outbound-payload - โครงสร้าง payload ของข้อความ
- inbound - การจัดการข้อความ inbound
- actions - ตัวจัดการ channel action
- threading - การจัดการ thread ID
- directory - Directory/roster API
- group-policy - การบังคับใช้นโยบายกลุ่ม
Provider status contracts
อยู่ใน src/plugins/contracts/*.contract.test.ts
- status - Channel status probes
- registry - รูปร่างของ plugin registry
Provider contracts
อยู่ใน src/plugins/contracts/*.contract.test.ts:
- auth - contract ของ auth flow
- auth-choice - การเลือก/selection auth
- catalog - Model catalog API
- discovery - การค้นพบ plugin
- loader - การโหลด plugin
- runtime - Provider runtime
- shape - รูปร่าง/interface ของ plugin
- wizard - Setup wizard
ควรรันเมื่อใด
- หลังจากเปลี่ยน plugin-sdk exports หรือ subpaths
- หลังจากเพิ่มหรือแก้ไข channel หรือ provider plugin
- หลังจาก refactor การลงทะเบียนหรือการค้นพบ plugin
Contract tests รันใน CI และไม่ต้องใช้ API keys จริง
การเพิ่ม regressions (แนวทาง)
เมื่อคุณแก้ปัญหา provider/model ที่พบใน live:
- เพิ่ม regression ที่ปลอดภัยสำหรับ CI ถ้าเป็นไปได้ (mock/stub provider หรือ capture การแปลง request-shape ที่แน่นอน)
- ถ้าโดยธรรมชาติเป็น live-only (rate limits, auth policies) ให้ทำ live test ให้แคบและ opt-in ผ่าน env vars
- ควร target layer ที่เล็กที่สุดซึ่งจับ bug ได้:
- bug การแปลง/replay คำขอ provider → direct models test
- bug ใน gateway session/history/tool pipeline → gateway live smoke หรือ gateway mock test ที่ปลอดภัยสำหรับ CI
- SecretRef traversal guardrail:
src/secrets/exec-secret-ref-id-parity.test.tsderive target ตัวอย่างหนึ่งรายการต่อคลาส SecretRef จาก registry metadata (listSecretTargetRegistryEntries()), จากนั้น assert ว่า exec ids แบบ traversal-segment ถูกปฏิเสธ- ถ้าคุณเพิ่ม family ของ target
includeInPlanSecretRef ใหม่ในsrc/secrets/target-registry-data.ts, ให้อัปเดตclassifyTargetClassใน test นั้น test ตั้งใจ fail กับ target ids ที่ยังไม่จัดคลาส เพื่อไม่ให้คลาสใหม่ถูกข้ามอย่างเงียบ ๆ