test(backend): 编排引擎/DSL/docx/报告导出 首批 Go 单测(19 用例,纯逻辑无依赖)
补齐核心后端逻辑的自动化测试,全部纯函数级、不依赖 docker/NATS/LLM,毫秒级跑完, 把"手动起全栈 curl 验证"变成 `go test`: - dispatcher/internal/eino (graph_test.go) evalCondition(各运算符+refs/tools/answer/profile 关键字+兜底)、resolveOperand、 aggregate(拼接/去重合并/默认/全空)、branchNode(真假边标签精确选路 + 无标签退回边序 + 单边剪枝)、cstr/cbool/countLines/labelOf/targetsOf。 - dispatcher/internal/dsl (compile_test.go) Topo(线性序 + 有环不丢节点)、Compile(system/query/tools 抽取 + 无输入兜底 + 空图用原文)、 ToolBinding(tool/retriever/非工具)、Parse(合法/非法)。 - mcp-go/internal/office (unioffice_test.go) RenderReport 产物为合法 docx(zip 三部件 + 标题/章节文本 + XML 转义)、escapeXML。 - mcp-go/internal/mcp (report_test.go) reportMarkdown(标题+多章 / 无标题)。 - gateway/internal/dsl (parser_test.go) ParseAndAssemble(task_ 前缀 + Graph 透传 + Meta 初始化 + 空/非法报错)。 `go test ./...` 各模块全绿。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package office
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRenderReport_ValidDocx(t *testing.T) {
|
||||
secs := []Section{
|
||||
{Heading: "第一章", Body: "正文内容 A&B"},
|
||||
{Heading: "第二章", Body: "正文 <内容> B"},
|
||||
}
|
||||
data, err := NewRenderer().RenderReport(context.Background(), "测试报告", secs)
|
||||
if err != nil {
|
||||
t.Fatalf("RenderReport err: %v", err)
|
||||
}
|
||||
zr, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
if err != nil {
|
||||
t.Fatalf("产物不是合法 zip/docx: %v", err)
|
||||
}
|
||||
parts := map[string]string{}
|
||||
for _, f := range zr.File {
|
||||
rc, _ := f.Open()
|
||||
b, _ := io.ReadAll(rc)
|
||||
rc.Close()
|
||||
parts[f.Name] = string(b)
|
||||
}
|
||||
for _, need := range []string{"[Content_Types].xml", "_rels/.rels", "word/document.xml"} {
|
||||
if _, ok := parts[need]; !ok {
|
||||
t.Errorf("docx 缺少部件 %s", need)
|
||||
}
|
||||
}
|
||||
doc := parts["word/document.xml"]
|
||||
if !strings.Contains(doc, "测试报告") || !strings.Contains(doc, "第一章") || !strings.Contains(doc, "第二章") {
|
||||
t.Error("document.xml 应含标题与各章标题")
|
||||
}
|
||||
// XML 特殊字符必须转义,避免破坏文档。
|
||||
if strings.Contains(doc, "A&B") || !strings.Contains(doc, "A&B") {
|
||||
t.Error("正文 & 应被转义为 &")
|
||||
}
|
||||
if strings.Contains(doc, "<内容>") || !strings.Contains(doc, "<内容>") {
|
||||
t.Error("正文尖括号应被转义")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEscapeXML(t *testing.T) {
|
||||
got := escapeXML(`a&b<c>"d'`)
|
||||
want := "a&b<c>"d'"
|
||||
if got != want {
|
||||
t.Errorf("escapeXML = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user