' ============================================================================== ' 模块: M99_TestRunner ' 职责: 单元测试,验证 M03_Logic 的核心算法 ' 依赖: M03_Logic, clsErrorLogger (无需引用 Scripting Runtime) ' ============================================================================== Option Explicit Private m_Logger As clsErrorLogger Private m_FailCount As Long Private m_PassCount As Long ' ------------------------------------------------------------------------------ ' 主入口: 运行所有测试 ' ------------------------------------------------------------------------------ Public Sub RunAllTests() ' 初始化环境 Set m_Logger = New clsErrorLogger M03_Logic.InitLogic m_Logger m_FailCount = 0 m_PassCount = 0 Debug.Print String(50, "=") Debug.Print "开始运行单元测试: " & Now Debug.Print String(50, "-") ' 执行测试用例 Test_01_SimpleAtom Test_02_SimpleAND Test_03_SimpleOR Test_04_CartesianProduct ' 核心:测试 (A OR B) AND C Test_05_InequalityMerge ' 核心:测试 !=A AND !=B Test_06_LogicConflict ' 核心:测试 A=1 AND A=2 Test_07_ComplexNested ' 核心:多层括号 ' 汇总结果 Debug.Print String(50, "-") If m_FailCount = 0 Then Debug.Print "测试结果: ALL PASS! (共 " & m_PassCount & " 个测试点)" Else Debug.Print "测试结果: 失败 " & m_FailCount & " 个, 通过 " & m_PassCount & " 个" End If Debug.Print String(50, "=") End Sub ' ------------------------------------------------------------------------------ ' 测试用例 01: 简单赋值 ' 输入: gclj=M20 ' 期望: 1行数据, gclj字段为M20 ' ------------------------------------------------------------------------------ Private Sub Test_01_SimpleAtom() Dim col As Collection Dim row As Object ' Dictionary Set col = M03_Logic.ParseRule("gclj=M20", 1) Assert_NotNull col, "T01_Col_Not_Null" Assert_Equal col.count, 1, "T01_Count" Set row = col(1) Assert_Equal row("gclj"), "M20", "T01_Value_Check" End Sub ' ------------------------------------------------------------------------------ ' 测试用例 02: AND 逻辑 (属性合并) ' 输入: gclj=M20 AND jycz=1 ' 期望: 1行数据, 包含两个字段 ' ------------------------------------------------------------------------------ Private Sub Test_02_SimpleAND() Dim col As Collection Dim row As Object Set col = M03_Logic.ParseRule("gclj=M20 AND jycz=1", 2) Assert_Equal col.count, 1, "T02_Count" Set row = col(1) Assert_Equal row("gclj"), "M20", "T02_Key1" Assert_Equal row("jycz"), "1", "T02_Key2" End Sub ' ------------------------------------------------------------------------------ ' 测试用例 03: OR 逻辑 (记录分裂) ' 输入: azxs=A0 OR azxs=A1 ' 期望: 2行数据 ' ------------------------------------------------------------------------------ Private Sub Test_03_SimpleOR() Dim col As Collection Set col = M03_Logic.ParseRule("azxs=A0 OR azxs=A1", 3) Assert_Equal col.count, 2, "T03_Count" End Sub ' ------------------------------------------------------------------------------ ' 测试用例 04: 笛卡尔积 (AND 连接 OR) ' 输入: gclj=M20 AND (azxs=A0 OR azxs=A1) ' 期望: 2行数据。行1(gclj=M20, azxs=A0), 行2(gclj=M20, azxs=A1) ' ------------------------------------------------------------------------------ Private Sub Test_04_CartesianProduct() Dim col As Collection Dim r1 As Object, r2 As Object Set col = M03_Logic.ParseRule("gclj=M20 AND (azxs=A0 OR azxs=A1)", 4) Assert_Equal col.count, 2, "T04_Count" Set r1 = col(1) Set r2 = col(2) ' 验证公共部分 Assert_Equal r1("gclj"), "M20", "T04_Row1_Common" Assert_Equal r2("gclj"), "M20", "T04_Row2_Common" ' 验证差异部分 Dim hasA0 As Boolean, hasA1 As Boolean If r1("azxs") = "A0" Or r2("azxs") = "A0" Then hasA0 = True If r1("azxs") = "A1" Or r2("azxs") = "A1" Then hasA1 = True Assert_Equal hasA0, True, "T04_Has_A0" Assert_Equal hasA1, True, "T04_Has_A1" End Sub ' ------------------------------------------------------------------------------ ' 测试用例 05: 不等于逻辑合并 ' 输入: gclj!=M20 AND gclj!=M30 ' 期望: 1行数据, gclj字段为 "!=M20,!=M30" ' ------------------------------------------------------------------------------ Private Sub Test_05_InequalityMerge() Dim col As Collection Dim row As Object Set col = M03_Logic.ParseRule("gclj!=M20 AND gclj!=M30", 5) Assert_Equal col.count, 1, "T05_Count" Set row = col(1) Assert_Equal row("gclj"), "!=M20,!=M30", "T05_Value_Merge" End Sub ' ------------------------------------------------------------------------------ ' 测试用例 06: 逻辑冲突检测 (修正版) ' 输入: gclj=M20 AND gclj=M30 ' 期望: 返回 Nothing 或 空集合,且 Logger 中有记录 ' ------------------------------------------------------------------------------ Private Sub Test_06_LogicConflict() Dim col As Collection ' 重置 Logger Set m_Logger = New clsErrorLogger M03_Logic.InitLogic m_Logger ' 此时 ParseRule 内部会捕捉冲突 Set col = M03_Logic.ParseRule("gclj=M20 AND gclj=M30", 6) ' 检查结果: 应该是 Nothing 或者 Count=0 Dim isInvalid As Boolean If col Is Nothing Then isInvalid = True Else If col.count = 0 Then isInvalid = True Else isInvalid = False End If Assert_Equal isInvalid, True, "T06_Should_Return_Empty_Or_Nothing" Assert_Equal m_Logger.HasErrors, True, "T06_Should_Log_Error" End Sub ' ------------------------------------------------------------------------------ ' 测试用例 07: 复杂嵌套 ' 输入: A=1 AND (B=1 OR (B=2 AND C=3)) ' 期望: 2行 ' Row 1: A=1, B=1 ' Row 2: A=1, B=2, C=3 ' ------------------------------------------------------------------------------ Private Sub Test_07_ComplexNested() Dim col As Collection Set col = M03_Logic.ParseRule("A=1 AND (B=1 OR (B=2 AND C=3))", 7) Assert_Equal col.count, 2, "T07_Count" Dim count2 As Long, count3 As Long Dim i As Long Dim r As Object For i = 1 To col.count Set r = col(i) If r.count = 2 Then count2 = count2 + 1 If r.count = 3 Then count3 = count3 + 1 Next i Assert_Equal count2, 1, "T07_Row_With_2_Keys" Assert_Equal count3, 1, "T07_Row_With_3_Keys" End Sub ' ============================================================================== ' 辅助断言函数 ' ============================================================================== Private Sub Assert_Equal(actual As Variant, expected As Variant, testName As String) If CStr(actual) = CStr(expected) Then ' Debug.Print " [PASS] " & testName 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_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