
人工智能AI 应用交互助手AI Agent【免费下载链接】ironclawIronClaw is an Agent OS focused on privacy, security and extensibility项目地址https://gitcode.com/gh_mirrors/iro/ironclaw点击查看免费下载本篇技术指南系统讲解 Agent OS 项目 IronClaw 的完整测试体系包括测试优先test-first开发纪律、三层测试分层单元 / 集成 / E2E的定位与取舍、全套cargo运行命令、五大测试模式、覆盖率目标与 CI/CD 质量门禁以及针对 Agent 循环、能力Capability、数据库、安全等不同领域的测试写法。读完本文你将能按照 IronClaw 的规范为任意模块编写单元、集成与契约测试掌握调试与排查 flaky 测试的完整方法论并把测试接入本仓库现有的 CI 流水线。测试哲学通过调用方测试而不是只测辅助函数IronClaw 采用test-first 纪律每个 Bug 修复必须附带一个回归测试每个功能变更都应包含验证该变更的测试。目标是尽早捕获回归并用测试固化预期行为。其核心原则是通过调用方caller测试而不是只测辅助函数当一个辅助函数控制副作用时HTTP 请求、数据库写入、OAuth 流程、工具执行、UI 变更必须在调用点测试而不是单独测试辅助函数本身。这一原则在仓库中随处可见——例如 tests/integration/AGENTS.md 明确要求通过真实路径测试test through the real path断言的是持久化的回复、记录的边界调用与状态而不是内部实现集成测试只有在 vendor-SDK 接缝处才允许替换脚本化模型其余整个LlmProviderModelGateway 装饰器链都必须真实执行。从源码结构看这一纪律还延伸到文档层面tests/AGENTS.md 作为仓库级场景测试覆盖映射要求每新增、重命名、删除一个场景测试都必须在同一提交内更新该文档且每一行都要能用一句平实的用户语言描述用户能做什么而非某个函数返回什么。测试三层单元、集成与 E2EIronClaw 将测试划分为三个层级每个层级有明确的定位、速度、数量与外部依赖Tier 1单元测试快速、隔离维度说明目的测试局部逻辑函数、结构体、纯计算速度每个 1 秒数量约 10,000 个外部依赖无必要时 mock命令cargo test --lib适用场景大多数测试的默认选择示例测试 sanitizer 函数、编码器、解析器Tier 2集成测试中等、真实依赖维度说明目的测试运行时行为、数据库交互、路由速度每个 1–60 秒数量约 1,000 个外部依赖PostgreSQL可选、libSQL内置命令cargo test --test *或cargo test --features integration适用场景用真实 DB 或服务端到端测试一个功能示例测试一个 turn 是否正确流过 Agent 循环仓库中的集成测试集中在 tests/integration/ 目录这里运行的是整个真实的 Reborn turn产品工作流、turn 协调器、调度器、Agent 循环、真实的LlmProviderModelGateway与ironclaw_llm装饰器链、真实的RootFilesystem持久化唯一被 faked 的是栈底——vendor-SDK 接缝处的脚本化模型。每个集成测试二进制的入口都注册在工作区根 Cargo.toml 的[[test]]段中如reborn_group_approvals、reborn_integration_golden_payload、reborn_integration_backend_matrix等数十个目标其 dev-dependencies 中引入了ironclaw_agent_loop、ironclaw_llm、ironclaw_auth等 crate 的test-supportfeature确保StubLlm、内存版能力租约存储等测试接缝只出现在测试二进制里而不会随发布版本分发。Tier 3E2E 测试慢速、全栈维度说明目的测试用户可见的流程浏览器 UI、API、CLI速度数分钟到数小时数量约 100 个外部依赖浏览器Playwright、LLM API、线上服务命令cargo test -- --ignored仅运行带标记的测试适用场景测试用户会执行的完整工作流示例测试一条 Slack 消息流经工具执行再返回仓库的 E2E 测试主要位于 tests/e2e/以 Python pytest 场景文件组织103 个场景文件、889 个测试函数见 tests/AGENTS.md覆盖 WebUI、Slack/Telegram 通道、扩展生命周期、OAuth、自动化与项目等用户可见流程其说明文档见 tests/e2e/CLAUDE.md。运行测试从冒烟到全量快速冒烟测试# 运行全部快速测试单元 部分集成 cargo test --lib本地全量测试套件# 运行单元 集成测试无需外部服务 cargo test带 PostgreSQL 的全量测试# 启动 PostgreSQL docker-compose up -d postgres # 使用 PostgreSQL 后端运行全部测试 IRONCLAW_HOOKS_POSTGRES_URLpostgres://ironclaw:ironclaw127.0.0.1:5432/ironclaw \ cargo test --features postgresPostgreSQL 的编排配置见 docker-compose.yml默认端口 5432、库名ironclaw。测试默认走 libSQL 后端PostgreSQL 用于双后端场景验证——tests/integration/backend_matrix.rs 专门断言行为在内存、libSQL、PostgreSQL 三种存储上完全一致。只跑 E2E 测试# 运行带 #[ignore] 标记的测试 cargo test -- --ignored单测或单模块# 运行单个测试 cargo test test_my_feature # 运行某个 crate 的全部测试 cargo test -p ironclaw_agent_loop # 运行某个文件中的测试 cargo test --test executor_happy_paths # 按模式匹配运行测试 cargo test --lib safety监听模式# 文件变更时自动重跑测试 cargo watch -x test # 只监听单元测试 cargo watch -x test --lib环境搭建细节如scripts/dev-setup.sh会安装 clippy、rustfmt、wasm32 目标与 cargo-nextest、cargo-deny、cargo-watch 等工具可参见 openwiki/development/setup.md。测试结构单元、集成与契约测试单元测试示例#[cfg(test)] mod tests { use super::*; #[test] fn test_sanitizer_removes_injection() { let input Hello {{prompt_injection}}; let result sanitize(input); assert_eq!(result, Hello); // 注入已被移除 } #[test] fn test_sanitizer_preserves_safe_text() { let input Hello world; let result sanitize(input); assert_eq!(result, Hello world); } }关键要点每个测试只验证一个行为使用描述性命名test_*_should_*或test_*_when_*同时覆盖 happy path 与边界情况使用能显示失败原因的断言assert_eq!、assert!测试中允许unwrap()集成测试示例// tests/executor_happy_paths.rs #[tokio::test] async fn test_loop_executes_tool_and_returns_result() { // Setup: 创建一个最小的执行器环境 let db setup_test_db().await; let mut executor ExecutorBuilder::default() .db(db.clone()) .build(); // Act: 运行一个简单的 turn let result executor.execute(ExecutorRequest { thread_id: test-thread, message: whats 22?, ..Default::default() }).await; // Assert: 验证结果 assert_ok!(result); assert_eq!(result.exit, LoopExit::Done); assert!(result.output.contains(4)); }关键要点异步测试使用#[tokio::test]搭建真实但最小化的依赖内存 DB、mock HTTP通过公共 API 测试调用真实执行器而非内部实现断言整个流程而不是只断言其中一段仓库中的 Reborn 集成测试还遵循一次性脚本纪律脚本模型RebornScriptedReply是模型调用的 FIFO 队列普通回复 turn 消耗 1 条未加门的工具调用 turn 消耗 2 条tool_call 执行后的模型调用带审批/认证门的 turn 也恰好 2 条脚本条目过多会静默泄漏进下一个 turn造成难查的偶发失败。典型写法是build → submit_turn → assert三步式见 tests/integration/AGENTS.md。契约测试示例契约测试验证组件满足某个接口契约// crates/ironclaw_executor/tests/executor_happy_paths.rs // 测试 Executor trait 是否被正确实现 #[tokio::test] async fn executor_contract_simple_message() { // Executor 的所有实现都应通过此测试 // 例如 LlmExecutor、CodeActExecutor 等 }五大测试模式模式 1异步测试#[tokio::test] async fn test_async_operation() { let result some_async_function().await; assert_ok!(result); } // 需要多线程异步的测试 #[tokio::test(flavor multi_threaded)] async fn test_concurrent_operations() { // 多个 tokio 任务可以并发运行 }模式 2测试夹具与辅助函数// 定义测试辅助函数 async fn setup_test_environment() - (TestDb, TestExecutor, TestLlm) { // 创建测试替身 (db, executor, llm) } #[tokio::test] async fn test_with_fixtures() { let (db, executor, llm) setup_test_environment().await; // 在测试中使用夹具 }模式 3参数化测试#[test] fn test_parser_on_multiple_inputs() { let cases vec![ (input1, expected1), (input2, expected2), (input3, expected3), ]; for (input, expected) in cases { let result parse(input); assert_eq!(result, expected, Failed for input: {}, input); } }仓库中更工程化的参数化方案是rstest已在根 Cargo.toml 的 dev-dependencies 中声明rstest 0.23用于存储后端矩阵等场景的#[case]参数化。模式 4测试错误路径#[test] fn test_invalid_input_returns_error() { let result validate_input(); assert!(result.is_err()); assert_eq!(result.unwrap_err(), ValidationError::EmptyInput); }模式 5Mock 外部服务// 测试中使用 mock HTTP 服务器 #[tokio::test] async fn test_llm_provider_calls_api() { let mock_server mockito::Server::new_async().await; // Mock LLM API mock_server.mock(POST, /v1/completions) .with_status(200) .with_body(r#{choices:[{text:hello}]}#) .create_async() .await; let provider OpenAiProvider::new_with_url(mock_server.url()); let result provider.complete(request).await; assert_ok!(result); }仓库还提供了更贴近生产路径的 LLM 测试替身ironclaw_llm的test-supportfeature 提供StubLlm与故障注入辅助tests/support/trace_llm.rs 与 tests/trace_llm_tests.rs 则演示如何用录制好的真实 LLM trace 回放模型行为。代码覆盖率目标与查看方式查看覆盖率# 生成覆盖率报告需要 cargo-tarpaulin 或 cargo-llvm-cov cargo tarpaulin --out Html # 打开报告 open tarpaulin-report.html # 或使用 llvm-cov cargo llvm-cov --html open target/llvm-cov/html/index.html覆盖率目标最低要求全代码库 60%安全层90%安全关键Agent 循环80%能力Capabilities70%当前覆盖率状态可在 CI 流水线中查看GitHub Actions 的 .github/workflows/coverage.yml。仓库还维护了一份详细的 COVERAGE_PLAN.md按每单位工作量换取的覆盖行数排定了六个执行层级Trace 测试Tier 2约 7,000 行杠杆率最高——每个 trace 测试通过TestRigBuilder回放 LLM trace可同时覆盖多个模块其次是 0% 文件的单元测试、Web handler 测试用axum_test或tower::ServiceExt::oneshot 内存 DB 构建真实路由、CLI 子命令测试、Setup 向导抽取测试等。所有 trace 测试均要求--features libsql。CI/CD 中的测试GitHub Actions 工作流工作流用途触发时机时长test.yml运行全部单元/集成测试PR、push约 10 分钟reborn-tests.ymlReborn crate 测试PR、push约 5 分钟e2e.yml浏览器级 E2E 测试手动、dispatch约 30 分钟code_style.yml格式化、clippy、依赖检查PR、push约 5 分钟coverage.yml覆盖率测量push 到 main约 20 分钟仓库中实际存在的工作流包括 .github/workflows/reborn-tests.yml、.github/workflows/reborn-e2e.yml、.github/workflows/reborn-playwright.yml、.github/workflows/code_style.yml 与 .github/workflows/coverage.ymlCI 概述可参考 .github/workflows/README.md。另有专门的reborn_coverage_lane_stack_headroom.rs断言 CI 任务需声明足够的栈余量对应 tests/reborn_coverage_lane_stack_headroom.rs。提交前检查pre-commitpre-commit git 钩子会在你提交时自动运行# 在 git commit 时自动运行 1. cargo fmt -- --check 格式化 2. cargo clippy -- -D warnings lint 3. cargo deny check 依赖审计 4. UTF-8 校验如果失败修复它们# 修复格式化 cargo fmt # 修复 clippy 警告 cargo clippy --fix推送前检查pre-pushpre-push git 钩子会在你推送时自动运行# 在 git push 时自动运行 1. 全部 pre-commit 检查 2. 单元测试cargo test --lib 3. 回归测试带 #[ignore] 标记的测试 4. 架构边界测试如果 pre-push 失败要么修复问题要么使用git push --no-verify应尽量少用。为不同领域编写测试测试 Agent 循环变更// tests/agent_loop_contract.rs #[tokio::test] async fn test_loop_handles_capability_timeout() { let mut executor TestExecutor::new(); // 为能力设置超时 executor.set_timeout(Duration::from_millis(100)); // 请求一个会超时的能力 let result executor.execute(ExecutorRequest { message: call slow_tool, ..Default::default() }).await; // 验证超时处理 assert_eq!(result.exit, LoopExit::Error); assert!(result.error.contains(timeout)); }测试能力Capability实现// crates/ironclaw_*/tests/capability_contract.rs #[tokio::test] async fn test_capability_conforms_to_host_api() { let host TestHost::new(); let capability MyCapability::new(); // 能力应实现 CapabilityPort trait let request CapabilityRequest { ... }; let response capability.handle(request).await; assert_ok!(response); }测试数据库交互// tests/event_store_contract.rs #[tokio::test] async fn test_event_store_persists_and_retrieves() { let db setup_test_db().await; let event TestEvent { ... }; // 写入 db.append_event(event.clone()).await?; // 读取 let retrieved db.get_event(event.id).await?; // 验证 assert_eq!(retrieved, event); }测试安全特性// tests/safety_contract.rs #[test] fn test_injection_detector_catches_prompt_injection() { let input Complete this: {{system_prompt}}; let result detect_injection(input); assert!(result.is_injection); assert_eq!(result.injected_patterns, vec![{{system_prompt}}]); }安全层属高风险改动仓库要求先读 crates/ironclaw_safety/CLAUDE.md 理解现有行为再先写测试、实现检测逻辑、用真实攻击向量验证、最后以安全视角复查能否被绕过、边界情况、覆盖是否充分完整流程见 openwiki/development/workflows.md。测试优先的 Bug 修复工作流修复 Bug 时遵循以下纪律先写一个能复现 Bug 的失败测试#[test] fn test_bug_reproduced() { let input /* 触发 Bug 的用例 */; let result buggy_function(input); assert_eq!(result, /* 期望值 */); // 该测试当前失败 }验证测试确实失败cargo test test_bug_reproduced # 应输出thread ... test_bug_reproduced panicked修复 Bugfn buggy_function(input: str) - String { // 修复问题 }验证测试通过cargo test test_bug_reproduced # 应输出test test_bug_reproduced ... ok运行全部测试cargo test提交并附带规范信息git commit -m fix(agent-loop): handle timeout in capability request Fixes #123. Added regression test test_bug_reproduced that captures the timeout scenario.提交信息遵循 Conventional Commits 格式type(scope): messagetype 可取fix、feat、docs、style、refactor、test、chore仓库有专门的 commit-msg 钩子校验该格式。性能测试基准测试Benchmark#[bench] fn bench_sanitizer(b: mut Bencher) { let input /* 复杂注入 */; b.iter(|| { sanitize(input) }); }运行基准测试cargo bench -p ironclaw_safety压力测试负载测试使用 tools/ironclaw_stress/ 中的压力测试框架# 运行一次压力测试 cargo run -p ironclaw_stress -- --requests 1000 --concurrency 10调试测试带输出运行单个测试# 查看 println! 输出 cargo test test_my_feature -- --nocapture # 失败时查看回溯 RUST_BACKTRACE1 cargo test test_my_feature用 IDE 调试VS Code安装 CodeLLDB 扩展创建.vscode/launch.json{ version: 0.2.0, configurations: [ { type: lldb, request: launch, name: Debug Test, cargo: { args: [ test, --lib, test_my_feature, --, --nocapture ] } } ] }条件编译测试#[test] #[cfg(feature slow_tests)] fn test_slow_operation() { // 该测试仅在启用 feature 时运行 } // 运行cargo test --features slow_tests注意根 Cargo.toml 将 dev 与 test profile 的debug设为0对齐 CI 构建减小产物体积并命中缓存预算本地调试需要变量级检查时可用CARGO_PROFILE_DEV_DEBUG2 cargo cmd覆盖。另外调试时用debug!()而非info!()输出RUST_LOGdebug可开启调试日志避免敏感信息进入常规日志。常见测试问题问题本地通过但 CI 失败检查环境变量—— CI 可能没有你的本地环境变量检查文件路径—— CI 使用不同的工作目录检查时序—— CI 更慢超时测试可能 flaky检查操作系统—— CI 可能运行在与本机不同的 OS 上问题Flaky 测试Flaky 测试时好时坏常见原因时序问题使用tokio::time::sleep而非std::thread::sleep随机性在测试中为随机数生成器固定种子共享状态每个测试应相互独立网络mock 外部服务而不是调用真实 API修复示例#[tokio::test] async fn test_timing_sensitive() { // 使用 tokio sleep而非 std sleep tokio::time::sleep(Duration::from_millis(100)).await; } #[test] fn test_with_deterministic_rng() { use rand::SeedableRng; let mut rng rand::rngs::StdRng::seed_from_u64(42); // 现在 rng 是确定性的 }问题测试挂起如果测试挂起# 杀掉挂起的测试带超时 timeout 30 cargo test test_hanging # 或使用超时环境变量运行 TEST_TIMEOUT_SECS30 cargo test定位原因死锁检查锁、互斥量、channel 是否存在循环等待死循环添加超时或用println!调试外部服务mock 外部服务不要调用真实 API延伸阅读openwiki/development/setup.md —— 本地环境搭建含 dev-setup.sh 钩子安装openwiki/development/workflows.md —— 修复 Bug、加功能、Code Review 等开发流程AGENTS.md —— 仓库级编码规则与测试纪律COVERAGE_PLAN.md —— 覆盖率目标与分层执行策略tests/e2e/CLAUDE.md —— E2E 测试文档tests/AGENTS.md —— 场景测试覆盖映射与已知缺口tests/integration/AGENTS.md —— Reborn 集成测试编写规范赞分享人工智能AI 应用交互助手AI Agent【免费下载链接】ironclawIronClaw is an Agent OS focused on privacy, security and extensibility项目地址https://gitcode.com/gh_mirrors/iro/ironclaw点击查看免费下载相关推荐Skill Seekers 测试指南从 1,880 测试、四类测试分层到 CI/CD 质量门禁的完整实践Skill Seekers 测试指南从 1,880 测试、四类测试分层到 CI/CD 质量门禁的完整实践 Skill Seekers文档网站、GitHub人工智能AI 应用AI 技能RAGMCP 服务网页爬虫StaffML Vault 测试体系全解从测试金字塔到 CI 门禁的工程化质量防线StaffML Vault 测试体系全解从测试金字塔到 CI 门禁的工程化质量防线 本文是 StaffML Vault 数据管线 vault cli 命令行教育教程人工智能机器学习RustFS 测试体系全解分层策略、nextest 配置、CI 门禁与 Flake 治理RustFS 测试体系全解分层策略、nextest 配置、CI 门禁与 Flake 治理 RustFS 是一个开源、兼容 S3 的高性能对象存储系统其测试体后端对象存储分布式存储上一篇终极指南GildedRose-Refactoring-Kata多语言实现对比与重构技巧下一篇Turbo5分钟上手轻量级流程引擎框架创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考