2cb22df60cd38700471fa0296c9ec45d2fbbbe21
## Phase 1: Core Call Chain Tracking ### New Features - CallStack class module: Manually maintain VBA call stack - Enhanced TestLogger: Integrated call stack management - LogEntry: Record on procedure entry - LogExit: Pop on procedure exit - LogError: Capture complete call chain - Weave all procedures in module to support call chain tracking ### Data Model Updates - TestResult new fields: error_module, call_chain - Result format: ERROR|Module.Proc|Line|Number|Desc|CallChain ### Key Fixes - Fixed LogSuccess overwriting error state LogSuccess now only sets success when no error exists - Fixed incomplete call chain due to weaving only single procedure Now weaves all procedures in the entire module ## Phase 2: Full Project Testing ### New Methods - CodeWeaver.parse_modules: Parse all VBA modules - CodeWeaver.weave_module_all_procedures: Weave all procedures in single module - CodeWeaver.weave_all_modules: Weave all procedures in multiple modules - TestRunner.discover_all_tests: Auto-discover all entry points - TestRunner.run_all_tests: Batch execute all tests - TestRunner._weave_all_modules_inplace: In-place weave all modules ### CLI Interface - Mode 1: python vba_test_runner.py <file> --all (full project testing) - Mode 2: python vba_test_runner.py <file> <module> <proc>... (specific testing) ## Test Verification ### Call Chain Tracking Example TestSuccessfulProcedure -> TestErrorProcedure -> TestTypeMismatch Output: Call Chain: Module1.TestSuccessfulProcedure -> Module1.TestErrorProcedure -> Module1.TestTypeMismatch Location: Module1.TestTypeMismatch:20 Source: y = 20 ### Statistics - New code: ~500 lines - New methods: 8 - Test scenarios: Multi-level nested call chain verification passed Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
VBA 自动化测试与精确报错系统
通过代码编织(Code Weaving)技术,实现 VBA 宏的精确到行的代码报错定位。
核心特性
- 精确行号定位: 捕获 VBA 错误的具体行号,不再只是"发生意外"
- 源代码映射: 通过 Source Map 机制显示出错行的原始代码
- 自动化测试: 批量执行 VBA 宏并收集结果
- 非侵入式: 测试过程不修改原始 Excel 文件
- 详细报告: 提供清晰的测试结果输出
安装依赖
pip install xlwings pywin32
快速开始
1. 创建演示文件
首先创建一个包含测试代码的 Excel 文件:
python create_demo.py
这将创建 demo.xlsm 文件,包含以下测试过程:
TestErrorProcedure: 除以零错误TestTypeMismatch: 类型不匹配错误TestSubscriptError: 下标越界错误TestSuccessfulProcedure: 成功执行的测试
2. 运行测试
测试单个过程:
python vba_test_runner.py demo.xlsm Module1 TestSuccessfulProcedure
批量测试多个过程:
python vba_test_runner.py demo.xlsm Module1 TestErrorProcedure TestTypeMismatch TestSubscriptError TestSuccessfulProcedure
输出示例
单个测试
成功时:
[PASS] TestSuccessfulProcedure - Test Passed
失败时:
[FAIL] TestErrorProcedure - Test Failed
Error Description: Division by zero
Error Line: 30
Source Code: result = x / y
批量测试
===== VBA Batch Test Results =====
[1/4] [FAIL] TestErrorProcedure - Test Failed
Error Description: Division by zero
Error Line: 30
Source Code: result = x / y
[2/4] [FAIL] TestTypeMismatch - Test Failed
Error Description: Type mismatch
Error Line: 20
Source Code: y = x
[3/4] [FAIL] TestSubscriptError - Test Failed
Error Description: Subscript out of range
Error Line: 40
Source Code: value = arr(5)
[4/4] [PASS] TestSuccessfulProcedure - Test Passed
===== Test Summary =====
Passed: 1/4
Failed: 3/4
工作原理
代码编织(Code Weaving)
系统通过以下步骤实现精确报错:
- 解析 VBA 代码: 识别所有 Sub/Function 过程
- 注入行号标签: 在可执行代码前插入数字标签(10, 20, 30...)
- 注入错误处理: 添加
On Error GoTo语句和错误处理块 - 创建 Source Map: 维护行号到源代码的映射
VBA 行号机制
VBA 的 Erl 函数会返回最近执行的行号标签:
10 x = 10
20 y = 0
30 result = x / y ' Erl 将返回 30
测试流程
原始 VBA 代码
↓
代码编织器注入行号和错误处理
↓
注入 _TestLogger 辅助模块
↓
热替换目标模块代码
↓
执行 VBA 宏
↓
从 _TestLogger 读取结果
↓
格式化输出
架构设计
模块划分
vba_test_runner.py
├── CodeWeaver (代码编织器类)
│ ├── parse_procedures() - 解析 VBA 过程
│ ├── weave_procedure() - 编织单个过程
│ ├── _inject_line_numbers() - 注入行号标签
│ └── _inject_error_handler() - 注入错误处理
│
├── LoggerInjector (日志模块注入器类)
│ ├── inject_or_replace() - 注入或替换 Logger 模块
│ └── LOGGER_MODULE_CODE - Logger 模块的 VBA 代码
│
└── TestRunner (执行控制器类)
├── run_test() - 执行完整测试流程
├── _get_vba_code() - 读取 VBA 代码
├── _replace_module_code() - 热替换模块代码
├── _execute_macro() - 执行宏
└── _get_test_result() - 获取测试结果
关键技术点
行号标签规则
- 使用纯数字标签:
10,20,30... (不带冒号) - 只在可执行代码前注入
- 跳过声明区(Dim, Private 等)
- 跳过注释行和空行
- 跳过现有的 On Error 语句
错误处理模板
On Error GoTo Auto_Err_Handler_{proc_name}
... 原有代码 ...
Call _TestLogger.LogSuccess()
Exit Sub/Function
Auto_Err_Handler_{proc_name}:
Call _TestLogger.LogError("{proc_name}", Err.Number, Err.Description, Erl)
热替换不保存
使用 wb.Close(SaveChanges=False) 确保注入的代码不会污染原始文件。
限制和注意事项
-
信任访问 VBA 项目: 需要在 Excel 信任中心启用"信任对 VBA 工程对象模型的访问"
- 路径: 文件 > 选项 > 信任中心 > 信任中心设置 > 宏设置 > 勾选"信任对 VBA 工程对象模型的访问"
-
行号标签冲突: 如果原始代码中已使用相同数值的行号标签,可能会产生冲突
-
复杂过程: 对于非常复杂的过程(包含大量 GoTo 语句),可能需要额外处理
-
只支持标准模块: 当前版本不支持类模块和窗体模块
扩展开发
添加新的测试过程
在 Excel 文件的 VBA 模块中添加你的测试过程:
Sub YourTestProcedure()
' 你的测试代码
End Sub
然后运行:
python vba_test_runner.py your_file.xlsm Module1 YourTestProcedure
自定义 Logger 模块
修改 LoggerInjector.LOGGER_MODULE_CODE 可以自定义日志记录逻辑。
常见问题
Q: 为什么测试后原始文件没有被修改?
A: 系统使用热替换技术,在内存中修改代码,测试完成后使用 Close(SaveChanges=False) 不保存更改。
Q: 如何测试类模块中的方法?
A: 当前版本只支持标准模块。要测试类模块,可以创建一个包装的 Sub 在标准模块中调用类方法。
Q: 可以捕获运行时警告吗?
A: 当前版本只捕获错误。要捕获警告,需要修改 Logger 模块来处理 InfoMessage 事件。
许可证
MIT License
贡献
欢迎提交 Issue 和 Pull Request!
Description
Languages
Python
100%