- 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>
287 lines
11 KiB
QBasic
287 lines
11 KiB
QBasic
' ==============================================================================
|
||
' 模块名称: 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 |