跳至主要內容

EDD 测试指南

Mr.Lexon大约 2 分钟EDD

Title

EDD 测试指南:副作用驱动架构下的多层次测试策略

一、测试的结构定位

在 Effect-Driven Design (EDD) 架构中,系统被分为以下五层:

core ──► domain ──► app ──► event ──► infra

每层的副作用等级不同,测试方法、测试目标也随之不同。

层级目标副作用等级测试策略
core纯函数业务逻辑0单元测试 + 属性测试 + 形式化验证(可选)
domaintrait 抽象接口1mock注入测试 + contract约束
appusecase 组合逻辑2trait+mock组合测试 + YAML驱动测试生成
event副作用调度逻辑2/3事件断言测试 + event schema 测试
infra副作用真实实现3集成测试(db/api/log) + 端到端测试

二、core 层测试

目标:100% 纯函数测试

  • 所有业务模型(User, Post, Order)的方法都不应有副作用
  • 所有校验函数(validate_开头)都应测试全路径
  • 未来可采用形式化测试,比如说quick check
#[test]
fn test_validate_username() {
    assert!(validate_username("ab").is_err());
    assert!(validate_username("valid_user").is_ok());
}

三、app 层 usecase 测试

目标:

  • 使用 mock 实现隔离所有副作用(DB/API/AB决策)
  • 断言返回值 + 断言 events 中的副作用语义

推荐结构

#[tokio::test]
async fn test_register_user_success() {
    let mut mock_repo = MockUserRepository::new();
    let mut mock_ab = MockABSelector::new();

    mock_repo.expect_exists().return_const(false);
    mock_ab.expect_is_in_experiment().returning(|_, _| Ok(true));

    let result = register_user(input, &mock_repo, &mock_ab).await.unwrap();
    assert!(result.events.contains(&AppEvent::SendWelcomeEmail { .. }));
}

四、event 层测试(事件语义验证)

目标:

  • 对于每种事件,确保:
    • 构造正确(payload 合法)
    • schema 正确(可序列化)
    • 分发机制逻辑正确
#[test]
fn test_send_email_event_serialization() {
    let evt = AppEvent::SendWelcomeEmail { to: "a@b.com".into() };
    let json = serde_json::to_string(&evt).unwrap();
    assert!(json.contains("SendWelcomeEmail"));
}

五、infra 层测试(副作用实现)

目标:

  • 实际发邮件 / 调用 API / 写数据库 的行为正确
  • 支持集成测试(用 testcontainers 或 test SQLite)
#[tokio::test]
async fn test_user_repo_save_and_list() {
    let db = setup_test_db().await;
    let repo = SeaUserRepository { db };

    let user = User::new(...);
    repo.save(&user).await.unwrap();
    let list = repo.list().await.unwrap();
    assert_eq!(list.len(), 1);
}

六、测试覆盖规划

建议覆盖率
core100% 单元测试
domain100% mock/trait行为路径
appusecase主路径全覆盖 + 多副作用分支测试
event所有事件结构测试 + 流路径测试
infra核心接口集成测试 + 副作用可观测性测试

七、其他建议

  • 所有 usecase 应测试其 Outcome<T, Vec<AppEvent>> 的结构完整性
  • 所有副作用 trait 都应有 mockable + test impl
  • 所有事件建议在 CI 中跑 schema 检查
  • 建议引入 proptest 对纯逻辑进行属性测试
  • 使用 cargo-nextest 加速异步 usecase 级测试执行

八、结语

副作用驱动架构中,测试本身也必须“语义化”:测试的目标不再是命中路径,而是验证意图清晰的语义行为是否被正确组织与触发。 测试设计就是 usecase 设计的镜像 —— 它也是架构表达力的一部分。

上次编辑于:
贡献者: lexon