Files
AutoBOM-BOMForge/VBA/Modules/mTestEngine.bas
Misaka_Company d17d7c5864 Add strategy pattern architecture for BOM module processing
- Add IModuleProcessor interface defining the processor contract
- Implement cProcessor_AppendOnly strategy for modifying existing BOM rows
- Implement cProcessor_CloneNew strategy for creating new BOM rows
- Add mProcessorFactory module for creating processor instances
- Add mSpecAdditionManager module for coordinating spec addition operations
- Enhance test suite with business logic layer and pipeline integration tests

This implements the Strategy pattern to allow flexible BOM modification behaviors while maintaining clean separation of concerns.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 14:09:29 +08:00

287 lines
11 KiB
QBasic
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
' ==============================================================================
' 模块名称: mTestEngine
' 模块类别: 标准模块 (Standard Module)
' 模块职责: 专门用于测试 cConditionEngine 类的逻辑准确性 (引入轻量级单元测试框架)
' ==============================================================================
Option Explicit
' 定义模块级变量,用于统计测试结果
Private passCount As Integer
Private failCount As Integer
Public Sub RunBOMForgeTests()
' 初始化计数器
passCount = 0
failCount = 0
' 执行条件引擎测试
Call Test_ConditionEngine
' 执行数据模型测试
Call Test_cBOMRow
' 执行存储库数据层测试
Call Test_BOMRepository
' 执行业务策略层测试
Call Test_Processors
' 执行调度中枢联调测试 (新增)
Call Test_Manager_Pipeline
' ---- 输出测试汇总 ----
Debug.Print "-----------------------------------------------"
Debug.Print "测试汇总: 共 " & (passCount + failCount) & " 个用例"
Debug.Print "通过: " & passCount & " 失败: " & failCount
If failCount = 0 Then
Debug.Print ">>> 状态: 全部通过! (ALL PASS)"
Else
Debug.Print ">>> 状态: 存在失败用例,请检查逻辑!"
End If
Debug.Print "========== BOMForge 测试框架结束 =========="
End Sub
Private Sub Test_ConditionEngine()
Dim conditionEngine As cConditionEngine
Set conditionEngine = New cConditionEngine
Dim originStr As String
Dim expectedStr As String
Dim paramName As String
Dim newValue As String
paramName = "lcfw"
newValue = "M19"
Debug.Print "========== 1. 开始测试: cConditionEngine =========="
' ---- 测试用例 1: 盘止钉 (纯 OR 链,无 AND无括号) ----
originStr = "lcfw=M01 OR lcfw=M02 OR lcfw=M30"
expectedStr = "lcfw=M01 OR lcfw=M02 OR lcfw=M30 OR lcfw=M19"
AssertEqual "场景1_盘止钉", expectedStr, conditionEngine.InjectOr(originStr, paramName, newValue)
' ---- 测试用例 2: 接头 (括号包裹的 OR 链,外面有 AND) ----
originStr = "(azxs=A0 OR azxs=AT OR azxs=AH) AND gclj=Z14 AND (lcfw=M12 OR lcfw=M13 OR lcfw=M14 OR lcfw=M15 OR lcfw=M16)"
expectedStr = "(azxs=A0 OR azxs=AT OR azxs=AH) AND gclj=Z14 AND (lcfw=M12 OR lcfw=M13 OR lcfw=M14 OR lcfw=M15 OR lcfw=M16 OR lcfw=M19)"
AssertEqual "场景2_接头", expectedStr, conditionEngine.InjectOr(originStr, paramName, newValue)
' ---- 测试用例 3: 弹性元件 (孤立的参数,外面有 AND需自动加括号) ----
originStr = "lcfw=M01 AND gclj!=M20"
expectedStr = "(lcfw=M01 OR lcfw=M19) AND gclj!=M20"
AssertEqual "场景3_弹簧管", expectedStr, conditionEngine.InjectOr(originStr, paramName, newValue)
' ---- 测试用例 4: 封口片 (右侧紧跟 AND 的情况) ----
originStr = "(lcfw=M12 OR lcfw=M13 OR lcfw=M14 OR lcfw=M15 OR lcfw=M16)AND gclj!=M20"
expectedStr = "(lcfw=M12 OR lcfw=M13 OR lcfw=M14 OR lcfw=M15 OR lcfw=M16 OR lcfw=M19)AND gclj!=M20"
AssertEqual "场景4_封口片", expectedStr, conditionEngine.InjectOr(originStr, paramName, newValue)
' ---- 测试用例 5: 防御性测试 (本身已经包含了目标条件,看是否会重复添加) ----
originStr = "lcfw=M01 OR lcfw=M19"
expectedStr = "lcfw=M01 OR lcfw=M19"
AssertEqual "场景5_防重复", expectedStr, conditionEngine.InjectOr(originStr, paramName, newValue)
End Sub
Private Sub Test_cBOMRow()
Debug.Print ""
Debug.Print "========== 2. 开始测试: cBOMRow 数据模型 =========="
Dim bomRow As cBOMRow
Set bomRow = New cBOMRow
AssertEqual "初始脏标记测试", "False", CStr(bomRow.IsDirty)
bomRow.RowNo = 700
bomRow.ModuleType = "接头"
bomRow.Code = "01081014361"
bomRow.ItemName = "径向高压接头"
bomRow.Condition = "(azxs=A0) AND gclj=Z14"
AssertEqual "赋值后脏标记测试", "True", CStr(bomRow.IsDirty)
bomRow.ResetDirtyFlag
AssertEqual "重置后脏标记测试", "False", CStr(bomRow.IsDirty)
bomRow.Condition = "(azxs=A0) AND gclj=Z14"
AssertEqual "重复赋值脏标记测试", "False", CStr(bomRow.IsDirty)
bomRow.Condition = "(azxs=A0) AND gclj=Z14 AND (lcfw=M19)"
AssertEqual "状态变更脏标记测试", "True", CStr(bomRow.IsDirty)
AssertEqual "属性读取测试", "(azxs=A0) AND gclj=Z14 AND (lcfw=M19)", bomRow.Condition
End Sub
Private Sub Test_BOMRepository()
Debug.Print ""
Debug.Print "========== 3. 开始测试: mBOMRepository 数据访问层 =========="
Dim wb As Workbook
Dim wsTemp As Worksheet
Set wb = ThisWorkbook
Application.DisplayAlerts = False
On Error Resume Next
wb.Worksheets("BOMForge_Test_Sandbox").Delete
On Error GoTo 0
Set wsTemp = wb.Worksheets.Add
wsTemp.Name = "BOMForge_Test_Sandbox"
wsTemp.Cells(3, 1).value = "行号"
wsTemp.Cells(4, 1).value = 10
wsTemp.Cells(4, 2).value = "接头"
wsTemp.Cells(4, 6).value = "lcfw=M01"
wsTemp.Cells(5, 1).value = 20
wsTemp.Cells(5, 2).value = "盘止钉"
wsTemp.Cells(5, 6).value = "lcfw=M02"
Dim bomColl As Collection
Set bomColl = LoadAllBOMs(wsTemp)
AssertEqual "加载集合数量", "2", CStr(bomColl.count)
AssertEqual "验证读取第一行", "接头", bomColl(1).ModuleType
AssertEqual "验证加载后脏标记为空", "False", CStr(bomColl(1).IsDirty)
bomColl(2).Condition = "lcfw=M02 OR lcfw=M19"
SaveAll wsTemp, bomColl
AssertEqual "验证Excel未被错误修改", "lcfw=M01", wsTemp.Cells(4, 6).value
AssertEqual "验证Excel正确更新", "lcfw=M02 OR lcfw=M19", wsTemp.Cells(5, 6).value
AssertEqual "验证保存后脏标记重置", "False", CStr(bomColl(2).IsDirty)
Dim newRow As cBOMRow
Set newRow = InsertNewBOMRow(bomColl, bomColl(1))
newRow.Condition = "lcfw=M19"
SaveAll wsTemp, bomColl
AssertEqual "验证新增行集合追加", "3", CStr(bomColl.count)
AssertEqual "验证新增行Excel保存", "lcfw=M19", wsTemp.Cells(6, 6).value
AssertEqual "验证新增行Excel映射行号", "6", CStr(newRow.ExcelRowIndex)
wsTemp.Delete
Application.DisplayAlerts = True
End Sub
Private Sub Test_Processors()
Debug.Print ""
Debug.Print "========== 4. 开始测试: 业务策略层 (Strategy) 新架构 =========="
Dim engine As cConditionEngine
Set engine = New cConditionEngine
Dim paramName As String: paramName = "lcfw"
Dim newValue As String: newValue = "M19"
Dim mockBOMs As New Collection
Dim row1 As New cBOMRow, row2 As New cBOMRow, row3 As New cBOMRow
row1.ItemName = "径向高压接头"
row1.Condition = "lcfw=M12"
mockBOMs.Add row1
row2.ItemName = "径向高压接头"
row2.Condition = "lcfw=M13"
mockBOMs.Add row2
row3.ItemName = "弹簧管"
row3.Condition = "lcfw=M01 AND gclj!=M20"
mockBOMs.Add row3
Dim strategyAppend As IModuleProcessor
Set strategyAppend = New cProcessor_AppendOnly
strategyAppend.ProcessSpec mockBOMs, "径向高压接头", paramName, newValue, engine
AssertEqual "追加策略_变种1被更新", "lcfw=M12 OR lcfw=M19", row1.Condition
AssertEqual "追加策略_变种2被更新", "lcfw=M13 OR lcfw=M19", row2.Condition
AssertEqual "追加策略_不影响其他物料", "lcfw=M01 AND gclj!=M20", row3.Condition
Dim strategyClone As IModuleProcessor
Set strategyClone = New cProcessor_CloneNew
Dim initialCount As Integer
initialCount = mockBOMs.count
strategyClone.ProcessSpec mockBOMs, "弹簧管", paramName, newValue, engine
AssertEqual "克隆策略_集合数量增加", CStr(initialCount + 1), CStr(mockBOMs.count)
AssertEqual "克隆策略_新行条件纯粹准确", "lcfw=M19", mockBOMs(mockBOMs.count).Condition
AssertEqual "克隆策略_新行名称继承", "弹簧管", mockBOMs(mockBOMs.count).ItemName
End Sub
' ==============================================================================
' 新增:端到端流水线集成测试
' 验证 Manager 能否将表数据读取、调用策略并正确写回物理单元格
' ==============================================================================
Private Sub Test_Manager_Pipeline()
Debug.Print ""
Debug.Print "========== 5. 开始测试: 调度中枢集成测试 (Pipeline) =========="
Dim wb As Workbook
Dim wsTemp As Worksheet
Set wb = ThisWorkbook
' 创建沙盒工作表并准备初始数据
Application.DisplayAlerts = False
On Error Resume Next
wb.Worksheets("BOMForge_Test_Pipeline").Delete
On Error GoTo 0
Set wsTemp = wb.Worksheets.Add
wsTemp.Name = "BOMForge_Test_Pipeline"
' 表头及数据
wsTemp.Cells(3, 1).value = "行号"
' 第4行目标物料1
wsTemp.Cells(4, 1).value = 700
wsTemp.Cells(4, 4).value = "径向高压接头" ' ItemName
wsTemp.Cells(4, 6).value = "lcfw=M12" ' Condition
' 第5行目标物料2 (变种)
wsTemp.Cells(5, 1).value = 710
wsTemp.Cells(5, 4).value = "径向高压接头"
wsTemp.Cells(5, 6).value = "lcfw=M13"
' 第6行非目标物料
wsTemp.Cells(6, 1).value = 800
wsTemp.Cells(6, 4).value = "弹簧管"
wsTemp.Cells(6, 6).value = "lcfw=M01"
' ===== 执行调度中枢的追加流水线 =====
mSpecAdditionManager.ExecuteAddition wsTemp, "径向高压接头", "lcfw", "M19", "APPEND"
' 断言 Excel 表格的结果
AssertEqual "集成测试_追加_目标行1已被更新", "lcfw=M12 OR lcfw=M19", wsTemp.Cells(4, 6).value
AssertEqual "集成测试_追加_目标行2已被更新", "lcfw=M13 OR lcfw=M19", wsTemp.Cells(5, 6).value
AssertEqual "集成测试_追加_非目标行保持不变", "lcfw=M01", wsTemp.Cells(6, 6).value
' ===== 执行调度中枢的克隆新增流水线 =====
mSpecAdditionManager.ExecuteAddition wsTemp, "弹簧管", "lcfw", "M19", "CLONE"
' 断言 Excel 表格的结果 (克隆的行应追加在末尾)
AssertEqual "集成测试_克隆_原行保持不变", "lcfw=M01", wsTemp.Cells(6, 6).value
AssertEqual "集成测试_克隆_新增行名称", "弹簧管", wsTemp.Cells(7, 4).value
AssertEqual "集成测试_克隆_新增行条件", "lcfw=M19", wsTemp.Cells(7, 6).value
wsTemp.Delete
Application.DisplayAlerts = True
End Sub
' ==============================================================================
' 内部辅助方法:断言测试结果
' ==============================================================================
Private Sub AssertEqual(testName As String, expected As String, actual As String)
If expected = actual Then
Debug.Print "[PASS] " & testName
passCount = passCount + 1
Else
Debug.Print "[FAIL] " & testName
Debug.Print " 期望结果: " & expected
Debug.Print " 实际结果: " & actual
failCount = failCount + 1
End If
End Sub