feat: VBA Automated Testing and Precise Error Reporting System
Implement a comprehensive VBA testing framework that provides precise line-by-line error reporting through code weaving technology. Core Features: - CodeWeaver: Injects line number labels and error handling into VBA code - LoggerInjector: Manages TestLogger module for capturing test results - TestRunner: Orchestrates Excel lifecycle and test execution - Command-line interface supporting single and batch testing Key Capabilities: - Captures exact line numbers where errors occur - Displays source code context for error locations - Non-invasive testing (original files unchanged) - Batch testing support with detailed summaries Components: - vba_test_runner.py: Main framework implementation - demo.xlsm: Demo Excel file with test procedures - create_demo.py: Script to generate demo files - check_vba_access.py: VBA access permission checker Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
234
README.md
Normal file
234
README.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# VBA 自动化测试与精确报错系统
|
||||
|
||||
通过代码编织(Code Weaving)技术,实现 VBA 宏的精确到行的代码报错定位。
|
||||
|
||||
## 核心特性
|
||||
|
||||
- **精确行号定位**: 捕获 VBA 错误的具体行号,不再只是"发生意外"
|
||||
- **源代码映射**: 通过 Source Map 机制显示出错行的原始代码
|
||||
- **自动化测试**: 批量执行 VBA 宏并收集结果
|
||||
- **非侵入式**: 测试过程不修改原始 Excel 文件
|
||||
- **详细报告**: 提供清晰的测试结果输出
|
||||
|
||||
## 安装依赖
|
||||
|
||||
```bash
|
||||
pip install xlwings pywin32
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 创建演示文件
|
||||
|
||||
首先创建一个包含测试代码的 Excel 文件:
|
||||
|
||||
```bash
|
||||
python create_demo.py
|
||||
```
|
||||
|
||||
这将创建 `demo.xlsm` 文件,包含以下测试过程:
|
||||
- `TestErrorProcedure`: 除以零错误
|
||||
- `TestTypeMismatch`: 类型不匹配错误
|
||||
- `TestSubscriptError`: 下标越界错误
|
||||
- `TestSuccessfulProcedure`: 成功执行的测试
|
||||
|
||||
### 2. 运行测试
|
||||
|
||||
测试单个过程:
|
||||
|
||||
```bash
|
||||
python vba_test_runner.py demo.xlsm Module1 TestSuccessfulProcedure
|
||||
```
|
||||
|
||||
批量测试多个过程:
|
||||
|
||||
```bash
|
||||
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)
|
||||
|
||||
系统通过以下步骤实现精确报错:
|
||||
|
||||
1. **解析 VBA 代码**: 识别所有 Sub/Function 过程
|
||||
2. **注入行号标签**: 在可执行代码前插入数字标签(10, 20, 30...)
|
||||
3. **注入错误处理**: 添加 `On Error GoTo` 语句和错误处理块
|
||||
4. **创建 Source Map**: 维护行号到源代码的映射
|
||||
|
||||
### VBA 行号机制
|
||||
|
||||
VBA 的 `Erl` 函数会返回最近执行的行号标签:
|
||||
|
||||
```vba
|
||||
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 语句
|
||||
|
||||
### 错误处理模板
|
||||
|
||||
```vba
|
||||
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)` 确保注入的代码不会污染原始文件。
|
||||
|
||||
## 限制和注意事项
|
||||
|
||||
1. **信任访问 VBA 项目**: 需要在 Excel 信任中心启用"信任对 VBA 工程对象模型的访问"
|
||||
- 路径: 文件 > 选项 > 信任中心 > 信任中心设置 > 宏设置 > 勾选"信任对 VBA 工程对象模型的访问"
|
||||
|
||||
2. **行号标签冲突**: 如果原始代码中已使用相同数值的行号标签,可能会产生冲突
|
||||
|
||||
3. **复杂过程**: 对于非常复杂的过程(包含大量 GoTo 语句),可能需要额外处理
|
||||
|
||||
4. **只支持标准模块**: 当前版本不支持类模块和窗体模块
|
||||
|
||||
## 扩展开发
|
||||
|
||||
### 添加新的测试过程
|
||||
|
||||
在 Excel 文件的 VBA 模块中添加你的测试过程:
|
||||
|
||||
```vba
|
||||
Sub YourTestProcedure()
|
||||
' 你的测试代码
|
||||
End Sub
|
||||
```
|
||||
|
||||
然后运行:
|
||||
|
||||
```bash
|
||||
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!
|
||||
Reference in New Issue
Block a user