Skip to content

测试与调试

本文给出在 Easy-Agents 中进行单元测试与问题定位的建议,结合流式执行与结果池两种视角。

单元测试基础

  • 依赖:JUnit 5、Reactor Test(StepVerifier
  • 建议:
    • startStreaming() 使用 StepVerifier 验证完成:
      java
      StepVerifier.create(manager.startStreaming())
          .thenConsumeWhile(e -> true) // 接受所有事件
          .verifyComplete();
    • startBlocking() 验证结果池:
      java
      var pool = manager.startBlocking();
      assertThat(pool).containsKey(nodeId);

流式调试打点

  • 在订阅链路添加日志:
    java
    manager.startStreaming()
        .doOnSubscribe(s -> log.info("subscribed"))
        .doOnNext(e -> log.info("NEXT: {}", e))
        .doOnError(ex -> log.error("ERR", ex))
        .doOnComplete(() -> log.info("DONE"))
        .blockLast();
  • 目的:观察事件顺序、节点间数据传递与异常定位。

结果池核对

  • 工作流结束后:
    • 打印 manager.getResultPool() 检查每个节点聚合结果是否符合预期。
    • 子节点通过 build(upstreamId) 取到的是上游的“最后一个值”。

常见问题与定位

  • NPE:
    • 现象:子节点执行时从结果池取上游数据为空。
    • 根因:多次调用 setStartNode 导致根 UUID 更换或接线错误。
    • 方案:仅调用一次 setStartNode,统一使用同一个 rootNodeaddChild
  • 事件不触发:
    • 现象:startStreaming() 无输出。
    • 根因:未订阅、订阅前抛错、或节点未接线。
    • 方案:确认 blockLast()subscribe();为链路添加 doOnError;检查 addChild
  • AI 输出不稳定:
    • 现象:测试断言对具体 token 失败。
    • 方案:对流只断言完成(verifyComplete()),或断言“包含/格式”而非精确内容。

端到端示例

  • 流式 + 结果池双重校验:
    java
    var flux = manager.startStreaming();
    StepVerifier.create(flux)
        .thenConsumeWhile(e -> true)
        .verifyComplete();
    
    var pool = manager.getResultPool();
    assertThat(pool).containsKeys(upstreamId, downstreamId);

日志建议

  • 为每个节点命名/标注(在 CodeNode 中打印自定义前缀),便于从日志上还原 DAG。
  • 对关键路由点记录:父计数、是否放行、写入结果池的 key 与 value 概要。

Released under the MIT License.