' ============================================================================== ' 模块名称: 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 allBOMs As New Collection Dim targetBOMs As New Collection Dim row1 As New cBOMRow, row2 As New cBOMRow, row3 As New cBOMRow row1.ItemName = "径向高压接头": row1.Condition = "lcfw=M12": allBOMs.Add row1 row2.ItemName = "径向高压接头": row2.Condition = "lcfw=M13": allBOMs.Add row2 row3.ItemName = "弹簧管": row3.Condition = "lcfw=M01 AND gclj!=M20": allBOMs.Add row3 ' 【核心逻辑】模拟 UI 层仅将用户勾选的具体行 (比如 row1) 加入 targetBOMs 集合 targetBOMs.Add row1 ' 测试 1: 追加策略 (AppendOnly) Dim strategyAppend As IModuleProcessor Set strategyAppend = New cProcessor_AppendOnly strategyAppend.ProcessSpec allBOMs, targetBOMs, paramName, newValue, engine AssertEqual "追加策略_选中的变种1被更新", "lcfw=M12 OR lcfw=M19", row1.Condition AssertEqual "追加策略_未选中的变种2保持不变", "lcfw=M13", row2.Condition AssertEqual "追加策略_不影响其他物料", "lcfw=M01 AND gclj!=M20", row3.Condition ' 测试 2: 克隆新增策略 (CloneNew) Dim strategyClone As IModuleProcessor Set strategyClone = New cProcessor_CloneNew Dim initialCount As Integer: initialCount = allBOMs.count ' 模拟 UI 选择弹簧管作为克隆母版 Set targetBOMs = New Collection targetBOMs.Add row3 strategyClone.ProcessSpec allBOMs, targetBOMs, paramName, newValue, engine AssertEqual "克隆策略_总库数量增加", CStr(initialCount + 1), CStr(allBOMs.count) AssertEqual "克隆策略_新行条件纯粹准确", "lcfw=M19", allBOMs(allBOMs.count).Condition End Sub ' ============================================================================== ' 新增:端到端流水线集成测试 ' ============================================================================== 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 = "行号" wsTemp.Cells(4, 1).value = 700: wsTemp.Cells(4, 4).value = "径向高压接头": wsTemp.Cells(4, 6).value = "lcfw=M12" wsTemp.Cells(5, 1).value = 710: wsTemp.Cells(5, 4).value = "径向高压接头": wsTemp.Cells(5, 6).value = "lcfw=M13" wsTemp.Cells(6, 1).value = 800: wsTemp.Cells(6, 4).value = "弹簧管": wsTemp.Cells(6, 6).value = "lcfw=M01" ' 模拟 UI 打开时加载数据 Dim globalBOMs As Collection Set globalBOMs = mSpecAdditionManager.LoadData(wsTemp) ' 模拟 UI 细粒度勾选:只选中了第5行 (即集合中的第2个对象) Dim uiSelectedBOMs As New Collection uiSelectedBOMs.Add globalBOMs(2) ' 执行调度中枢的追加流水线 mSpecAdditionManager.ExecutePipeline wsTemp, globalBOMs, uiSelectedBOMs, "lcfw", "M19", "APPEND" AssertEqual "流水线_追加_目标行1未选中(不变)", "lcfw=M12", 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 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