# 第10章 用测试拆层理解编译流程
# 一、前言
测试是理解与防回归的“放大镜”。通过分层测试,我们能快速定位问题处于哪一层。
# 二、目标
- 建立分层测试视角:词法/AST/语义/端到端
- 掌握标准输出捕获与诊断断言写法
- 能按需单独运行任一测试类
# 三、设计
核心流程图:
架构交互图:
# 四、实现
目录树(关注项):
src
└── test
└── java
└── com
└── lxg
├── SemanticErrorTest.java
└── LxgEndToEndTest.java
命令:
mvn -q test
mvn -q -Dtest=LxgEndToEndTest test
代码对照:捕获标准输出(节选)
private String run(String source) {
PrintStream oldOut = System.out;
ByteArrayOutputStream bout = new ByteArrayOutputStream();
System.setOut(new PrintStream(bout));
try {
Main.runSource(source, null, false, false, false);
return new String(bout.toByteArray());
} finally {
System.setOut(oldOut);
}
}
代码对照:诊断断言(未声明变量)
@Test
public void undeclared_variable() {
String src = "print x;";
LxgLexer lexer = new LxgLexer(CharStreams.fromString(src));
CommonTokenStream tokens = new CommonTokenStream(lexer);
LxgParser parser = new LxgParser(tokens);
CompilationUnit unit = new AstBuilder().build(parser.prog());
Diagnostics diags = new TypeChecker().check(unit);
assertTrue(diags.hasErrors());
assertTrue(diags.getErrors().stream().anyMatch(e -> e.contains("Unknown variable")));
}
# 五、测试
- 运行:
mvn -q test
- 常见排错:
- 输出不一致:注意换行
\n
与顺序 - 诊断为空:确认未跳过语义层或样例无错
- 输出不一致:注意换行
# 六、总结
- 测试拆层能显著提升定位效率;端到端测试保证主线用法稳定