Testing
การทดสอบ
OpenClaw มีชุดทดสอบ Vitest สามชุด (unit/integration, e2e, live) และชุด Docker runners ขนาดเล็ก เอกสารนี้เป็นคู่มือ "วิธีที่เราทดสอบ":
- แต่ละชุดครอบคลุมอะไร (และตั้งใจ ไม่ ครอบคลุมอะไร)
- คำสั่งใดที่ควรรันสำหรับเวิร์กโฟลว์ทั่วไป (ในเครื่อง, ก่อน push, การดีบัก)
- การทดสอบแบบ live ค้นหาข้อมูลรับรองและเลือกโมเดล/ผู้ให้บริการอย่างไร
- วิธีเพิ่ม regression สำหรับปัญหาโมเดล/ผู้ให้บริการในโลกจริง
เริ่มต้นอย่างรวดเร็ว
โดยทั่วไป:
- เกตเต็มรูปแบบ (คาดหวังก่อน push):
pnpm build && pnpm check && pnpm check:test-types && pnpm test - การรัน full-suite ในเครื่องที่เร็วขึ้นบนเครื่องที่มีพื้นที่เพียงพอ:
pnpm test:max - ลูป watch ของ Vitest โดยตรง:
pnpm test:watch - การกำหนดเป้าหมายไฟล์โดยตรงตอนนี้ route path ของส่วนขยาย/ช่องทางด้วย:
pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts - ให้เลือกการรันแบบเจาะจงก่อนเมื่อคุณกำลัง iterate กับความล้มเหลวเดียว
- ไซต์ QA ที่มี Docker รองรับ:
pnpm qa:lab:up - เลน QA ที่มี Linux VM รองรับ:
pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline
เมื่อคุณแตะการทดสอบหรือต้องการความมั่นใจเพิ่ม:
- เกต coverage:
pnpm test:coverage - ชุด E2E:
pnpm test:e2e
ไดเรกทอรีชั่วคราวสำหรับการทดสอบ
ควรใช้ helper ที่ใช้ร่วมกันใน test/helpers/temp-dir.ts สำหรับไดเรกทอรีชั่วคราวที่การทดสอบเป็นเจ้าของ helper เหล่านี้ทำให้ ownership ชัดเจนและให้ cleanup อยู่ใน lifecycle เดียวกับการทดสอบ:
const tempDirs = useAutoCleanupTempDirTracker(afterEach); it("uses a temp workspace", () => { const workspace = tempDirs.make("openclaw-example-"); // use workspace});useAutoCleanupTempDirTracker(afterEach) ตั้งใจไม่เปิดเผยเมธอด cleanup แบบ manual; Vitest เป็นเจ้าของการ cleanup หลังการทดสอบแต่ละรายการ helper ระดับต่ำที่มีอยู่ยังคงอยู่สำหรับการทดสอบที่ยังไม่ได้ย้าย แต่การทดสอบใหม่และการทดสอบที่ migrate แล้วควรใช้ tracker ที่ cleanup อัตโนมัติ หลีกเลี่ยงการใช้งาน makeTempDir, cleanupTempDirs หรือ createTempDirTracker แบบ manual ใหม่ และหลีกเลี่ยงการเรียก fs.mkdtemp* แบบเปล่าใหม่ในการทดสอบ เว้นแต่กรณีนั้นกำลังตรวจสอบพฤติกรรม temp-dir ดิบอย่างชัดเจน เพิ่มคอมเมนต์ allow ที่ audit ได้พร้อมเหตุผลที่เป็นรูปธรรมเมื่อการทดสอบตั้งใจต้องใช้ไดเรกทอรีชั่วคราวแบบเปล่า:
// openclaw-temp-dir: allow verifies raw fs cleanup behaviorconst workspace = fs.mkdtempSync(prefix);เพื่อให้เห็นการ migration, node scripts/report-test-temp-creations.mjs รายงานการสร้าง temp-dir แบบเปล่าใหม่และการใช้งาน shared-helper แบบ manual ใหม่ในบรรทัด diff ที่เพิ่ม โดยไม่บล็อกสไตล์ cleanup ที่มีอยู่ ขอบเขตไฟล์ของมันตั้งใจทำตามการจัดประเภท test-path เดียวกับที่ scripts/changed-lanes.mjs ใช้ แทนการดูแล heuristic ชื่อไฟล์ test-helper แยกต่างหาก พร้อมข้าม implementation ของ shared helper เอง check:changed รันรายงานนี้สำหรับ path การทดสอบที่เปลี่ยนเป็นสัญญาณ CI แบบเตือนเท่านั้น; findings เป็น annotation คำเตือนของ GitHub ไม่ใช่ความล้มเหลว
เมื่อดีบักผู้ให้บริการ/โมเดลจริง (ต้องใช้ข้อมูลรับรองจริง):
- ชุด live (โมเดล + probe เครื่องมือ/รูปภาพของ Gateway):
pnpm test:live - กำหนดเป้าหมายไฟล์ live หนึ่งไฟล์แบบเงียบ:
pnpm test:live -- src/agents/models.profiles.live.test.ts - รายงาน performance ของ runtime: dispatch
OpenClaw Performanceพร้อมlive_openai_candidate=trueสำหรับ agent turn จริงของopenai/gpt-5.5หรือdeep_profile=trueสำหรับ artifact CPU/heap/trace ของ Kova การรันตามตารางรายวัน publish artifact ของเลน mock-provider, deep-profile และ GPT 5.5 ไปยังopenclaw/clawgrit-reportsเมื่อกำหนดค่าCLAWGRIT_REPORTS_TOKENแล้ว รายงาน mock-provider ยังรวมตัวเลขระดับ source สำหรับการบูต Gateway, memory, plugin-pressure, hello-loop ของ fake-model ซ้ำ และการเริ่มต้น CLI - การ sweep โมเดล live ด้วย Docker:
pnpm test:docker:live-models- ตอนนี้แต่ละโมเดลที่เลือกจะรัน turn ข้อความและ probe ขนาดเล็กแบบอ่านไฟล์
โมเดลที่ metadata ประกาศ input
imageยังรัน turn รูปภาพขนาดเล็กด้วย ปิด probe เพิ่มเติมด้วยOPENCLAW_LIVE_MODEL_FILE_PROBE=0หรือOPENCLAW_LIVE_MODEL_IMAGE_PROBE=0เมื่อแยกความล้มเหลวของผู้ให้บริการ - Coverage ของ CI:
OpenClaw Scheduled Live And E2E ChecksรายวันและOpenClaw Release Checksแบบ manual ต่างเรียก reusable workflow live/E2E ด้วยinclude_live_suites: trueซึ่งรวม job matrix ของ Docker live model แยกตาม provider และ shard แล้ว - สำหรับการ rerun 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และ caller แบบ scheduled/release ของมัน
- ตอนนี้แต่ละโมเดลที่เลือกจะรัน turn ข้อความและ probe ขนาดเล็กแบบอ่านไฟล์
โมเดลที่ metadata ประกาศ input
- Smoke ของ native Codex bound-chat:
pnpm test:docker:live-codex-bind- รันเลน Docker live กับ path app-server ของ Codex, bind Slack DM สังเคราะห์ด้วย
/codex bind, exercise/codex fastและ/codex permissionsจากนั้นตรวจสอบ reply แบบธรรมดาและ route attachment รูปภาพผ่าน binding ของ Plugin แบบ native แทน ACP
- รันเลน Docker live กับ path app-server ของ Codex, bind Slack DM สังเคราะห์ด้วย
- Smoke ของ Codex app-server harness:
pnpm test:docker:live-codex-harness- รัน agent turn ของ Gateway ผ่าน harness Codex app-server ที่ Plugin เป็นเจ้าของ,
ตรวจสอบ
/codex statusและ/codex modelsและโดยค่าเริ่มต้น exercise probe รูปภาพ, 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
- รัน agent turn ของ Gateway ผ่าน harness Codex app-server ที่ Plugin เป็นเจ้าของ,
ตรวจสอบ
- Smoke การติดตั้ง Codex ตามต้องการ:
pnpm test:docker:codex-on-demand- ติดตั้ง tarball OpenClaw ที่ package แล้วใน Docker, รัน onboarding ด้วย OpenAI API-key
และตรวจสอบว่า Plugin Codex พร้อม dependency
@openai/codexถูกดาวน์โหลดเข้าไปใน root โปรเจกต์ npm ที่จัดการไว้ตามต้องการ
- ติดตั้ง tarball OpenClaw ที่ package แล้วใน Docker, รัน onboarding ด้วย OpenAI API-key
และตรวจสอบว่า Plugin Codex พร้อม dependency
- Smoke dependency ของเครื่องมือ Plugin แบบ live:
pnpm test:docker:live-plugin-tool- Pack fixture Plugin ที่มี dependency
slugifyจริง, ติดตั้งผ่านnpm-pack:, ตรวจสอบ dependency ใต้ root โปรเจกต์ npm ที่จัดการไว้, จากนั้นขอให้โมเดล OpenAI แบบ live เรียกเครื่องมือ Plugin และส่งคืน slug ที่ซ่อนอยู่
- Pack fixture Plugin ที่มี dependency
- Smoke คำสั่ง rescue ของ Crestodian:
pnpm test:live:crestodian-rescue-channel- การตรวจแบบ opt-in belt-and-suspenders สำหรับพื้นผิวคำสั่ง rescue ของ message-channel
มัน exercise
/crestodian status, จัดคิวการเปลี่ยนโมเดลแบบ persistent, reply/crestodian yesและตรวจสอบ path การเขียน audit/config
- การตรวจแบบ opt-in belt-and-suspenders สำหรับพื้นผิวคำสั่ง rescue ของ message-channel
มัน exercise
- Smoke ของ Crestodian planner ด้วย Docker:
pnpm test:docker:crestodian-planner- รัน Crestodian ใน container ที่ไม่มี config พร้อม Claude CLI ปลอมบน
PATHและตรวจสอบว่า fallback ของ fuzzy planner แปลเป็นการเขียน typed config ที่มี audit แล้ว
- รัน Crestodian ใน container ที่ไม่มี config พร้อม Claude CLI ปลอมบน
- Smoke first-run ของ Crestodian ด้วย Docker:
pnpm test:docker:crestodian-first-run- เริ่มจาก state dir ของ OpenClaw ที่ว่างเปล่า, ตรวจสอบ entrypoint Crestodian ของ onboard แบบ modern,
ใช้การเขียน setup/model/agent/Discord Plugin + SecretRef,
validate config และตรวจสอบ audit entries path การตั้งค่า Ring 0 เดียวกันยังครอบคลุมใน QA Lab โดย
pnpm openclaw qa suite --scenario crestodian-ring-zero-setup
- เริ่มจาก state dir ของ OpenClaw ที่ว่างเปล่า, ตรวจสอบ entrypoint Crestodian ของ onboard แบบ modern,
ใช้การเขียน setup/model/agent/Discord Plugin + SecretRef,
validate config และตรวจสอบ audit entries path การตั้งค่า Ring 0 เดียวกันยังครอบคลุมใน QA Lab โดย
- 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แบบ isolated กับmoonshot/kimi-k2.6ตรวจสอบว่า JSON รายงาน Moonshot/K2.6 และ transcript ของ assistant เก็บusage.costที่ normalize แล้ว
runner เฉพาะ QA
คำสั่งเหล่านี้อยู่ข้างชุดทดสอบหลักเมื่อคุณต้องการความสมจริงแบบ QA-lab:
CI รัน QA Lab ใน workflow เฉพาะ Agentic parity ซ้อนอยู่ใต้
QA-Lab - All Lanes และ release validation ไม่ใช่ workflow PR แบบ standalone
การ validation แบบกว้างควรใช้ Full Release Validation พร้อม
rerun_group=qa-parity หรือกลุ่ม QA ของ release-checks การตรวจ release แบบ stable/default
เก็บ soak แบบ live/Docker ที่ละเอียดไว้หลัง run_release_soak=true; profile
full บังคับเปิด soak QA-Lab - All Lanes
รันทุกคืนบน main และจาก manual dispatch พร้อมเลน mock parity, เลน Matrix แบบ live,
เลน Telegram live ที่จัดการโดย Convex และเลน Discord live ที่จัดการโดย Convex
เป็น job คู่ขนาน Scheduled QA และ release checks ส่ง Matrix
--profile fast อย่างชัดเจน ขณะที่ค่า default ของ Matrix CLI และ input ของ manual workflow
ยังคงเป็น all; manual dispatch สามารถ shard all เป็น job transport,
media, e2ee-smoke, e2ee-deep และ e2ee-cli ได้ OpenClaw Release Checks รัน parity พร้อมเลน Matrix แบบ fast และ Telegram ก่อนการอนุมัติ release
โดยใช้ mock-openai/gpt-5.5 สำหรับการตรวจ release transport เพื่อให้ deterministic
และหลีกเลี่ยงการเริ่มต้น provider-plugin ปกติ Gateway การขนส่งแบบ live เหล่านี้
ปิด 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> ที่ใช้ร่วมกันซึ่ง build หนึ่งครั้งต่อ commit
ที่เลือก จากนั้น pull ด้วย OPENCLAW_SKIP_DOCKER_BUILD=1 แทนการ rebuild
ภายในทุก shard
pnpm openclaw qa suite- เรียกใช้สถานการณ์ QA ที่อิงกับรีโปโดยตรงบนโฮสต์
- เขียนอาร์ติแฟกต์ระดับบนสุด
qa-evidence.json,qa-suite-summary.jsonและqa-suite-report.mdสำหรับชุดสถานการณ์ที่เลือก รวมถึงการเลือกสถานการณ์แบบ mixed flow, Vitest และ Playwright - เมื่อถูกส่งงานโดย
pnpm openclaw qa run --qa-profile <profile>จะฝัง สกอร์การ์ดโปรไฟล์ taxonomy ที่เลือกไว้ในqa-evidence.jsonเดียวกันsmoke-ciเขียนหลักฐานแบบย่อ ซึ่งตั้งค่าevidenceMode: "slim"และละเว้นexecutionรายรายการreleaseครอบคลุมส่วนคัดสรรสำหรับความพร้อมของรีลีส;allเลือกทุกหมวด maturity ที่ใช้งานอยู่ และมีไว้สำหรับการส่งงานเวิร์กโฟลว์ QA Profile Evidence อย่างชัดเจนเมื่อจำเป็นต้องมีอาร์ติแฟกต์สกอร์การ์ดเต็มรูปแบบ - เรียกใช้สถานการณ์ที่เลือกหลายรายการแบบขนานโดยค่าเริ่มต้นด้วย
gateway worker ที่แยกกัน
qa-channelมีค่าเริ่มต้นเป็น concurrency 4 (จำกัดด้วยจำนวนสถานการณ์ที่เลือก) ใช้--concurrency <count>เพื่อปรับจำนวน worker หรือ--concurrency 1สำหรับเลนแบบอนุกรมเดิม - ออกด้วยสถานะไม่เป็นศูนย์เมื่อสถานการณ์ใดล้มเหลว ใช้
--allow-failuresเมื่อต้องการอาร์ติแฟกต์โดยไม่มีรหัสออกที่ล้มเหลว - รองรับโหมด provider
live-frontier,mock-openaiและaimockaimockเริ่มเซิร์ฟเวอร์ provider ในเครื่องที่อิง AIMock สำหรับความครอบคลุม fixture และ protocol-mock เชิงทดลอง โดยไม่แทนที่เลนmock-openaiที่รับรู้สถานการณ์
pnpm openclaw qa coverage --match <query>- ค้นหา ID สถานการณ์ ชื่อเรื่อง surface, coverage ID, การอ้างอิงเอกสาร, การอ้างอิงโค้ด, plugins และข้อกำหนดของ provider จากนั้นพิมพ์เป้าหมายชุดทดสอบ ที่ตรงกัน
- ใช้สิ่งนี้ก่อนการรัน QA Lab เมื่อคุณรู้พฤติกรรมหรือพาธไฟล์ที่ถูกแตะ แต่ไม่รู้สถานการณ์ที่เล็กที่สุด คำสั่งนี้เป็นเพียงคำแนะนำเท่านั้น; ยังต้องเลือกหลักฐาน mock, live, Multipass, Matrix หรือ transport จากพฤติกรรม ที่กำลังเปลี่ยน
pnpm test:plugins:kitchen-sink-live- เรียกใช้การทดสอบ live OpenAI Kitchen Sink plugin แบบ gauntlet ผ่าน QA Lab
โดยติดตั้งแพ็กเกจ Kitchen Sink ภายนอก ตรวจสอบ inventory ของพื้นผิว plugin SDK
โพรบ
/healthzและ/readyzบันทึกหลักฐาน CPU/RSS ของ gateway เรียกใช้ OpenAI turn แบบ live และตรวจสอบ diagnostics เชิงปฏิปักษ์ ต้องมี auth OpenAI แบบ live เช่นOPENAI_API_KEYในเซสชัน Testbox ที่ hydrate แล้ว จะ source โปรไฟล์ live-auth ของ Testbox โดยอัตโนมัติเมื่อมีตัวช่วยopenclaw-testbox-env
- เรียกใช้การทดสอบ live OpenAI Kitchen Sink plugin แบบ gauntlet ผ่าน QA Lab
โดยติดตั้งแพ็กเกจ Kitchen Sink ภายนอก ตรวจสอบ inventory ของพื้นผิว plugin SDK
โพรบ
pnpm test:gateway:cpu-scenarios- เรียกใช้ bench การเริ่มต้น gateway พร้อมกับแพ็กสถานการณ์ QA Lab แบบ mock
ขนาดเล็ก (
channel-chat-baseline,memory-failure-fallback,gateway-restart-inflight-run) และเขียนสรุปการสังเกต CPU แบบรวมไว้ใต้.artifacts/gateway-cpu-scenarios/ - แจ้งเฉพาะการสังเกต CPU ร้อนที่คงอยู่นานโดยค่าเริ่มต้น (
--cpu-core-warnพร้อม--hot-wall-warn-ms) ดังนั้น burst สั้น ๆ ตอนเริ่มต้นจะถูกบันทึกเป็น metrics โดยไม่ดูเหมือน regression ที่ทำให้ gateway ตรึง CPU นานหลายนาที - ใช้อาร์ติแฟกต์
distที่ build แล้ว; รัน build ก่อนเมื่อ checkout ยังไม่มี output runtime ที่สดใหม่
- เรียกใช้ bench การเริ่มต้น gateway พร้อมกับแพ็กสถานการณ์ QA Lab แบบ mock
ขนาดเล็ก (
pnpm openclaw qa suite --runner multipass- เรียกใช้ชุด QA เดียวกันภายใน Multipass Linux VM แบบใช้แล้วทิ้ง
- คงพฤติกรรมการเลือกสถานการณ์เหมือนกับ
qa suiteบนโฮสต์ - ใช้ flags การเลือก provider/model เดียวกันกับ
qa suite - การรันแบบ live จะส่งต่อ input auth ของ QA ที่รองรับและใช้งานได้จริงสำหรับ guest:
คีย์ provider ผ่าน env, พาธ config provider แบบ live ของ 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- สร้าง npm tarball จาก checkout ปัจจุบัน ติดตั้งแบบ global ใน Docker รันการ onboarding ด้วย OpenAI API key แบบไม่โต้ตอบ กำหนดค่า Telegram โดยค่าเริ่มต้น ตรวจสอบว่า runtime ของ packaged plugin โหลดได้โดยไม่ต้องซ่อม dependency ตอนเริ่มต้น รัน doctor และรัน agent turn ในเครื่องหนึ่งครั้งกับ endpoint OpenAI แบบ mock
- ใช้
OPENCLAW_NPM_ONBOARD_CHANNEL=discordเพื่อรันเลน packaged-install เดียวกันกับ Discord
pnpm test:docker:session-runtime-context- รัน smoke ของ built-app ใน Docker แบบกำหนดได้แน่นอนสำหรับ transcript ของ
embedded runtime context โดยตรวจสอบว่า runtime context ของ OpenClaw ที่ซ่อนอยู่
ถูก persist เป็น custom message ที่ไม่แสดงผล แทนที่จะรั่วไปยัง user turn
ที่มองเห็นได้ จากนั้น seed JSONL ของ session ที่เสียซึ่งได้รับผลกระทบ และตรวจสอบว่า
openclaw doctor --fixเขียนใหม่ไปยัง active branch พร้อม backup
- รัน smoke ของ built-app ใน Docker แบบกำหนดได้แน่นอนสำหรับ transcript ของ
embedded runtime context โดยตรวจสอบว่า runtime context ของ OpenClaw ที่ซ่อนอยู่
ถูก persist เป็น custom message ที่ไม่แสดงผล แทนที่จะรั่วไปยัง user turn
ที่มองเห็นได้ จากนั้น seed JSONL ของ session ที่เสียซึ่งได้รับผลกระทบ และตรวจสอบว่า
pnpm test:docker:npm-telegram-live- ติดตั้ง package candidate ของ OpenClaw ใน Docker รัน onboarding ของแพ็กเกจที่ติดตั้ง กำหนดค่า Telegram ผ่าน CLI ที่ติดตั้ง จากนั้นใช้เลน Telegram QA แบบ live ซ้ำโดยใช้แพ็กเกจที่ติดตั้งนั้นเป็น Gateway ของ SUT
- wrapper mount เฉพาะซอร์ส harness
qa-labจาก checkout; แพ็กเกจที่ติดตั้ง เป็นเจ้าของdist,openclaw/plugin-sdkและ runtime ของ bundled plugin เพื่อให้เลนไม่ผสม plugins จาก checkout ปัจจุบันเข้าไปในแพ็กเกจที่ทดสอบ - ค่าเริ่มต้นคือ
OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta; ตั้งค่าOPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgzหรือOPENCLAW_CURRENT_PACKAGE_TGZเพื่อทดสอบ tarball ในเครื่องที่ resolve แล้ว แทนการติดตั้งจาก registry - ปล่อย timing RTT ซ้ำใน
qa-evidence.jsonโดยค่าเริ่มต้นด้วยOPENCLAW_NPM_TELEGRAM_RTT_SAMPLES=20ปรับทับOPENCLAW_NPM_TELEGRAM_RTT_SAMPLES,OPENCLAW_NPM_TELEGRAM_RTT_TIMEOUT_MSหรือOPENCLAW_NPM_TELEGRAM_RTT_MAX_FAILURESเพื่อปรับการรัน RTTOPENCLAW_NPM_TELEGRAM_RTT_CHECKSรับรายการ ID การตรวจสอบ Telegram QA ที่คั่นด้วยจุลภาคสำหรับสุ่มตัวอย่าง; เมื่อไม่ได้ตั้งค่า การตรวจสอบเริ่มต้น ที่รองรับ RTT คือtelegram-mentioned-message-reply - ใช้ credentials env ของ Telegram หรือแหล่ง credentials ของ 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และ Convex role secret มีอยู่ใน CI wrapper ของ Docker จะเลือก Convex โดยอัตโนมัติ - wrapper ตรวจสอบ env ของ credentials Telegram หรือ Convex บนโฮสต์ก่อนงาน
Docker build/install ตั้งค่า
OPENCLAW_NPM_TELEGRAM_SKIP_CREDENTIAL_PREFLIGHT=1เฉพาะเมื่อตั้งใจ debug การตั้งค่าก่อนมี credentials OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintaineroverrideOPENCLAW_QA_CREDENTIAL_ROLEที่ใช้ร่วมกันสำหรับเลนนี้เท่านั้น เมื่อเลือก credentials ของ Convex และไม่ได้ตั้ง role wrapper จะใช้ciใน CI และmaintainerนอก CI- GitHub Actions เปิดเลนนี้เป็นเวิร์กโฟลว์ maintainer แบบ manual
NPM Telegram Beta E2Eเลนนี้ไม่รันเมื่อ merge เวิร์กโฟลว์ใช้ environmentqa-live-sharedและ lease credentials CI ของ Convex
- GitHub Actions ยังเปิด
Package Acceptanceสำหรับหลักฐานผลิตภัณฑ์แบบ side-run กับแพ็กเกจ candidate หนึ่งรายการด้วย โดยรับ ref ที่เชื่อถือได้, npm spec ที่เผยแพร่แล้ว, URL tarball แบบ HTTPS พร้อม SHA-256 หรืออาร์ติแฟกต์ tarball จากการรันอื่น อัปโหลดopenclaw-current.tgzที่ normalize แล้วเป็นpackage-under-testจากนั้นรัน Docker E2E scheduler ที่มีอยู่ด้วยโปรไฟล์เลน smoke, package, product, full หรือ custom ตั้งค่าtelegram_mode=mock-openaiหรือlive-frontierเพื่อรันเวิร์กโฟลว์ 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 และใช้นโยบายความปลอดภัย ของ URL สาธารณะ:
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- mirror tarball สำหรับ enterprise/private ใช้นโยบาย trusted-source ที่ระบุชัดเจน:
gh workflow run package-acceptance.yml --ref main \ -f source=trusted-url \ -f trusted_source_id=enterprise-artifactory \ -f package_url=https://packages.example.internal:8443/artifactory/openclaw/openclaw-VERSION.tgz \ -f package_sha256=<sha256> \ -f suite_profile=packagesource=trusted-url อ่าน .github/package-trusted-sources.json จาก ref
เวิร์กโฟลว์ที่เชื่อถือได้ และไม่รับ credentials ของ URL หรือ bypass
private-network ผ่าน workflow-input หากนโยบายที่ระบุชื่อประกาศ bearer auth
ให้กำหนดค่า secret คงที่ OPENCLAW_TRUSTED_PACKAGE_TOKEN
- หลักฐานอาร์ติแฟกต์ดาวน์โหลดอาร์ติแฟกต์ 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/plugins ที่ bundled ผ่านการแก้ไข config
- ตรวจสอบว่า setup discovery ปล่อยให้ downloadable plugins ที่ยังไม่ได้กำหนดค่า ไม่ปรากฏอยู่ การซ่อม doctor ครั้งแรกที่กำหนดค่าแล้วติดตั้ง downloadable plugin ที่ขาดหายแต่ละรายการอย่างชัดเจน และการ restart ครั้งที่สองไม่รัน การซ่อม dependency ที่ซ่อนอยู่
- ยังติดตั้ง baseline npm รุ่นเก่าที่ทราบ เปิดใช้ Telegram ก่อนรัน
openclaw update --tag <candidate>และตรวจสอบว่า doctor หลัง update ของ candidate ทำความสะอาดเศษ dependency ของ legacy plugin โดยไม่มีการซ่อม postinstall ฝั่ง harness
-
pnpm test:parallels:npm-update-
รัน smoke การ update แบบ packaged-install native ข้าม guest ของ Parallels แต่ละแพลตฟอร์มที่เลือกจะติดตั้งแพ็กเกจ baseline ที่ขอก่อน จากนั้นรันคำสั่ง
openclaw updateที่ติดตั้งแล้วใน guest เดียวกัน และตรวจสอบเวอร์ชันที่ติดตั้ง สถานะ update ความพร้อมของ gateway และ agent turn ในเครื่องหนึ่งครั้ง -
ใช้
--platform macos,--platform windowsหรือ--platform linuxระหว่าง iterate บน guest หนึ่งรายการ ใช้--jsonสำหรับพาธอาร์ติแฟกต์สรุป และสถานะต่อเลน -
เลน OpenAI ใช้
openai/gpt-5.5สำหรับหลักฐาน agent-turn แบบ live โดยค่าเริ่มต้น ส่ง--model <provider/model>หรือตั้งค่าOPENCLAW_PARALLELS_OPENAI_MODELเมื่อตั้งใจตรวจสอบโมเดล OpenAI อื่น -
ครอบการรันในเครื่องที่ใช้เวลานานด้วย timeout ของโฮสต์ เพื่อไม่ให้การค้างของ transport ของ Parallels ใช้เวลาทดสอบที่เหลือทั้งหมด:
bash timeout --foreground 150m pnpm test:parallels:npm-update -- --jsontimeout --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ก่อนสรุปว่า wrapper ชั้นนอกค้าง -
การ update บน Windows อาจใช้เวลา 10 ถึง 15 นาทีในงาน doctor หลัง update และงาน update แพ็กเกจบน guest ที่เย็นอยู่; ยังถือว่าปกติเมื่อ npm debug log ที่ซ้อนอยู่ยังคืบหน้า
-
อย่ารัน wrapper รวมนี้ขนานกับเลน smoke แยกของ Parallels macOS, Windows หรือ Linux เพราะใช้สถานะ VM ร่วมกันและอาจชนกันในการ restore snapshot การเสิร์ฟแพ็กเกจ หรือสถานะ gateway ของ guest
-
หลักฐานหลัง update รันพื้นผิว bundled plugin ปกติ เพราะ capability facade เช่น speech, image generation และ media understanding ถูกโหลดผ่าน bundled runtime APIs แม้ว่า agent turn เองจะตรวจเพียง response ข้อความแบบง่าย
-
-
pnpm openclaw qa aimock- เริ่มเฉพาะเซิร์ฟเวอร์ผู้ให้บริการ AIMock ภายในเครื่องสำหรับการทดสอบ smoke ของโปรโตคอลโดยตรง
-
pnpm openclaw qa matrix- รันเลน QA สดของ Matrix กับ Tuwunel homeserver แบบใช้แล้วทิ้งที่รองรับด้วย Docker เฉพาะ source-checkout เท่านั้น - การติดตั้งแบบแพ็กเกจไม่ได้ส่ง
qa-labมาด้วย - CLI แบบเต็ม แคตตาล็อกโปรไฟล์/สถานการณ์ ตัวแปรสภาพแวดล้อม และโครงร่าง artifact: Matrix QA
- รันเลน QA สดของ Matrix กับ Tuwunel homeserver แบบใช้แล้วทิ้งที่รองรับด้วย Docker เฉพาะ source-checkout เท่านั้น - การติดตั้งแบบแพ็กเกจไม่ได้ส่ง
-
pnpm openclaw qa telegram- รันเลน QA สดของ Telegram กับกลุ่มส่วนตัวจริง โดยใช้โทเค็นบอต driver และ SUT จาก env
- ต้องใช้
OPENCLAW_QA_TELEGRAM_GROUP_ID,OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKENและOPENCLAW_QA_TELEGRAM_SUT_BOT_TOKENid ของกลุ่มต้องเป็น id แชต Telegram แบบตัวเลข - รองรับ
--credential-source convexสำหรับข้อมูลประจำตัวแบบพูลร่วม ใช้โหมด env เป็นค่าเริ่มต้น หรือตั้งค่าOPENCLAW_QA_CREDENTIAL_SOURCE=convexเพื่อเลือกใช้ lease แบบพูล - ค่าเริ่มต้นครอบคลุม canary, mention gating, command addressing,
/status, การตอบกลับแบบบอตถึงบอตที่ถูก mention และการตอบกลับคำสั่ง native หลัก ค่าเริ่มต้นmock-openaiยังครอบคลุมรีเกรสชันของ reply-chain แบบกำหนดแน่นอนและการสตรีม final-message ของ Telegram ด้วย ใช้--list-scenariosสำหรับ probe เสริม เช่นsession_status - ออกด้วยค่าที่ไม่ใช่ศูนย์เมื่อสถานการณ์ใดล้มเหลว ใช้
--allow-failuresเมื่อคุณ ต้องการ artifact โดยไม่มี exit code ที่ล้มเหลว - ต้องใช้บอตที่แตกต่างกันสองตัวในกลุ่มส่วนตัวเดียวกัน โดยบอต SUT ต้องเปิดเผยชื่อผู้ใช้ Telegram
- เพื่อการสังเกตบอตถึงบอตที่เสถียร ให้เปิดใช้งาน Bot-to-Bot Communication Mode ใน
@BotFatherสำหรับบอตทั้งสองตัว และตรวจสอบว่าบอต driver สามารถสังเกตทราฟฟิกบอตในกลุ่มได้ - เขียนรายงาน QA ของ Telegram, สรุป และ
qa-evidence.jsonไว้ใต้.artifacts/qa-e2e/...สถานการณ์ที่มีการตอบกลับจะรวม RTT ตั้งแต่คำขอส่งของ driver จนถึงการตอบกลับของ SUT ที่สังเกตพบ
Mantis Telegram Live คือ wrapper หลักฐาน PR รอบเลนนี้ โดยจะรัน ref ผู้สมัครด้วยข้อมูลประจำตัว Telegram ที่ lease ผ่าน Convex, เรนเดอร์รายงาน QA
และชุดหลักฐานที่ redacted ในเบราว์เซอร์เดสก์ท็อป Crabbox, บันทึกหลักฐาน MP4,
สร้าง GIF ที่ตัดแต่งตามการเคลื่อนไหว, อัปโหลดชุด artifact และโพสต์หลักฐาน PR
แบบ inline ผ่าน Mantis GitHub App เมื่อมีการตั้งค่า pr_number ผู้ดูแลสามารถ
เริ่มจาก Actions UI ผ่าน Mantis Scenario (scenario_id: telegram-live) หรือโดยตรงจากคอมเมนต์ใน pull request:
@openclaw-mantis telegram@openclaw-mantis telegram scenario=telegram-status-command@openclaw-mantis telegram scenarios=telegram-status-command,telegram-mentioned-message-replyMantis Telegram Desktop Proof คือ wrapper แบบ agentic สำหรับ Telegram Desktop
native ก่อน/หลัง สำหรับหลักฐานภาพของ PR เริ่มจาก Actions UI ด้วย
instructions แบบ freeform, ผ่าน Mantis Scenario (scenario_id: telegram-desktop-proof) หรือจากคอมเมนต์ PR:
@openclaw-mantis telegram desktop proofagent ของ Mantis อ่าน PR, ตัดสินใจว่าพฤติกรรมที่มองเห็นได้ใน Telegram ใดพิสูจน์
การเปลี่ยนแปลง, รันเลนพิสูจน์ Telegram Desktop ผ่าน Crabbox แบบผู้ใช้จริงบน ref baseline และ
candidate, ทำซ้ำจนกว่า GIF native จะมีประโยชน์, เขียน manifest motionPreview
แบบจับคู่ และโพสต์ตาราง GIF 2 คอลัมน์เดียวกันผ่าน Mantis GitHub App เมื่อมีการตั้งค่า pr_number
pnpm openclaw qa mantis telegram-desktop-builder- Lease หรือใช้เดสก์ท็อป Linux ของ Crabbox เดิมซ้ำ, ติดตั้ง Telegram Desktop native, กำหนดค่า OpenClaw ด้วยโทเค็นบอต SUT ของ Telegram ที่ถูก lease, เริ่ม Gateway และบันทึกหลักฐาน screenshot/MP4 จากเดสก์ท็อป VNC ที่มองเห็นได้
- ค่าเริ่มต้นเป็น
--credential-source convexเพื่อให้ workflow ต้องใช้เฉพาะ secret ของ broker Convex ใช้--credential-source envกับตัวแปรOPENCLAW_QA_TELEGRAM_*เดียวกับpnpm openclaw qa telegram - Telegram Desktop ยังคงต้องมีการเข้าสู่ระบบ/โปรไฟล์ผู้ใช้ โทเค็นบอตกำหนดค่าเฉพาะ OpenClaw ใช้
--telegram-profile-archive-env <name>สำหรับ archive โปรไฟล์.tgzแบบ base64 หรือใช้--keep-leaseและเข้าสู่ระบบด้วยตนเองผ่าน VNC หนึ่งครั้ง - เขียน
mantis-telegram-desktop-builder-report.md,mantis-telegram-desktop-builder-summary.json,telegram-desktop-builder.pngและtelegram-desktop-builder.mp4ใต้ไดเรกทอรีเอาต์พุต
เลน transport สดใช้สัญญามาตรฐานเดียวกันเพื่อไม่ให้ transport ใหม่เบี่ยงออกไป เมทริกซ์ความครอบคลุมต่อเลนอยู่ใน ภาพรวม QA → ความครอบคลุม transport สด qa-channel คือชุดทดสอบสังเคราะห์แบบกว้าง และไม่ได้เป็นส่วนหนึ่งของเมทริกซ์นั้น
ข้อมูลประจำตัว Telegram แบบใช้ร่วมกันผ่าน Convex (v1)
เมื่อเปิดใช้งาน --credential-source convex (หรือ OPENCLAW_QA_CREDENTIAL_SOURCE=convex) สำหรับ
QA transport สด, QA lab จะขอรับ lease แบบเอกสิทธิ์จากพูลที่รองรับด้วย Convex, ส่ง Heartbeat ให้
lease นั้นขณะเลนกำลังรัน และปล่อย lease เมื่อปิดการทำงาน ชื่อส่วนนี้มีมาก่อน
การรองรับ Discord, Slack และ WhatsApp; สัญญา lease ใช้ร่วมกันข้ามชนิด
scaffold โปรเจกต์ Convex อ้างอิง:
qa/convex-credential-broker/
ตัวแปร env ที่จำเป็น:
OPENCLAW_QA_CONVEX_SITE_URL(ตัวอย่างเช่นhttps://your-deployment.convex.site)- secret หนึ่งรายการสำหรับบทบาทที่เลือก:
OPENCLAW_QA_CONVEX_SECRET_MAINTAINERสำหรับmaintainerOPENCLAW_QA_CONVEX_SECRET_CIสำหรับci
- การเลือกบทบาทข้อมูลประจำตัว:
- CLI:
--credential-role maintainer|ci - ค่าเริ่มต้น Env:
OPENCLAW_QA_CREDENTIAL_ROLE(ค่าเริ่มต้นเป็นciใน CI, มิฉะนั้นเป็นmaintainer)
- CLI:
ตัวแปร env เสริม:
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 แบบ local loopbackhttp://สำหรับการพัฒนาเฉพาะภายในเครื่อง
OPENCLAW_QA_CONVEX_SITE_URL ควรใช้ https:// ในการทำงานปกติ
คำสั่งผู้ดูแล maintainer (เพิ่ม/ลบ/แสดงรายการพูล) ต้องใช้
OPENCLAW_QA_CONVEX_SECRET_MAINTAINER โดยเฉพาะ
helper ของ CLI สำหรับ maintainer:
pnpm openclaw qa credentials doctorpnpm openclaw qa credentials add --kind telegram --payload-file qa/telegram-credential.jsonpnpm openclaw qa credentials list --kind telegrampnpm openclaw qa credentials remove --credential-id <credential-id>ใช้ doctor ก่อนการรันสดเพื่อตรวจสอบ URL ไซต์ Convex, secret ของ broker,
prefix ของ endpoint, HTTP timeout และการเข้าถึง admin/list โดยไม่พิมพ์
ค่า secret ใช้ --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 /payload-chunk- คำขอ:
{ kind, ownerId, actorRole, credentialId, leaseToken, index } - สำเร็จ:
{ status: "ok", index, data }
- คำขอ:
POST /heartbeat- คำขอ:
{ kind, ownerId, actorRole, credentialId, leaseToken, leaseTtlMs } - สำเร็จ:
{ status: "ok" }(หรือ2xxว่าง)
- คำขอ:
POST /release- คำขอ:
{ kind, ownerId, actorRole, credentialId, leaseToken } - สำเร็จ:
{ status: "ok" }(หรือ2xxว่าง)
- คำขอ:
POST /admin/add(เฉพาะ secret ของ maintainer)- คำขอ:
{ kind, actorId, payload, note?, status? } - สำเร็จ:
{ status: "ok", credential }
- คำขอ:
POST /admin/remove(เฉพาะ secret ของ maintainer)- คำขอ:
{ credentialId, actorId } - สำเร็จ:
{ status: "ok", changed, credential } - guard สำหรับ lease ที่ใช้งานอยู่:
{ status: "error", code: "LEASE_ACTIVE", ... }
- คำขอ:
POST /admin/list(เฉพาะ secret ของ maintainer)- คำขอ:
{ kind?, status?, includePayload?, limit? } - สำเร็จ:
{ status: "ok", credentials, count }
- คำขอ:
รูปทรง payload สำหรับชนิด Telegram:
{ groupId: string, driverToken: string, sutToken: string }groupIdต้องเป็นสตริง id แชต Telegram แบบตัวเลขadmin/addตรวจสอบรูปทรงนี้สำหรับkind: "telegram"และปฏิเสธ payload ที่มีรูปแบบไม่ถูกต้อง
รูปทรง payload สำหรับชนิดผู้ใช้จริงของ Telegram:
{ groupId: string, sutToken: string, testerUserId: string, testerUsername: string, telegramApiId: string, telegramApiHash: string, tdlibDatabaseEncryptionKey: string, tdlibArchiveBase64: string, tdlibArchiveSha256: string, desktopTdataArchiveBase64: string, desktopTdataArchiveSha256: string }groupId,testerUserIdและtelegramApiIdต้องเป็นสตริงตัวเลขtdlibArchiveSha256และdesktopTdataArchiveSha256ต้องเป็นสตริง hex SHA-256kind: "telegram-user"สงวนไว้สำหรับ workflow พิสูจน์ Mantis Telegram Desktop เลน QA Lab ทั่วไปต้องไม่ acquire ชนิดนี้
payload หลายช่องทางที่ broker ตรวจสอบ:
- Discord:
{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string, voiceChannelId?: string } - WhatsApp:
{ driverPhoneE164: string, sutPhoneE164: string, driverAuthArchiveBase64: string, sutAuthArchiveBase64: string, groupJid?: string }
เลน Slack สามารถ lease จากพูลได้เช่นกัน แต่การตรวจสอบ payload ของ Slack ในปัจจุบัน
อยู่ใน runner QA ของ Slack แทนที่จะอยู่ใน broker ใช้
{ channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }
สำหรับแถว Slack
การเพิ่มช่องทางเข้า QA
ชื่อสถาปัตยกรรมและ helper ของสถานการณ์สำหรับ adapter ช่องทางใหม่อยู่ใน ภาพรวม QA → การเพิ่มช่องทาง เกณฑ์ขั้นต่ำ: implement runner ของ transport บน seam โฮสต์ qa-lab ที่ใช้ร่วมกัน, ประกาศ qaRunners ใน manifest ของ Plugin, เมานต์เป็น openclaw qa <runner> และเขียนสถานการณ์ไว้ใต้ qa/scenarios/
ชุดทดสอบ (อะไรทำงานที่ไหน)
ให้คิดว่าชุดทดสอบเป็น “ความสมจริงที่เพิ่มขึ้น” (และความไม่เสถียร/ต้นทุนที่เพิ่มขึ้น):
Unit / integration (ค่าเริ่มต้น)
- คำสั่ง:
pnpm test - Config: การรันที่ไม่ระบุเป้าหมายใช้ชุด shard
vitest.full-*.config.tsและอาจขยาย shard แบบหลายโปรเจกต์เป็น config ต่อโปรเจกต์สำหรับการจัดตารางแบบขนาน - ไฟล์: inventory core/unit ใต้
src/**/*.test.ts,packages/**/*.test.tsและtest/**/*.test.ts; การทดสอบ unit ของ UI รันใน shard เฉพาะunit-ui - ขอบเขต:
- การทดสอบ unit ล้วน
- การทดสอบ integration ภายใน process (การ auth ของ Gateway, routing, tooling, parsing, config)
- รีเกรสชันแบบกำหนดแน่นอนสำหรับบั๊กที่รู้จัก
- ความคาดหวัง:
- รันใน CI
- ไม่ต้องใช้คีย์จริง
- ควรรวดเร็วและเสถียร
- การทดสอบ resolver และ loader ของ public-surface ต้องพิสูจน์พฤติกรรม fallback ของ
api.jsและruntime-api.jsแบบกว้างด้วย fixture Plugin ขนาดเล็กที่สร้างขึ้น ไม่ใช่ API ของซอร์ส Plugin ที่ bundled จริง การโหลด API ของ Plugin จริงควรอยู่ใน ชุด contract/integration ที่ Plugin เป็นเจ้าของ
นโยบาย dependency แบบ native:
- การติดตั้งทดสอบค่าเริ่มต้นข้าม build opus native ของ Discord แบบเสริม Discord voice ใช้
libopus-wasmที่ bundled และ@discordjs/opusยังคงถูกปิดใช้งานในallowBuildsเพื่อให้การทดสอบภายในเครื่องและเลน Testbox ไม่คอมไพล์ addon native - เปรียบเทียบประสิทธิภาพ opus native ใน repo benchmark ของ
libopus-wasmไม่ใช่ใน loop ติดตั้ง/ทดสอบเริ่มต้นของ OpenClaw อย่าตั้งค่า@discordjs/opusเป็นtrueในallowBuildsค่าเริ่มต้น เพราะจะทำให้ loop ติดตั้ง/ทดสอบที่ไม่เกี่ยวข้องคอมไพล์โค้ด native
โปรเจกต์, shard และเลนแบบกำหนดขอบเขต
- การรัน
pnpm testแบบไม่ระบุเป้าหมายจะรันคอนฟิก shard ที่เล็กกว่า 12 ชุด (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 แบบเนทีฟขนาดใหญ่เพียงชุดเดียว วิธีนี้ลด RSS สูงสุดบนเครื่องที่มีโหลดสูง และหลีกเลี่ยงไม่ให้งาน auto-reply/extension แย่งทรัพยากรจากชุดทดสอบที่ไม่เกี่ยวข้อง pnpm test --watchยังใช้กราฟโปรเจกต์ root แบบเนทีฟvitest.config.tsเพราะลูป watch แบบหลาย shard ไม่เหมาะในทางปฏิบัติpnpm test,pnpm test:watch, และpnpm test:perf:importsจะส่งเป้าหมายไฟล์/ไดเรกทอรีที่ระบุชัดเจนผ่าน lane ตามขอบเขตก่อน ดังนั้นpnpm test extensions/discord/src/monitor/message-handler.preflight.test.tsจึงไม่ต้องเสียต้นทุนเริ่มต้นของ root project ทั้งหมดpnpm test:changedจะขยายพาธ git ที่เปลี่ยนเป็น lane ตามขอบเขตราคาถูกโดยค่าเริ่มต้น: การแก้ไขไฟล์ทดสอบโดยตรง, ไฟล์พี่น้อง*.test.ts, การแมปซอร์สที่ระบุชัดเจน, และ dependent ในกราฟ import ภายในเครื่อง การแก้ไข config/setup/package จะไม่รันการทดสอบแบบกว้าง เว้นแต่คุณจะใช้OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changedอย่างชัดเจนpnpm check:changedคือ gate ตรวจสอบภายในเครื่องแบบฉลาดสำหรับงานขอบเขตแคบตามปกติ มันจัดประเภท diff เป็น core, การทดสอบ core, extensions, การทดสอบ extension, apps, docs, metadata รุ่นเผยแพร่, เครื่องมือ live Docker, และ tooling จากนั้นรันคำสั่ง typecheck, lint, และ guard ที่ตรงกัน มันไม่รันการทดสอบ Vitest; ให้เรียกpnpm test:changedหรือpnpm test <target>ที่ระบุชัดเจนเพื่อเป็นหลักฐานการทดสอบ การ bump เวอร์ชันที่เป็น release metadata เท่านั้นจะรันการตรวจสอบเวอร์ชัน/config/root-dependency แบบเจาะจง พร้อม guard ที่ปฏิเสธการเปลี่ยนแปลง package นอกฟิลด์เวอร์ชันระดับบนสุด- การแก้ไข live Docker ACP harness จะรันการตรวจสอบเฉพาะจุด: syntax ของ shell สำหรับสคริปต์ auth ของ live Docker และ dry-run ของ scheduler ของ live Docker การเปลี่ยนแปลง
package.jsonจะถูกรวมเฉพาะเมื่อ diff จำกัดอยู่ที่scripts["test:docker:live-*"]; การแก้ไข dependency, export, version และพื้นผิว package อื่น ๆ ยังใช้ guard ที่กว้างกว่า - การทดสอบ unit แบบ import เบาจาก agents, commands, plugins, helper ของ auto-reply,
plugin-sdk, และพื้นที่ utility ล้วนที่คล้ายกัน จะถูกส่งผ่าน laneunit-fastซึ่งข้ามtest/setup-openclaw-runtime.ts; ไฟล์ที่มี stateful/runtime หนักยังคงอยู่บน lane เดิม - ไฟล์ซอร์ส helper บางส่วนของ
plugin-sdkและcommandsยังแมปการรัน changed-mode ไปยังการทดสอบพี่น้องที่ระบุชัดเจนใน lane เบาเหล่านั้นด้วย ดังนั้นการแก้ไข helper จึงเลี่ยงการรันชุดทดสอบหนักทั้งหมดของไดเรกทอรีนั้นซ้ำ auto-replyมี bucket เฉพาะสำหรับ helper core ระดับบนสุด, การทดสอบ integration ระดับบนสุดreply.*, และ subtreesrc/auto-reply/reply/**CI ยังแยก subtree reply เพิ่มเป็น shard agent-runner, dispatch, และ commands/state-routing เพื่อไม่ให้ bucket ที่ import หนักเพียงชุดเดียวแบกช่วงท้ายของ Node ทั้งหมด- CI ปกติของ PR/main ตั้งใจข้าม sweep แบบ batch ของ extension และ shard
agentic-pluginsที่ใช้เฉพาะ release การ dispatch Full Release Validation จะเรียก workflow ลูกPlugin Prereleaseแยกต่างหากสำหรับชุดทดสอบที่หนักด้าน plugin/extension เหล่านั้นบน release candidate
ความครอบคลุมของ embedded runner
- เมื่อคุณเปลี่ยน input ของการค้นหา message-tool หรือ context runtime ของ Compaction ให้คงความครอบคลุมทั้งสองระดับไว้
- เพิ่ม regression ของ helper แบบเจาะจงสำหรับขอบเขตการ routing และ normalization แบบล้วน
- รักษาชุด integration ของ embedded runner ให้สมบูรณ์:
src/agents/embedded-agent-runner/compact.hooks.test.ts,src/agents/embedded-agent-runner/run.overflow-compaction.test.ts, และsrc/agents/embedded-agent-runner/run.overflow-compaction.loop.test.ts - ชุดเหล่านั้นตรวจสอบว่า scoped id และพฤติกรรม Compaction ยังคงไหลผ่าน
พาธจริง
run.ts/compact.ts; การทดสอบเฉพาะ helper ไม่ใช่สิ่งทดแทนที่เพียงพอสำหรับพาธ integration เหล่านั้น
ค่าเริ่มต้นของ Vitest pool และ isolation
- คอนฟิก Vitest พื้นฐานมีค่าเริ่มต้นเป็น
threads - คอนฟิก Vitest ร่วมกำหนด
isolate: falseและใช้ runner แบบไม่ isolate ใน root projects, e2e, และคอนฟิก live - lane UI ของ root ยังคงใช้ setup และ optimizer ของ
jsdomแต่รันบน runner ร่วมแบบไม่ isolate เช่นกัน - แต่ละ shard ของ
pnpm testสืบทอดค่าเริ่มต้นthreads+isolate: falseเดียวกันจากคอนฟิก Vitest ร่วม scripts/run-vitest.mjsเพิ่ม--no-maglevให้กระบวนการลูก Node ของ Vitest โดยค่าเริ่มต้น เพื่อลด churn ของการ compile V8 ระหว่างการรันภายในเครื่องขนาดใหญ่ ตั้งค่าOPENCLAW_VITEST_ENABLE_MAGLEV=1เพื่อเปรียบเทียบกับพฤติกรรม V8 มาตรฐานscripts/run-vitest.mjsจะยุติการรัน Vitest แบบ non-watch ที่ระบุชัดเจนหลังจาก 5 นาทีหากไม่มี output stdout หรือ stderr ตั้งค่าOPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS=0เพื่อปิด watchdog สำหรับการสืบสวน ที่ตั้งใจให้เงียบ
การทำซ้ำภายในเครื่องอย่างรวดเร็ว
pnpm changed:lanesแสดงว่า diff กระตุ้น lane ทางสถาปัตยกรรมใดบ้าง- hook pre-commit ทำเฉพาะ formatting มัน restage ไฟล์ที่จัดรูปแบบแล้วและ ไม่รัน lint, typecheck, หรือการทดสอบ
- รัน
pnpm check:changedอย่างชัดเจนก่อน handoff หรือ push เมื่อคุณ ต้องการ gate ตรวจสอบภายในเครื่องแบบฉลาด pnpm test:changedส่งผ่าน lane ตามขอบเขตราคาถูกโดยค่าเริ่มต้น ใช้OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changedเฉพาะเมื่อ agent ตัดสินว่าการแก้ไข harness, config, package, หรือ contract ต้องการ ความครอบคลุม Vitest ที่กว้างกว่าจริง ๆpnpm test:maxและpnpm test:changed:maxคงพฤติกรรม routing เดิมไว้ เพียงแต่ใช้ขีดจำกัด worker ที่สูงกว่า- การปรับขนาด worker ภายในเครื่องโดยอัตโนมัติตั้งใจให้ระมัดระวัง และจะลดระดับลง เมื่อค่า load average ของโฮสต์สูงอยู่แล้ว ดังนั้นการรัน Vitest พร้อมกันหลายชุด จะสร้างผลกระทบน้อยลงโดยค่าเริ่มต้น
- คอนฟิก Vitest พื้นฐานทำเครื่องหมาย projects/config files เป็น
forceRerunTriggersเพื่อให้การรันซ้ำแบบ changed-mode ยังคงถูกต้องเมื่อ wiring ของการทดสอบเปลี่ยน - คอนฟิกเปิดใช้
OPENCLAW_VITEST_FS_MODULE_CACHEบนโฮสต์ที่รองรับ ตั้งค่าOPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/pathหากคุณต้องการ ตำแหน่ง cache ที่ระบุชัดเจนหนึ่งแห่งสำหรับการ profiling โดยตรง
การดีบักประสิทธิภาพ
pnpm test:perf:importsเปิดการรายงานระยะเวลา import ของ Vitest พร้อม output import-breakdownpnpm test:perf:imports:changedจำกัดมุมมอง profiling เดียวกันให้กับ ไฟล์ที่เปลี่ยนตั้งแต่origin/main- ข้อมูล timing ของ shard ถูกเขียนไปที่
.artifacts/vitest-shard-timings.jsonการรันทั้งคอนฟิกใช้พาธคอนฟิกเป็น key; shard ของ CI แบบ include-pattern จะต่อท้ายชื่อ shard เพื่อให้ติดตาม shard ที่ถูกกรองแยกกันได้ - เมื่อการทดสอบที่ร้อนรายการหนึ่งยังใช้เวลาส่วนใหญ่ไปกับ startup imports
ให้เก็บ dependency หนักไว้หลัง seam ภายในเครื่องแบบแคบ
*.runtime.tsและ mock seam นั้นโดยตรง แทนการ deep-import helper runtime เพียงเพื่อ ส่งผ่านไปยังvi.mock(...) pnpm test:perf:changed:bench -- --ref <git-ref>เปรียบเทียบtest:changedที่ผ่าน routing กับพาธ root-project แบบเนทีฟสำหรับ diff ที่ commit แล้วนั้น และพิมพ์ wall time พร้อม RSS สูงสุดบน macOSpnpm test:perf:changed:bench -- --worktreebenchmark tree ปัจจุบัน ที่ยัง dirty โดยส่งรายการไฟล์ที่เปลี่ยนผ่านscripts/test-projects.mjsและคอนฟิก Vitest ของ rootpnpm test:perf:profile:mainเขียน CPU profile ของ main-thread สำหรับ overhead การ startup และ transform ของ Vitest/Vitepnpm test:perf:profile:runnerเขียน profile CPU+heap ของ runner สำหรับ ชุด unit โดยปิด file parallelism
เสถียรภาพ (gateway)
- คำสั่ง:
pnpm test:stability:gateway - คอนฟิก:
vitest.gateway.config.ts, บังคับให้ใช้ worker เดียว - ขอบเขต:
- เริ่ม Gateway loopback จริงโดยเปิด diagnostics เป็นค่าเริ่มต้น
- ขับ churn ของข้อความ gateway, memory, และ payload ขนาดใหญ่แบบสังเคราะห์ผ่านพาธ diagnostic event
- query
diagnostics.stabilityผ่าน Gateway WS RPC - ครอบคลุม helper persistence ของ diagnostic stability bundle
- assert ว่า recorder ยังคงถูกจำกัดขนาด, ตัวอย่าง RSS สังเคราะห์ยังอยู่ใต้ budget ความกดดัน, และ queue depth ต่อ session ระบายกลับเป็นศูนย์
- ความคาดหวัง:
- ปลอดภัยสำหรับ CI และไม่ต้องใช้ key
- เป็น lane แคบสำหรับการติดตาม regression ด้านเสถียรภาพ ไม่ใช่สิ่งทดแทนชุด Gateway เต็ม
E2E (ภาพรวม repo)
- คำสั่ง:
pnpm test:e2e - ขอบเขต:
- รัน lane E2E gateway smoke
- รัน lane E2E browser ของ Control UI แบบ mock
- ความคาดหวัง:
- ปลอดภัยสำหรับ CI และไม่ต้องใช้ key
- ต้องติดตั้ง Playwright Chromium
E2E (gateway smoke)
- คำสั่ง:
pnpm test:e2e:gateway - คอนฟิก:
vitest.e2e.config.ts - ไฟล์:
src/**/*.e2e.test.ts,test/**/*.e2e.test.ts, และการทดสอบ E2E ของ bundled-plugin ภายใต้extensions/ - ค่าเริ่มต้น runtime:
- ใช้ Vitest
threadsพร้อมisolate: falseให้ตรงกับส่วนอื่นของ repo - ใช้ adaptive workers (CI: สูงสุด 2, local: ค่าเริ่มต้น 1)
- รันในโหมด silent โดยค่าเริ่มต้น เพื่อลด overhead ของ console I/O
- ใช้ Vitest
- override ที่มีประโยชน์:
OPENCLAW_E2E_WORKERS=<n>เพื่อบังคับจำนวน worker (จำกัดสูงสุดที่ 16)OPENCLAW_E2E_VERBOSE=1เพื่อเปิด verbose console output อีกครั้ง
- ขอบเขต:
- พฤติกรรม end-to-end ของ gateway หลาย instance
- พื้นผิว WebSocket/HTTP, การจับคู่ node, และเครือข่ายที่หนักกว่า
- ความคาดหวัง:
- รันใน CI (เมื่อเปิดใช้ใน pipeline)
- ไม่ต้องใช้ key จริง
- มีชิ้นส่วนเคลื่อนไหวมากกว่าการทดสอบ unit (อาจช้ากว่า)
E2E (browser ของ Control UI แบบ mock)
- คำสั่ง:
pnpm test:ui:e2e - คอนฟิก:
test/vitest/vitest.ui-e2e.config.ts - ไฟล์:
ui/src/**/*.e2e.test.ts - ขอบเขต:
- เริ่ม Vite Control UI
- ขับหน้า Chromium จริงผ่าน Playwright
- แทนที่ Gateway WebSocket ด้วย mock ใน browser ที่ deterministic
- ความคาดหวัง:
- รันใน CI เป็นส่วนหนึ่งของ
pnpm test:e2e - ไม่ต้องใช้ Gateway, agents, หรือ key ของ provider จริง
- ต้องมี dependency ของ browser (
pnpm --dir ui exec playwright install chromium)
- รันใน CI เป็นส่วนหนึ่งของ
E2E: OpenShell backend smoke
- คำสั่ง:
pnpm test:e2e:openshell - ไฟล์:
extensions/openshell/src/backend.e2e.test.ts - ขอบเขต:
- ใช้ gateway ของ OpenShell ภายในเครื่องที่ active อยู่ซ้ำ
- สร้าง sandbox จาก Dockerfile ภายในเครื่องชั่วคราว
- ทดสอบ backend OpenShell ของ OpenClaw ผ่าน
sandbox ssh-config+ SSH exec จริง - ตรวจสอบพฤติกรรม filesystem แบบ remote-canonical ผ่าน sandbox fs bridge
- ความคาดหวัง:
- opt-in เท่านั้น; ไม่ได้เป็นส่วนหนึ่งของการรัน
pnpm test:e2eค่าเริ่มต้น - ต้องมี CLI
openshellภายในเครื่องพร้อม Docker daemon ที่ใช้งานได้ - ต้องมี gateway OpenShell ภายในเครื่องที่ active และแหล่งคอนฟิกของมัน
- ใช้
HOME/XDG_CONFIG_HOMEแบบ isolate แล้วทำลาย sandbox ทดสอบ
- opt-in เท่านั้น; ไม่ได้เป็นส่วนหนึ่งของการรัน
- override ที่มีประโยชน์:
OPENCLAW_E2E_OPENSHELL=1เพื่อเปิดใช้การทดสอบเมื่อรันชุด e2e ที่กว้างกว่าด้วยตนเองOPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshellเพื่อชี้ไปยัง binary CLI หรือ wrapper script ที่ไม่ใช่ค่าเริ่มต้นOPENCLAW_E2E_OPENSHELL_CONFIG_HOME=/path/to/configเพื่อเปิดเผยคอนฟิก gateway ที่ลงทะเบียนไว้ให้กับการทดสอบแบบ isolateOPENCLAW_E2E_OPENSHELL_HOST_IP=172.18.0.1เพื่อ override IP ของ Docker gateway ที่ใช้โดย fixture ของ host policy
Live (provider จริง + model จริง)
- คำสั่ง:
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) - ขอบเขต:
- "provider/model นี้ใช้งานได้จริง วันนี้ ด้วยข้อมูลรับรองจริงหรือไม่?"
- ตรวจจับการเปลี่ยนรูปแบบของ provider, ความเฉพาะตัวของการเรียกใช้เครื่องมือ, ปัญหา auth และพฤติกรรม rate limit
- ความคาดหวัง:
- ไม่ได้ออกแบบให้เสถียรสำหรับ CI (เครือข่ายจริง, นโยบาย provider จริง, quota, outage)
- มีค่าใช้จ่าย / ใช้ rate limit
- ควรรัน subset ที่จำกัดขอบเขตแทนที่จะรัน "ทุกอย่าง"
- การรันแบบ live ใช้ API key ที่ export ไว้แล้วและโปรไฟล์ auth ที่เตรียมไว้
- โดยค่าเริ่มต้น การรันแบบ live ยังคงแยก
HOMEและคัดลอกวัสดุ config/auth ไปยัง test home ชั่วคราว เพื่อไม่ให้ fixture ของ unit test แก้ไข~/.openclawจริงของคุณได้ - ตั้งค่า
OPENCLAW_LIVE_USE_REAL_HOME=1เฉพาะเมื่อคุณตั้งใจให้การทดสอบแบบ live ใช้โฮมไดเรกทอรีจริงของคุณ pnpm test:liveใช้โหมดที่เงียบกว่าเป็นค่าเริ่มต้น: จะคง output ความคืบหน้า[live] ...ไว้ และปิดเสียง log bootstrap ของ gateway/ข้อความ Bonjour ตั้งค่าOPENCLAW_LIVE_TEST_QUIET=0หากคุณต้องการให้ log startup แบบเต็มกลับมา- การหมุนเวียน API key (เฉพาะ provider): ตั้งค่า
*_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:
- ตอนนี้ suite แบบ live จะปล่อยบรรทัดความคืบหน้าไปยัง stderr เพื่อให้เห็นว่าการเรียก provider ที่ใช้เวลานานยังทำงานอยู่ แม้การจับ console ของ Vitest จะเงียบ
vitest.live.config.tsปิดการดักจับ console ของ Vitest เพื่อให้บรรทัดความคืบหน้าของ provider/gateway stream ทันทีระหว่างการรันแบบ live- ปรับ Heartbeat ของ direct-model ด้วย
OPENCLAW_LIVE_HEARTBEAT_MS - ปรับ Heartbeat ของ gateway/probe ด้วย
OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS
ฉันควรรัน suite ใด?
ใช้ตารางตัดสินใจนี้:
- แก้ไข logic/tests: รัน
pnpm test(และpnpm test:coverageหากคุณเปลี่ยนเยอะ) - แตะ gateway networking / WS protocol / pairing: เพิ่ม
pnpm test:e2e - Debug "บอตของฉันล่ม" / failure เฉพาะ provider / tool calling: รัน
pnpm test:liveแบบจำกัดขอบเขต
การทดสอบแบบ Live (แตะเครือข่าย)
สำหรับ live model matrix, smoke ของ CLI backend, smoke ของ ACP, harness ของ Codex app-server และการทดสอบแบบ live ของ media-provider ทั้งหมด (Deepgram, BytePlus, ComfyUI, image, music, video, media harness) รวมถึงการจัดการ credential สำหรับการรันแบบ live โปรดดู การทดสอบ live suites สำหรับ checklist เฉพาะด้าน update และ การตรวจสอบ Plugin โปรดดู การทดสอบ updates และ plugins
Docker runners (การตรวจสอบ "ใช้งานได้ใน Linux" แบบ optional)
Docker runners เหล่านี้แบ่งเป็นสองกลุ่ม:
- Live-model runners:
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 และไฟล์ env profile ที่เป็น optional entrypoint ในเครื่องที่ตรงกันคือtest:live:models-profilesและtest:live:gateway-profiles - Docker live runners คง cap ที่ใช้งานจริงของตนไว้เมื่อจำเป็น:
test:docker:live-modelsใช้ชุด curated supported high-signal เป็นค่าเริ่มต้น และ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=90000เป็นค่าเริ่มต้น ตั้งค่าOPENCLAW_LIVE_MAX_MODELSหรือ env vars ของ gateway เมื่อคุณต้องการ cap ที่เล็กลงหรือการสแกนที่ใหญ่ขึ้นอย่างชัดเจน test:docker:allbuild live Docker image หนึ่งครั้งผ่านtest:docker:live-build, pack OpenClaw หนึ่งครั้งเป็น npm tarball ผ่านscripts/package-openclaw-for-docker.mjsจากนั้น build/reuse imagescripts/e2e/Dockerfileสองตัว image แบบ bare เป็นเพียง Node/Git runner สำหรับ lane install/update/plugin-dependency เท่านั้น; lane เหล่านั้น mount tarball ที่ prebuilt ไว้ image แบบ functional ติดตั้ง tarball เดียวกันลงใน/appสำหรับ lane ฟังก์ชันของ built-app คำจำกัดความของ Docker lane อยู่ในscripts/lib/docker-e2e-scenarios.mjs; logic ของ planner อยู่ในscripts/lib/docker-e2e-plan.mjs;scripts/test-docker-all.mjsรัน plan ที่เลือก aggregate ใช้ scheduler แบบ weighted local:OPENCLAW_DOCKER_ALL_PARALLELISMควบคุม process slots ขณะที่ resource caps กันไม่ให้ lane หนักอย่าง live, npm-install และ multi-service เริ่มพร้อมกันทั้งหมด หาก lane เดียวหนักกว่า cap ที่ active อยู่ scheduler ยังสามารถเริ่ม lane นั้นได้เมื่อ pool ว่าง แล้วปล่อยให้รันเดี่ยวจนกว่าจะมี capacity อีกครั้ง ค่าเริ่มต้นคือ 10 slots,OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9,OPENCLAW_DOCKER_ALL_NPM_LIMIT=5และOPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7; ปรับOPENCLAW_DOCKER_ALL_WEIGHT_LIMITหรือOPENCLAW_DOCKER_ALL_DOCKER_LIMITเฉพาะเมื่อ Docker host มี headroom มากขึ้น runner ทำ Docker preflight โดยค่าเริ่มต้น, ลบ container OpenClaw E2E ที่ค้างอยู่, พิมพ์สถานะทุก 30 วินาที, เก็บเวลาของ lane ที่สำเร็จไว้ใน.artifacts/docker-tests/lane-timings.jsonและใช้เวลาเหล่านั้นเพื่อเริ่ม lane ที่ยาวกว่าก่อนในการรันครั้งถัดไป ใช้OPENCLAW_DOCKER_ALL_DRY_RUN=1เพื่อพิมพ์ weighted lane manifest โดยไม่ build หรือรัน Docker หรือnode scripts/test-docker-all.mjs --plan-jsonเพื่อพิมพ์ CI plan สำหรับ lane ที่เลือก, ความต้องการ package/image และ credentialsPackage Acceptanceคือ gate package แบบ GitHub-native สำหรับ "tarball ที่ติดตั้งได้นี้ทำงานเป็นผลิตภัณฑ์ได้หรือไม่?" มัน 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ดู contract ของ package/update/plugin, survivor matrix ของ published-upgrade, ค่าเริ่มต้นของ release และการ triage failure ได้ที่ การทดสอบ updates และ plugins- การตรวจสอบ build และ release รัน
scripts/check-cli-bootstrap-imports.mjsหลัง tsdown guard จะเดิน static built graph จากdist/entry.jsและdist/cli/run-main.jsและ fail หาก startup ก่อน dispatch import package dependencies เช่น Commander, prompt UI, undici หรือ logging ก่อน command dispatch; นอกจากนี้ยังคุม bundled gateway run chunk ให้อยู่ใน budget และปฏิเสธ static import ของ cold gateway paths ที่รู้จัก Packaged CLI smoke ยังครอบคลุม root help, onboard help, doctor help, status, config schema และคำสั่ง model-list - ความเข้ากันได้แบบ legacy ของ Package Acceptance ถูก cap ที่
2026.4.25(รวม2026.4.25-beta.*) จนถึง cutoff นั้น harness จะยอมรับเฉพาะช่องว่าง metadata ของ shipped-package: รายการ private QA inventory ที่ละไว้, ไม่มีgateway install --wrapper, ไม่มี patch files ใน fixture git ที่ derive จาก tarball, ไม่มีupdate.channelที่ persist, ตำแหน่ง install-record ของ Plugin แบบ legacy, ไม่มี persistence ของ marketplace install-record และการ migrate config metadata ระหว่างplugins updateสำหรับ package หลัง2026.4.25path เหล่านั้นเป็น failure แบบ strict - Container smoke runners:
test:docker:openwebui,test:docker:onboard,test:docker:npm-onboard-channel-agent,test:docker:release-user-journey,test:docker:release-typed-onboarding,test:docker:release-media-memory,test:docker:release-upgrade-user-journey,test:docker:release-plugin-marketplace,test:docker:skill-install,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:agent-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 จริงหนึ่งตัวหรือมากกว่าและ verify path integration ระดับสูง - Docker/Bash E2E lanes ที่ติดตั้ง packed OpenClaw tarball ผ่าน
scripts/lib/openclaw-e2e-instance.shcapnpm installที่OPENCLAW_E2E_NPM_INSTALL_TIMEOUT(ค่าเริ่มต้น600s; ตั้งค่า0เพื่อปิด wrapper สำหรับ debugging)
Live-model Docker runners ยัง bind-mount เฉพาะ CLI auth homes ที่จำเป็น (หรือทั้งหมดที่รองรับเมื่อการรันไม่ได้จำกัดขอบเขต) จากนั้นคัดลอกเข้า container home ก่อนรัน เพื่อให้ OAuth ของ external-CLI refresh token ได้โดยไม่แก้ไข auth store ของ host:
-
Direct models:
pnpm test:docker:live-models(script:scripts/test-live-models-docker.sh) -
ACP bind smoke:
pnpm test:docker:live-acp-bind(script:scripts/test-live-acp-bind-docker.sh; ครอบคลุม Claude, Codex และ Gemini โดยค่าเริ่มต้น พร้อม coverage แบบ strict สำหรับ 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(script:scripts/test-live-cli-backend-docker.sh) -
Codex app-server harness smoke:
pnpm test:docker:live-codex-harness(script:scripts/test-live-codex-harness-docker.sh) -
Gateway + dev agent:
pnpm test:docker:live-gateway(script:scripts/test-live-gateway-models-docker.sh) -
Observability smokes:
pnpm qa:otel:smoke,pnpm qa:prometheus:smokeและpnpm qa:observability:smokeเป็น lane private QA source-checkout โดยตั้งใจไม่รวมอยู่ใน lane Docker release ของ package เพราะ npm tarball ละเว้น QA Lab -
Open WebUI live smoke:
pnpm test:docker:openwebui(script:scripts/e2e/openwebui-docker.sh) -
Onboarding wizard (TTY, scaffolding เต็มรูปแบบ):
pnpm test:docker:onboard(script:scripts/e2e/onboard-docker.sh) -
Npm tarball onboarding/channel/agent smoke:
pnpm test:docker:npm-onboard-channel-agentติดตั้ง packed OpenClaw tarball แบบ global ใน Docker, configure OpenAI ผ่าน env-ref onboarding พร้อม Telegram โดยค่าเริ่มต้น, รัน doctor และรัน agent turn ของ OpenAI ที่ mock หนึ่งครั้ง ใช้ tarball ที่ prebuilt ซ้ำด้วย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 -
สโมคการเดินทางผู้ใช้ของรุ่นเผยแพร่:
pnpm test:docker:release-user-journeyติดตั้ง tarball ของ OpenClaw ที่แพ็กแล้วแบบทั่วทั้งระบบใน Docker home ที่สะอาด, รันการเริ่มต้นใช้งาน, กำหนดค่า provider OpenAI แบบจำลอง, รันหนึ่ง agent turn, ติดตั้ง/ถอนการติดตั้ง Plugin ภายนอก, กำหนดค่า ClickClack กับ fixture ภายในเครื่อง, ตรวจสอบข้อความขาออก/ขาเข้า, รีสตาร์ท Gateway, และรัน doctor -
สโมคการเริ่มต้นใช้งานแบบ typed ของรุ่นเผยแพร่:
pnpm test:docker:release-typed-onboardingติดตั้ง tarball ที่แพ็กแล้ว, ขับopenclaw onboardผ่าน TTY จริง, กำหนดค่า OpenAI เป็น provider แบบ env-ref, ตรวจสอบว่าไม่มีการคงอยู่ของคีย์ดิบ, และรัน agent turn แบบจำลอง -
สโมคสื่อ/หน่วยความจำของรุ่นเผยแพร่:
pnpm test:docker:release-media-memoryติดตั้ง tarball ที่แพ็กแล้ว, ตรวจสอบความเข้าใจภาพจากไฟล์แนบ PNG, เอาต์พุตการสร้างภาพแบบเข้ากันได้กับ OpenAI, การเรียกคืนจากการค้นหาหน่วยความจำ, และการเรียกคืนยังอยู่รอดหลังรีสตาร์ท Gateway -
สโมคการเดินทางผู้ใช้สำหรับอัปเกรดรุ่นเผยแพร่:
pnpm test:docker:release-upgrade-user-journeyโดยค่าเริ่มต้นจะติดตั้ง baseline ที่เผยแพร่ล่าสุดซึ่งเก่ากว่า tarball ผู้สมัคร, กำหนดค่าสถานะ provider/Plugin/ClickClack บนแพ็กเกจที่เผยแพร่, อัปเกรดเป็น tarball ผู้สมัคร, แล้วรันการเดินทางหลักของ agent/Plugin/channel อีกครั้ง หากไม่มี baseline ที่เผยแพร่เก่ากว่า จะใช้เวอร์ชันผู้สมัครซ้ำ แทนที่ baseline ด้วยOPENCLAW_RELEASE_UPGRADE_BASELINE_SPEC=openclaw@<version> -
สโมคตลาด Plugin ของรุ่นเผยแพร่:
pnpm test:docker:release-plugin-marketplaceติดตั้งจากตลาด fixture ภายในเครื่อง, อัปเดต Plugin ที่ติดตั้งแล้ว, ถอนการติดตั้ง, และตรวจสอบว่า CLI ของ Plugin หายไปพร้อมกับ metadata การติดตั้งที่ถูกตัดออก -
สโมคการติดตั้ง Skill:
pnpm test:docker:skill-installติดตั้ง tarball ของ OpenClaw ที่แพ็กแล้วแบบทั่วทั้งระบบใน Docker, ปิดการติดตั้ง archive ที่อัปโหลดในการกำหนดค่า, resolve slug ของ ClawHub skill สดปัจจุบันจากการค้นหา, ติดตั้งด้วยopenclaw skills install, และตรวจสอบ skill ที่ติดตั้งพร้อม metadata ต้นทาง/ล็อก.clawhub -
สโมคการสลับ update channel:
pnpm test:docker:update-channel-switchติดตั้ง tarball ของ OpenClaw ที่แพ็กแล้วแบบทั่วทั้งระบบใน Docker, สลับจากแพ็กเกจstableเป็น gitdev, ตรวจสอบ channel ที่คงอยู่และงานหลังอัปเดตของ Plugin, จากนั้นสลับกลับเป็นแพ็กเกจstableและตรวจสอบสถานะการอัปเดต -
สโมคผู้รอดจากการอัปเกรด:
pnpm test:docker:upgrade-survivorติดตั้ง tarball ของ OpenClaw ที่แพ็กแล้วทับ fixture ผู้ใช้เก่าแบบ dirty ที่มี agents, การกำหนดค่า channel, allowlists ของ Plugin, สถานะ dependency ของ Plugin ที่ค้าง, และไฟล์ workspace/session ที่มีอยู่ โดยจะรันการอัปเดตแพ็กเกจพร้อม doctor แบบ non-interactive โดยไม่มี provider สดหรือคีย์ channel, จากนั้นเริ่ม Gateway แบบ loopback และตรวจสอบการคงอยู่ของ config/state พร้อมงบประมาณ startup/status -
สโมคผู้รอดจากการอัปเกรดที่เผยแพร่แล้ว:
pnpm test:docker:published-upgrade-survivorติดตั้งopenclaw@latestโดยค่าเริ่มต้น, seed ไฟล์ผู้ใช้ที่มีอยู่แบบสมจริง, กำหนดค่า baseline นั้นด้วยสูตรคำสั่งที่ bake ไว้, ตรวจสอบ config ที่ได้, อัปเดตการติดตั้งที่เผยแพร่นั้นเป็น tarball ผู้สมัคร, รัน doctor แบบ non-interactive, เขียน.artifacts/upgrade-survivor/summary.json, จากนั้นเริ่ม Gateway แบบ loopback และตรวจสอบ intents ที่กำหนดค่า, การคงอยู่ของสถานะ, startup,/healthz,/readyz, และงบประมาณสถานะ RPC แทนที่ baseline หนึ่งรายการด้วยOPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC, ขอให้ตัวจัดตารางแบบรวมขยาย baseline ภายในเครื่องที่ระบุแน่นอนด้วยOPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECSเช่นopenclaw@2026.5.2 openclaw@2026.4.23 openclaw@2026.4.15, และขยาย 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 -
สโมคบริบท runtime ของ session:
pnpm test:docker:session-runtime-contextตรวจสอบการคงอยู่ของ transcript บริบท runtime ที่ซ่อนอยู่ พร้อมการซ่อมโดย doctor ของกิ่ง prompt-rewrite ที่ซ้ำและได้รับผลกระทบ -
สโมคการติดตั้ง Bun แบบ global:
bash scripts/e2e/bun-global-install-smoke.shแพ็ก tree ปัจจุบัน, ติดตั้งด้วยbun install -gใน home ที่แยกไว้, และตรวจสอบว่าopenclaw infer image providers --jsonคืน provider ภาพที่ bundled แทนที่จะค้าง ใช้ 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 -
สโมค Docker ตัวติดตั้ง:
bash scripts/test-install-sh-docker.shแชร์แคช npm หนึ่งชุดระหว่างคอนเทนเนอร์ root, update, และ direct-npm สโมค update ใช้ npmlatestเป็น baseline stable โดยค่าเริ่มต้นก่อนอัปเกรดเป็น tarball ผู้สมัคร แทนที่ด้วยOPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22ภายในเครื่อง, หรือด้วย inputupdate_baseline_versionของ workflow Install Smoke บน GitHub การตรวจสอบตัวติดตั้งแบบ non-root เก็บแคช npm ที่แยกไว้ เพื่อไม่ให้รายการแคชที่ root เป็นเจ้าของบดบังพฤติกรรมการติดตั้งภายในเครื่องของผู้ใช้ ตั้งค่าOPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cacheเพื่อใช้แคช root/update/direct-npm ซ้ำในการรันซ้ำภายในเครื่อง -
Install Smoke CI ข้ามการอัปเดต global แบบ direct-npm ที่ซ้ำด้วย
OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1; รันสคริปต์ภายในเครื่องโดยไม่มี env นั้นเมื่อต้องการความครอบคลุมของnpm install -gโดยตรง -
สโมค CLI ลบ workspace ที่แชร์ของ Agents:
pnpm test:docker:agents-delete-shared-workspace(สคริปต์:scripts/e2e/agents-delete-shared-workspace-docker.sh) build image จาก root Dockerfile โดยค่าเริ่มต้น, seed agents สองตัวที่มี workspace เดียวใน 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:
pnpm test:docker:browser-cdp-snapshot(สคริปต์:scripts/e2e/browser-cdp-snapshot-docker.sh) build image source E2E พร้อมเลเยอร์ Chromium, เริ่ม Chromium ด้วย CDP ดิบ, รันbrowser doctor --deep, และตรวจสอบว่า role snapshots ของ CDP ครอบคลุม URL ของลิงก์, clickables ที่เลื่อนระดับจาก cursor, refs ของ iframe, และ metadata ของ frame -
รีเกรสชัน reasoning ขั้นต่ำของ OpenAI Responses web_search:
pnpm test:docker:openai-web-search-minimal(สคริปต์:scripts/e2e/openai-web-search-minimal-docker.sh) รันเซิร์ฟเวอร์ OpenAI แบบจำลองผ่าน Gateway, ตรวจสอบว่าweb_searchเพิ่มreasoning.effortจากminimalเป็นlow, จากนั้นบังคับให้ provider schema ปฏิเสธและตรวจสอบว่ารายละเอียดดิบปรากฏในบันทึก Gateway -
สะพาน MCP channel (Gateway ที่ seed แล้ว + stdio bridge + สโมค notification-frame ดิบของ Claude):
pnpm test:docker:mcp-channels(สคริปต์:scripts/e2e/mcp-channels-docker.sh) -
เครื่องมือ MCP ของ bundle OpenClaw (เซิร์ฟเวอร์ stdio MCP จริง + สโมค allow/deny ของโปรไฟล์ OpenClaw ที่ฝังไว้):
pnpm test:docker:agent-bundle-mcp-tools(สคริปต์:scripts/e2e/agent-bundle-mcp-tools-docker.sh) -
การล้าง Cron/subagent MCP (Gateway จริง + การรื้อ stdio MCP child หลังรัน cron แบบแยกและ subagent แบบ one-shot):
pnpm test:docker:cron-mcp-cleanup(สคริปต์:scripts/e2e/cron-mcp-cleanup-docker.sh) -
Plugins (สโมค install/update สำหรับ path ภายในเครื่อง,
file:, npm registry ที่มี dependencies แบบ hoisted, metadata แพ็กเกจ npm ที่ malformed, refs ของ git ที่เคลื่อนที่, ClawHub kitchen-sink, การอัปเดต marketplace, และการ enable/inspect Claude-bundle):pnpm test:docker:plugins(สคริปต์:scripts/e2e/plugins-docker.sh) ตั้งค่าOPENCLAW_PLUGINS_E2E_CLAWHUB=0เพื่อข้ามบล็อก ClawHub, หรือแทนที่คู่ package/runtime แบบ kitchen-sink ค่าเริ่มต้นด้วยOPENCLAW_PLUGINS_E2E_CLAWHUB_SPECและOPENCLAW_PLUGINS_E2E_CLAWHUB_IDหากไม่มีOPENCLAW_CLAWHUB_URL/CLAWHUB_URLการทดสอบจะใช้เซิร์ฟเวอร์ fixture ClawHub ภายในเครื่องแบบ hermetic -
สโมคการอัปเดต Plugin ที่ไม่เปลี่ยนแปลง:
pnpm test:docker:plugin-update(สคริปต์:scripts/e2e/plugin-update-unchanged-docker.sh) -
สโมคเมทริกซ์ lifecycle ของ Plugin:
pnpm test:docker:plugin-lifecycle-matrixติดตั้ง tarball ของ OpenClaw ที่แพ็กแล้วในคอนเทนเนอร์เปล่า, ติดตั้ง npm Plugin, สลับ enable/disable, อัปเกรดและดาวน์เกรดผ่าน npm registry ภายในเครื่อง, ลบโค้ดที่ติดตั้งแล้ว, จากนั้นตรวจสอบว่า uninstall ยังลบสถานะค้างได้พร้อมบันทึกเมตริก RSS/CPU สำหรับแต่ละเฟสของ lifecycle -
สโมค metadata reload ของ config:
pnpm test:docker:config-reload(สคริปต์:scripts/e2e/config-reload-source-docker.sh) -
Plugins:
pnpm test:docker:pluginsครอบคลุมสโมค install/update สำหรับ path ภายในเครื่อง,file:, npm registry ที่มี dependencies แบบ hoisted, refs ของ git ที่เคลื่อนที่, fixtures ของ ClawHub, การอัปเดต marketplace, และการ enable/inspect Claude-bundlepnpm test:docker:plugin-updateครอบคลุมพฤติกรรมการอัปเดตที่ไม่เปลี่ยนแปลงสำหรับ Plugins ที่ติดตั้งแล้วpnpm test:docker:plugin-lifecycle-matrixครอบคลุมการติดตั้ง npm Plugin ที่ติดตามทรัพยากร, enable, disable, upgrade, downgrade, และ uninstall เมื่อโค้ดหายไป
เพื่อ prebuild และใช้ image functional ที่แชร์ซ้ำด้วยตนเอง:
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local pnpm test:docker:e2e-buildOPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channelsimage override เฉพาะ suite เช่น OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE ยังคงมีผลเหนือกว่าเมื่อตั้งค่าไว้ เมื่อ OPENCLAW_SKIP_DOCKER_BUILD=1 ชี้ไปยัง image ที่แชร์แบบ remote สคริปต์จะ pull image นั้นถ้ายังไม่มีในเครื่อง การทดสอบ QR และ Docker ตัวติดตั้งเก็บ Dockerfiles ของตนเองไว้ เพราะตรวจสอบพฤติกรรมแพ็กเกจ/การติดตั้ง ไม่ใช่ runtime ของแอปที่ build แล้วแบบแชร์
รันเนอร์ Docker สำหรับโมเดลสดยัง bind-mount เช็กเอาต์ปัจจุบันแบบอ่านอย่างเดียว และ
จัดวางลงใน workdir ชั่วคราวภายในคอนเทนเนอร์ วิธีนี้ทำให้อิมเมจรันไทม์
มีขนาดเล็ก แต่ยังคงรัน Vitest กับซอร์ส/คอนฟิกในเครื่องของคุณได้ตรงตามจริง
ขั้นตอนการจัดวางจะข้ามแคชขนาดใหญ่ที่ใช้เฉพาะในเครื่องและเอาต์พุตบิลด์ของแอป เช่น
.pnpm-store, .worktrees, __openclaw_vitest__ และไดเรกทอรีเอาต์พุต .build เฉพาะแอปหรือ
Gradle เพื่อให้การรัน Docker แบบสดไม่ต้องใช้เวลาหลายนาทีคัดลอก
อาร์ทิแฟกต์เฉพาะเครื่อง
รันเนอร์เหล่านี้ยังกำหนด OPENCLAW_SKIP_CHANNELS=1 เพื่อให้โพรบสดของ gateway ไม่เริ่ม
เวิร์กเกอร์ช่องทาง Telegram/Discord/ฯลฯ จริงภายในคอนเทนเนอร์
test:docker:live-models ยังคงรัน pnpm test:live ดังนั้นให้ส่งผ่าน
OPENCLAW_LIVE_GATEWAY_* ด้วยเมื่อคุณต้องการจำกัดหรือยกเว้นความครอบคลุมสดของ gateway
จากเลน Docker นั้น
test:docker:openwebui เป็น smoke ความเข้ากันได้ระดับสูงกว่า: มันเริ่ม
คอนเทนเนอร์ gateway ของ OpenClaw พร้อมเปิดใช้งานปลายทาง HTTP ที่เข้ากันได้กับ OpenAI,
เริ่มคอนเทนเนอร์ Open WebUI เวอร์ชันที่ปักหมุดไว้กับ gateway นั้น, ลงชื่อเข้าใช้ผ่าน
Open WebUI, ตรวจสอบว่า /api/models เปิดเผย openclaw/default แล้วส่ง
คำขอแชตจริงผ่านพร็อกซี /api/chat/completions ของ Open WebUI
กำหนด OPENWEBUI_SMOKE_MODE=models สำหรับการตรวจ CI ในเส้นทางรีลีสที่ควรหยุด
หลังจากลงชื่อเข้าใช้ Open WebUI และค้นพบโมเดล โดยไม่รอให้โมเดลสด
ตอบ completion
การรันครั้งแรกอาจช้าลงอย่างสังเกตได้ เพราะ Docker อาจต้องดึง
อิมเมจ Open WebUI และ Open WebUI อาจต้องตั้งค่า cold-start ของตัวเองให้เสร็จ
เลนนี้คาดหวังคีย์โมเดลสดที่ใช้งานได้ ให้จัดเตรียมผ่านสภาพแวดล้อมของโปรเซส
โปรไฟล์ auth ที่จัดวางไว้ หรือ OPENCLAW_PROFILE_FILE ที่ระบุอย่างชัดเจน
การรันที่สำเร็จจะพิมพ์ payload JSON ขนาดเล็ก เช่น { "ok": true, "model": "openclaw/default", ... }
test:docker:mcp-channels ถูกออกแบบให้ deterministic และไม่ต้องใช้บัญชี
Telegram, Discord หรือ iMessage จริง มันบูตคอนเทนเนอร์ Gateway ที่ seed แล้ว,
เริ่มคอนเทนเนอร์ที่สองซึ่ง spawn openclaw mcp serve จากนั้น
ตรวจสอบการค้นพบบทสนทนาที่ถูก route, การอ่าน transcript, เมทาดาทาของไฟล์แนบ,
พฤติกรรมคิวเหตุการณ์สด, การ route การส่งออก และการแจ้งเตือนช่องทาง +
สิทธิ์แบบ Claude ผ่านสะพาน MCP stdio จริง การตรวจการแจ้งเตือน
ตรวจเฟรม MCP stdio ดิบโดยตรง เพื่อให้ smoke ตรวจสอบสิ่งที่
สะพาน emit จริง ไม่ใช่เพียงสิ่งที่ SDK ไคลเอนต์เฉพาะรายบังเอิญแสดงออกมา
test:docker:agent-bundle-mcp-tools เป็น deterministic และไม่ต้องใช้คีย์โมเดลสด
มันบิลด์อิมเมจ Docker ของ repo, เริ่มเซิร์ฟเวอร์โพรบ MCP stdio จริง
ภายในคอนเทนเนอร์, materialize เซิร์ฟเวอร์นั้นผ่านรันไทม์ MCP ของบันเดิล OpenClaw ที่ฝังไว้,
เรียกใช้เครื่องมือ แล้วตรวจสอบว่า coding และ messaging เก็บ
เครื่องมือ bundle-mcp ไว้ ขณะที่ minimal และ tools.deny: ["bundle-mcp"] กรองเครื่องมือเหล่านั้นออก
test:docker:cron-mcp-cleanup เป็น deterministic และไม่ต้องใช้คีย์โมเดลสด
มันเริ่ม Gateway ที่ seed แล้วพร้อมเซิร์ฟเวอร์โพรบ MCP stdio จริง, รัน
cron turn แบบแยกเดี่ยวและ child turn แบบ one-shot ของ sessions_spawn จากนั้นตรวจสอบว่า
โปรเซสลูก MCP ออกจากระบบหลังการรันแต่ละครั้ง
smoke เธรด ACP แบบภาษาธรรมดาด้วยตนเอง (ไม่ใช่ CI):
bun scripts/dev/discord-acp-plain-language-smoke.ts --channel <discord-channel-id> ...- เก็บสคริปต์นี้ไว้สำหรับเวิร์กโฟลว์ regression/debug อาจต้องใช้อีกครั้งสำหรับการตรวจสอบความถูกต้องของการ route เธรด ACP ดังนั้นอย่าลบ
env vars ที่มีประโยชน์:
OPENCLAW_CONFIG_DIR=...(ค่าเริ่มต้น:~/.openclaw) mount ไปที่/home/node/.openclawOPENCLAW_WORKSPACE_DIR=...(ค่าเริ่มต้น:~/.openclaw/workspace) mount ไปที่/home/node/.openclaw/workspaceOPENCLAW_PROFILE_FILE=...mount และ source ก่อนรันการทดสอบOPENCLAW_DOCKER_PROFILE_ENV_ONLY=1เพื่อตรวจสอบเฉพาะ env vars ที่ source จากOPENCLAW_PROFILE_FILEโดยใช้ไดเรกทอรี config/workspace ชั่วคราวและไม่มี mount สำหรับ auth ของ CLI ภายนอกOPENCLAW_DOCKER_CLI_TOOLS_DIR=...(ค่าเริ่มต้น:~/.cache/openclaw/docker-cli-tools) mount ไปที่/home/node/.npm-globalสำหรับการติดตั้ง CLI ที่แคชไว้ภายใน Docker- ไดเรกทอรี/ไฟล์ auth ของ CLI ภายนอกภายใต้
$HOMEจะถูก mount แบบอ่านอย่างเดียวภายใต้/host-auth...จากนั้นคัดลอกไปยัง/home/node/...ก่อนเริ่มการทดสอบ- ไดเรกทอรีเริ่มต้น:
.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หรือรายการคั่นด้วยจุลภาค เช่น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เพื่อใช้อิมเมจopenclaw:local-liveที่มีอยู่ซ้ำสำหรับการรันซ้ำที่ไม่ต้อง rebuildOPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1เพื่อให้แน่ใจว่า creds มาจาก profile store (ไม่ใช่ env)OPENCLAW_OPENWEBUI_MODEL=...เพื่อเลือกโมเดลที่ gateway เปิดเผยสำหรับ smoke ของ Open WebUIOPENCLAW_OPENWEBUI_PROMPT=...เพื่อ override prompt ตรวจ nonce ที่ใช้โดย smoke ของ Open WebUIOPENWEBUI_IMAGE=...เพื่อ override แท็กอิมเมจ Open WebUI ที่ปักหมุดไว้
การตรวจ sanity ของเอกสาร
รันการตรวจเอกสารหลังแก้ไขเอกสาร: pnpm check:docs
รันการตรวจสอบ anchor ของ Mintlify แบบเต็มเมื่อคุณต้องการตรวจหัวข้อภายในหน้าด้วย: pnpm docs:check-links:anchors
Regression แบบออฟไลน์ (ปลอดภัยสำหรับ CI)
สิ่งเหล่านี้คือ regression ของ "pipeline จริง" โดยไม่มี providers จริง:
- การเรียกเครื่องมือของ Gateway (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 (WS
wizard.start/wizard.next, เขียน config + บังคับใช้ auth):src/gateway/gateway.test.ts(case: "runs wizard over ws and writes auth token config")
Evals ความน่าเชื่อถือของ Agent (skills)
เรามีการทดสอบที่ปลอดภัยสำหรับ CI อยู่แล้วบางส่วน ซึ่งทำงานคล้ายกับ "agent reliability evals":
- การเรียกเครื่องมือแบบ mock ผ่าน gateway จริง + agent loop (
src/gateway/gateway.test.ts) - โฟลว์วิซาร์ดแบบ end-to-end ที่ตรวจสอบการเชื่อม session และผลของ config (
src/gateway/gateway.test.ts)
สิ่งที่ยังขาดสำหรับ skills (ดู Skills):
- การตัดสินใจ: เมื่อมีการระบุ skills ใน prompt agent เลือก skill ที่ถูกต้องหรือไม่ (หรือหลีกเลี่ยง skill ที่ไม่เกี่ยวข้องหรือไม่)?
- การปฏิบัติตาม: agent อ่าน
SKILL.mdก่อนใช้และทำตามขั้นตอน/args ที่กำหนดหรือไม่? - สัญญาของเวิร์กโฟลว์: สถานการณ์แบบหลาย turn ที่ assert ลำดับเครื่องมือ, การส่งต่อประวัติ session และขอบเขต sandbox
evals ในอนาคตควรเน้น deterministic ก่อน:
- scenario runner ที่ใช้ mock providers เพื่อ assert การเรียกเครื่องมือ + ลำดับ, การอ่านไฟล์ skill และการเชื่อม session
- ชุดสถานการณ์ขนาดเล็กที่เน้น skill (ใช้เทียบกับหลีกเลี่ยง, gating, prompt injection)
- evals แบบสดที่เป็นทางเลือก (opt-in, gated ด้วย env) เฉพาะหลังจากมีชุดทดสอบที่ปลอดภัยสำหรับ CI แล้ว
การทดสอบสัญญา (รูปทรง plugin และช่องทาง)
การทดสอบสัญญาจะตรวจสอบว่า plugin และช่องทางที่ลงทะเบียนทุกตัวสอดคล้องกับ
สัญญา interface ของตนเอง การทดสอบจะวนผ่าน plugins ที่ค้นพบทั้งหมดและรันชุด
assertions ด้านรูปทรงและพฤติกรรม เลน unit ของ pnpm test เริ่มต้นตั้งใจ
ข้ามไฟล์ smoke และ seam ที่ใช้ร่วมกันเหล่านี้ ให้รันคำสั่ง contract อย่างชัดเจน
เมื่อคุณแตะพื้นผิวช่องทางหรือ provider ที่ใช้ร่วมกัน
คำสั่ง
- สัญญาทั้งหมด:
pnpm test:contracts - สัญญาช่องทางเท่านั้น:
pnpm test:contracts:channels - สัญญา provider เท่านั้น:
pnpm test:contracts:plugins
สัญญาช่องทาง
อยู่ใน src/channels/plugins/contracts/*.contract.test.ts:
- plugin - รูปทรง plugin พื้นฐาน (id, name, capabilities)
- setup - สัญญาวิซาร์ดการตั้งค่า
- session-binding - พฤติกรรมการผูก session
- outbound-payload - โครงสร้าง payload ของข้อความ
- inbound - การจัดการข้อความขาเข้า
- actions - handlers ของ action ช่องทาง
- threading - การจัดการ Thread ID
- directory - Directory/roster API
- group-policy - การบังคับใช้นโยบายกลุ่ม
สัญญาสถานะ provider
อยู่ใน src/plugins/contracts/*.contract.test.ts
- status - โพรบสถานะช่องทาง
- registry - รูปทรง registry ของ Plugin
สัญญา provider
อยู่ใน src/plugins/contracts/*.contract.test.ts:
- auth - สัญญาโฟลว์ Auth
- auth-choice - ตัวเลือก/การเลือก Auth
- catalog - API แค็ตตาล็อกโมเดล
- discovery - การค้นพบ Plugin
- loader - การโหลด Plugin
- runtime - รันไทม์ provider
- shape - รูปทรง/interface ของ Plugin
- wizard - วิซาร์ดการตั้งค่า
ควรรันเมื่อใด
- หลังเปลี่ยน exports หรือ subpaths ของ plugin-sdk
- หลังเพิ่มหรือแก้ไขช่องทางหรือ provider plugin
- หลัง refactor การลงทะเบียนหรือการค้นพบ plugin
การทดสอบสัญญารันใน CI และไม่ต้องใช้ API keys จริง
การเพิ่ม regressions (แนวทาง)
เมื่อคุณแก้ปัญหา provider/model ที่พบจากการรันสด:
- เพิ่ม regression ที่ปลอดภัยสำหรับ CI หากเป็นไปได้ (mock/stub provider หรือจับ transformation ของ request-shape ที่ตรงจุด)
- ถ้ามันเป็นแบบ live-only โดยธรรมชาติ (rate limits, auth policies) ให้การทดสอบสดมีขอบเขตแคบและ opt-in ผ่าน env vars
- ควรเล็งไปที่เลเยอร์ที่เล็กที่สุดซึ่งจับบั๊กได้:
- บั๊กการแปลง/เล่นซ้ำคำขอของ provider → การทดสอบ models โดยตรง
- บั๊ก pipeline ของ session/history/tool ของ gateway → gateway live smoke หรือการทดสอบ mock gateway ที่ปลอดภัยสำหรับ CI
- Guardrail การ traverse SecretRef:
src/secrets/exec-secret-ref-id-parity.test.tsดึง target ตัวอย่างหนึ่งรายการต่อคลาส SecretRef จากเมทาดาทา registry (listSecretTargetRegistryEntries()) แล้ว assert ว่า exec ids ที่เป็น traversal segment ถูกปฏิเสธ- หากคุณเพิ่ม target family ของ SecretRef แบบ
includeInPlanใหม่ในsrc/secrets/target-registry-data.tsให้อัปเดตclassifyTargetClassในการทดสอบนั้น การทดสอบตั้งใจ fail กับ target ids ที่ยังไม่ถูกจัดประเภท เพื่อไม่ให้คลาสใหม่ถูกข้ามอย่างเงียบ ๆ