Files
AutoBOM/VBA_BOMConverter/Modules/M06B_TestRunner.bas
Misaka_Company 093a2d0a3b
All checks were successful
NTFY Notification / notify (push) Successful in 11s
feat: implement BOM auto-extraction system
Add complete BOM auto-extraction system with the following modules:

- M06_ModelParser: Parse product model strings to extract parameters
  (azxs, bkxs, gclj, jycz, lcfw, fjgn)
  - Extracts header part from full model (ignores dial/attachment parts)
  - Splits process connection and material code (G123 -> G12, 3)
  - Supports multiple additional features with comma/dot separators

- M07_BOMMatcher: Match materials in BOM library
  - Exact match, wildcard (empty cell), negative match (!=)
  - Special fjgn contains matching logic
  - Array-based performance optimization for bulk operations

- M08_ComponentProcessor: Handle component material special logic
  - Component inventory check (interface reserved)
  - Sub-component extraction (joint + elastic element)
  - Combination validation rules (1 component OR 1 joint + 1 element)

- M09_BOMExtractor: Main extraction orchestrator
  - Reads input models from worksheet
  - Processes each model and matches all material types
  - Outputs to "BOM提取结果" worksheet
  - Error reporting and non-blocking design

- M06B_TestRunner: Comprehensive unit tests
  - 8 test cases for model parsing
  - 5 test cases for BOM matching
  - 5 test cases for component processing

- M04_Config: Add BOM extraction constants
  - BOM library filename and configuration
  - Input/output column definitions
  - Output column enumeration

- M01_Main: Add RunBOMExtraction entry point

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-12 13:02:14 +08:00

412 lines
15 KiB
QBasic

' ==============================================================================
' 模块: M06B_TestRunner
' 职责: BOM自动提取系统的单元测试
'
' 测试模块:
' - M06_ModelParser: 型号解析测试
' - M07_BOMMatcher: BOM匹配测试
' - M08_ComponentProcessor: 部件处理测试
' - M09_BOMExtractor: 提取流程测试
' ==============================================================================
Option Explicit
Private m_Logger As clsErrorLogger
Private m_FailCount As Long
Private m_PassCount As Long
' ------------------------------------------------------------------------------
' 主入口: 运行所有BOM提取测试
' ------------------------------------------------------------------------------
Public Sub RunBOMExtractionTests()
' 初始化环境
Set m_Logger = New clsErrorLogger
M06_ModelParser.InitModelParser m_Logger
M07_BOMMatcher.InitBOMMatcher m_Logger
M08_ComponentProcessor.InitComponentProcessor m_Logger
m_FailCount = 0
m_PassCount = 0
Debug.Print String(60, "=")
Debug.Print "开始运行BOM自动提取系统测试: " & Now
Debug.Print String(60, "-")
' M06_ModelParser 测试
Debug.Print vbCrLf & "[M06_ModelParser 测试]"
Debug.Print String(60, "-")
Test_MP_01_简单型号解析
Test_MP_02_复杂型号带管道符
Test_MP_03_过程连接与材质分离
Test_MP_04_量程范围提取
Test_MP_05_附加功能提取
Test_MP_06_多个附加功能
Test_MP_07_不完整型号验证
Test_MP_08_空型号处理
' M07_BOMMatcher 测试
Debug.Print vbCrLf & "[M07_BOMMatcher 测试]"
Debug.Print String(60, "-")
Test_BM_01_精确匹配
Test_BM_02_空值通配符匹配
Test_BM_03_否定条件匹配
Test_BM_04_附加功能包含匹配
Test_BM_05_fjgn包含逻辑
' M08_ComponentProcessor 测试
Debug.Print vbCrLf & "[M08_ComponentProcessor 测试]"
Debug.Print String(60, "-")
Test_CP_01_验证仅部件
Test_CP_02_验证接头加弹性元件
Test_CP_03_无效组合缺少弹性元件
Test_CP_04_无效组合重复类型
Test_CP_05_空物料列表验证
' 汇总结果
Debug.Print String(60, "-")
If m_FailCount = 0 Then
Debug.Print "测试结果: ALL PASS! (共 " & m_PassCount & " 个测试点)"
Else
Debug.Print "测试结果: 失败 " & m_FailCount & " 个, 通过 " & m_PassCount & " 个"
End If
Debug.Print String(60, "=")
End Sub
' ==============================================================================
' M06_ModelParser 测试用例
' ==============================================================================
' ------------------------------------------------------------------------------
' 测试用例 MP_01: 简单型号解析
' ------------------------------------------------------------------------------
Private Sub Test_MP_01_简单型号解析()
Dim params As Object
Set params = M06_ModelParser.ParseProductModel("YTHN-100.A0.531.G123.M04.Y3")
Assert_NotNull params, "MP01_Params_Not_Null"
Assert_Equal params.count, 8, "MP01_Params_Count"
Assert_Equal params("xh"), "YTHN", "MP01_xh"
Assert_Equal params("gcwj"), "100", "MP01_gcwj"
Assert_Equal params("azxs"), "A0", "MP01_azxs"
Assert_Equal params("bkxs"), "531", "MP01_bkxs"
Assert_Equal params("gclj"), "G12", "MP01_gclj"
Assert_Equal params("jycz"), "3", "MP01_jycz"
Assert_Equal params("lcfw"), "M04", "MP01_lcfw"
Assert_Equal params("fjgn"), "Y3", "MP01_fjgn"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 MP_02: 复杂型号带管道符
' ------------------------------------------------------------------------------
Private Sub Test_MP_02_复杂型号带管道符()
Dim params As Object
Set params = M06_ModelParser.ParseProductModel("YTHN-100.A0.531.G123.M04.Y3|BP-088.2312.B09.0A3")
Assert_NotNull params, "MP02_Params_Not_Null"
Assert_Equal params("azxs"), "A0", "MP02_azxs"
Assert_Equal params("bkxs"), "531", "MP02_bkxs"
Assert_Equal params("lcfw"), "M04", "MP02_lcfw"
Assert_Equal params("fjgn"), "Y3", "MP02_fjgn"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 MP_03: 过程连接与材质分离
' ------------------------------------------------------------------------------
Private Sub Test_MP_03_过程连接与材质分离()
Dim params As Object
Set params = M06_ModelParser.ParseProductModel("YTHN-100.BZ.531.M201.M09.Y3")
Assert_Equal params("gclj"), "M20", "MP03_gclj"
Assert_Equal params("jycz"), "1", "MP03_jycz"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 MP_04: 量程范围提取
' ------------------------------------------------------------------------------
Private Sub Test_MP_04_量程范围提取()
Dim params1 As Object
Set params1 = M06_ModelParser.ParseProductModel("YTHN-100.A0.531.G123.M06.Y3")
Assert_Equal params1("lcfw"), "M06", "MP04_lcfw_M06"
Dim params2 As Object
Set params2 = M06_ModelParser.ParseProductModel("YTHN-100.A0.531.G123.M16.Y3")
Assert_Equal params2("lcfw"), "M16", "MP04_lcfw_M16"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 MP_05: 附加功能提取
' ------------------------------------------------------------------------------
Private Sub Test_MP_05_附加功能提取()
Dim params As Object
Set params = M06_ModelParser.ParseProductModel("YTHN-100.A0.531.G123.M04.N1.Y3")
Assert_Equal params("fjgn"), "N1,Y3", "MP05_fjgn_N1"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 MP_06: 多个附加功能
' ------------------------------------------------------------------------------
Private Sub Test_MP_06_多个附加功能()
Dim params1 As Object
Set params1 = M06_ModelParser.ParseProductModel("YTHN-100.A0.531.G123.M04.N1,N2.Y3")
Assert_Equal params1("fjgn"), "N1,N2,Y3", "MP06_fjgn_Comma"
Dim params2 As Object
Set params2 = M06_ModelParser.ParseProductModel("YTHN-100.A0.531.G123.M04.N1.N2.Y3")
Assert_Equal params2("fjgn"), "N1,N2,Y3", "MP06_fjgn_Dot"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 MP_07: 不完整型号验证
' ------------------------------------------------------------------------------
Private Sub Test_MP_07_不完整型号验证()
Dim params As Object
Set params = M06_ModelParser.ParseProductModel("YTHN-100.A0")
' 不完整型号仍应返回字典,但字段较少
Assert_NotNull params, "MP07_Params_Not_Null"
Assert_True params.Exists("azxs"), "MP07_Has_azxs"
Assert_False params.Exists("bkxs"), "MP07_No_bkxs"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 MP_08: 空型号处理
' ------------------------------------------------------------------------------
Private Sub Test_MP_08_空型号处理()
Dim params As Object
Set params = M06_ModelParser.ParseProductModel("")
Assert_NotNull params, "MP08_Params_Not_Null"
Assert_Equal params.count, 0, "MP08_Empty_Count"
End Sub
' ==============================================================================
' M07_BOMMatcher 测试用例
' ==============================================================================
' ------------------------------------------------------------------------------
' 测试用例 BM_01: 精确匹配
' ------------------------------------------------------------------------------
Private Sub Test_BM_01_精确匹配()
Dim cellValue As String
cellValue = "A0"
Dim paramValue As String
paramValue = "A0"
Dim result As Boolean
result = M07_BOMMatcher.EvaluateCellCondition(cellValue, paramValue, "azxs")
Assert_Equal result, True, "BM01_Exact_Match"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 BM_02: 空值通配符匹配
' ------------------------------------------------------------------------------
Private Sub Test_BM_02_空值通配符匹配()
Dim cellValue As Variant
cellValue = ""
Dim paramValue As String
paramValue = "A0"
Dim result As Boolean
result = M07_BOMMatcher.EvaluateCellCondition(cellValue, paramValue, "azxs")
Assert_Equal result, True, "BM02_Wildcard_Match"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 BM_03: 否定条件匹配
' ------------------------------------------------------------------------------
Private Sub Test_BM_03_否定条件匹配()
Dim cellValue As String
cellValue = "!=A0"
Dim paramValue As String
paramValue = "B0"
Dim result As Boolean
result = M07_BOMMatcher.EvaluateCellCondition(cellValue, paramValue, "azxs")
Assert_Equal result, True, "BM03_Not_Equal_Match"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 BM_04: 附加功能包含匹配
' ------------------------------------------------------------------------------
Private Sub Test_BM_04_附加功能包含匹配()
Dim cellValue As String
cellValue = "N1"
Dim fjgnList As String
fjgnList = "N1,N2,Y3"
Dim result As Boolean
result = M07_BOMMatcher.CheckFjgnMatch(cellValue, fjgnList)
Assert_Equal result, True, "BM04_Fjgn_Contains_N1"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 BM_05: fjgn包含逻辑
' ------------------------------------------------------------------------------
Private Sub Test_BM_05_fjgn包含逻辑()
' 测试包含
Assert_True M07_BOMMatcher.CheckFjgnMatch("N3", "N3,N2"), "BM05_Contains_N3"
Assert_True M07_BOMMatcher.CheckFjgnMatch("N2", "N3,N2"), "BM05_Contains_N2"
' 测试不包含
Assert_False M07_BOMMatcher.CheckFjgnMatch("N1", "N3,N2"), "BM05_Not_Contains_N1"
' 测试空列表
Assert_False M07_BOMMatcher.CheckFjgnMatch("N1", ""), "BM05_Empty_List"
End Sub
' ==============================================================================
' M08_ComponentProcessor 测试用例
' ==============================================================================
' ------------------------------------------------------------------------------
' 测试用例 CP_01: 验证仅部件
' ------------------------------------------------------------------------------
Private Sub Test_CP_01_验证仅部件()
Dim materials As Collection
Set materials = New Collection
Dim mat1 As Object
Set mat1 = CreateMaterial("部件", "部件A", "C001", 1)
materials.Add mat1
Dim validation As Object
Set validation = M08_ComponentProcessor.ValidateComponentCombination(materials)
Assert_Equal validation("valid"), True, "CP01_Valid_Component"
Assert_True InStr(validation("message"), "1个部件") > 0, "CP01_Message_Content"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 CP_02: 验证接头加弹性元件
' ------------------------------------------------------------------------------
Private Sub Test_CP_02_验证接头加弹性元件()
Dim materials As Collection
Set materials = New Collection
Dim mat1 As Object
Set mat1 = CreateMaterial("接头", "接头A", "J001", 1)
materials.Add mat1
Dim mat2 As Object
Set mat2 = CreateMaterial("弹性元件", "元件A", "E001", 1)
materials.Add mat2
Dim validation As Object
Set validation = M08_ComponentProcessor.ValidateComponentCombination(materials)
Assert_Equal validation("valid"), True, "CP02_Valid_Joint_Element"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 CP_03: 无效组合缺少弹性元件
' ------------------------------------------------------------------------------
Private Sub Test_CP_03_无效组合缺少弹性元件()
Dim materials As Collection
Set materials = New Collection
Dim mat1 As Object
Set mat1 = CreateMaterial("接头", "接头A", "J001", 1)
materials.Add mat1
Dim validation As Object
Set validation = M08_ComponentProcessor.ValidateComponentCombination(materials)
Assert_Equal validation("valid"), False, "CP03_Invalid_No_Element"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 CP_04: 无效组合重复类型
' ------------------------------------------------------------------------------
Private Sub Test_CP_04_无效组合重复类型()
Dim materials As Collection
Set materials = New Collection
Dim mat1 As Object
Set mat1 = CreateMaterial("部件", "部件A", "C001", 1)
materials.Add mat1
Dim mat2 As Object
Set mat2 = CreateMaterial("接头", "接头A", "J001", 1)
materials.Add mat2
Dim validation As Object
Set validation = M08_ComponentProcessor.ValidateComponentCombination(materials)
Assert_Equal validation("valid"), False, "CP04_Invalid_Both"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 CP_05: 空物料列表验证
' ------------------------------------------------------------------------------
Private Sub Test_CP_05_空物料列表验证()
Dim materials As Collection
Set materials = New Collection
Dim validation As Object
Set validation = M08_ComponentProcessor.ValidateComponentCombination(materials)
Assert_Equal validation("valid"), False, "CP05_Empty_List"
End Sub
' ==============================================================================
' 辅助函数
' ==============================================================================
' 辅助断言函数
Private Sub Assert_Equal(actual As Variant, expected As Variant, testName As String)
If CStr(actual) = CStr(expected) Then
m_PassCount = m_PassCount + 1
Else
Debug.Print " [FAIL] " & testName & " | Expected: " & expected & ", Actual: " & actual
m_FailCount = m_FailCount + 1
End If
End Sub
Private Sub Assert_True(actual As Boolean, testName As String)
If actual Then
m_PassCount = m_PassCount + 1
Else
Debug.Print " [FAIL] " & testName & " | Expected: True, Actual: False"
m_FailCount = m_FailCount + 1
End If
End Sub
Private Sub Assert_False(actual As Boolean, testName As String)
If Not actual Then
m_PassCount = m_PassCount + 1
Else
Debug.Print " [FAIL] " & testName & " | Expected: False, Actual: True"
m_FailCount = m_FailCount + 1
End If
End Sub
Private Sub Assert_NotNull(obj As Object, testName As String)
If Not obj Is Nothing Then
m_PassCount = m_PassCount + 1
Else
Debug.Print " [FAIL] " & testName & " | Object is Nothing"
m_FailCount = m_FailCount + 1
End If
End Sub
' 创建测试物料对象
Private Function CreateMaterial( _
ByVal matType As String, _
ByVal matName As String, _
ByVal matCode As String, _
ByVal matQty As Long _
) As Object
Dim mat As Object
Set mat = CreateObject("Scripting.Dictionary")
mat("materialType") = matType
mat("materialName") = matName
mat("materialCode") = matCode
mat("materialQty") = matQty
mat("remarks") = ""
Set CreateMaterial = mat
End Function