Imports System.Text Imports System.Threading Imports UTS_Core.UTSModule.DbConnect Imports UTS_Core.UTSModule.Station Imports UTS_Core.UTSModule.Station.StationTestPlan Imports UTS_Core.UTSModule.Test.Command Imports UTS_Core.UTSModule.Test.StatusMonitor Imports UTS_Core.UTSModule.Test.StatusMonitor.TestStatusMonitor Namespace UTSModule.Test Public Class TestNodeCompletedEventArgs Inherits EventArgs Sub New(node As RowNode, testReturn As TestCommandReturn) Me.Node = node Me.TestReturn = testReturn End Sub Public Property Node() As RowNode Public Property TestReturn() As TestCommandReturn End Class Public Class TestNodeResultChangedEventArgs Inherits EventArgs Sub New(node As RowNode, testReturn As TestCommandReturn) Me.Node = node Me.TestReturn = testReturn End Sub Public Property Node() As RowNode Public Property TestReturn() As TestCommandReturn End Class Public Class TestNodeChangedEventArgs Inherits EventArgs Sub New(node As RowNode) Me.Node = node End Sub Public Property Node() As RowNode End Class Public Class TestProgressChangedEventArgs Inherits EventArgs Sub New(process As Double) Percent = process End Sub ''' ''' 当前百分比 ''' ''' Public Property Percent As Double End Class Public Class TestCountChangedEventArgs Inherits EventArgs Sub New(pass As Integer, fail As Integer) PassCount = pass FailCount = fail End Sub Public Property PassCount As Integer Public Property FailCount As Integer Public ReadOnly Property Count() As Integer Get Return PassCount + FailCount End Get End Property End Class Public Class TestTimeEventArgs Inherits EventArgs Sub New(span As TimeSpan) TimeElapsed = span End Sub Public Property TimeElapsed() As TimeSpan End Class Public Class TestPauseEventArgs Sub New(node As RowNode) Me.Node = node End Sub Public Property Node() As RowNode End Class Public Class TestFailEventArgs Sub New(node As RowNode) Me.Node = node End Sub Public Property Node() As RowNode End Class Public Class TestEndEventArgs Inherits EventArgs Sub New(result As TestResult) TestResult = result End Sub Public Property TestResult() As TestResult End Class Public Class UtsTester '''测试开始事件 Public Event TestStart(sender As Object, e As EventArgs) '''测试暂停事件 Public Event TestPause(sender As Object, e As TestPauseEventArgs) '''测试成功事件 Public Event TestPass(sender As Object, e As EventArgs) '''测试失败事件 Public Event TestFail(sender As Object, e As TestFailEventArgs) '''测试结束事件 Public Event TestEnd(sender As Object, e As TestEndEventArgs) '''测试状态变更事件 Public Event TestStatusChanged(sender As Object, e As TestStatusChangedEventArgs) '''测试计数变更事件 Public Event TestCountChanged(sender As Object, e As TestCountChangedEventArgs) '''测试节点变更事件 Public Event TestNodeChanged(sender As Object, e As TestNodeChangedEventArgs) '''测试节点完成事件 Public Event TestNodeCompleted(sender As Object, e As TestNodeCompletedEventArgs) '''测试节点结果变化事件 Public Event TestNodeResultChanged(sender As Object, e As TestNodeResultChangedEventArgs) '''测试时间变更事件 Public Event TestTimeChanged(sender As Object, e As TestTimeEventArgs) '重试次数变更,加node Public Event TestProgressChanged(sender As Object, e As TestProgressChangedEventArgs) Public Event RetryProgressChanged(sender As Object, e As TestProgressChangedEventArgs) ''' 当前测试节点 Private _testNode As RowNode ''' 当前测试固定模块 Private _testFixedModule As FixedModuleEnum = FixedModuleEnum.None ''' 测试耗时计时器 Private ReadOnly _testWatch As New Stopwatch ''' 单步执行耗时计时器 Private ReadOnly _stepWatch As New Stopwatch ''' 程序运行后,测试通过总数 Private _testPassCount As Integer ''' 程序运行后,测试失败总数 Private _testFailCount As Integer ''' 是否已执行设置模块 Private _setupModuleExecuted As Boolean ''' 是否处于调试断点 Private _nodePaused As Boolean ''' 是否退出调试断点 Private _exitPaused As Boolean ''' 是否下一节点调试断点 Private _nextPause As Boolean ''' 内置模块入口集合 Private ReadOnly _testModules As Dictionary(Of String, RowNode) ''' 自定义模块下函数入口集合 Private ReadOnly _customModules As Dictionary(Of String, RowNode) ''' 测试结果内容 Private ReadOnly _testResult As TestResult ''' 是否退出测试 Private _exitTest As Boolean ''' 测试时间线程 Private ReadOnly _timeThread As Thread ''' 测试过程中,产生的变量存储 Private ReadOnly _userVar As New Dictionary(Of String, String) ''' 测试过程中,全局变量存储 Private ReadOnly _globalVar As New Dictionary(Of String, String) ''' 测试过程中,使用的测试站位 Private _processStation As ProcessStation ''' 测试器句柄,全局唯一 Private Shared _tester As UtsTester ''' 初始化测试器线程锁 Private Shared ReadOnly InitLock As New Object() Private _startTestIndex As Integer Private _endTestIndex As Integer Private _testCount As Integer ''' ''' 创建测试器,若测试器已经创建则返回句柄 ''' ''' Public Shared Function CreateTester() As UtsTester If _tester Is Nothing Then SyncLock InitLock Thread.MemoryBarrier() If _tester Is Nothing Then _tester = New UtsTester End If End SyncLock End If Return _tester End Function Private Sub New() _testResult = New TestResult() _testResult.AppName = Windows.Forms.Application.ProductName & Windows.Forms.Application.ProductVersion _testResult.ServiceID = CInt(UtsRegistry.DataServiceIndex) _testModules = New Dictionary(Of String, RowNode)() _customModules = New Dictionary(Of String, RowNode) _testWatch = New Stopwatch() _stepWatch = New Stopwatch() _exitTest = False TestStatus = TestStatusEnum.WaitForTest TestFailMode = TestFailModeEnum.StepFail _timeThread = New Thread(AddressOf TestTime) _timeThread.IsBackground = True _timeThread.Start() End Sub Public Property DebugMode() As Boolean ''' 测试状态 Public Property TestStatus As TestStatusEnum Get Return TestStatusMonitor.TestStatus End Get Set(value As TestStatusEnum) TestStatusMonitor.TestStatus = value End Set End Property Public ReadOnly Property TestResult() As TestResult Get Return _testResult End Get End Property Public ReadOnly Property TestFiexdModule As FixedModuleEnum Get Return _testFixedModule End Get End Property ''' ''' 判定测试失败的模式 ''' ''' Public Property TestFailMode() As TestFailModeEnum ''' ''' 测试时,重新执行Setup模块 ''' Public Sub RerunSetupModule() _setupModuleExecuted = False End Sub Public Property ProcessStation() As ProcessStation Get Return _processStation End Get Set(value As ProcessStation) '测试站位修改 _processStation = value _setupModuleExecuted = False UpdateTestModule(CType(_processStation.Packet.StationPlan, StationTestPlan).RowNodes) _testResult.TestPlan = _processStation.Packet.FileName End Set End Property ''' ''' 获取指定名称的模块节点 ''' ''' ''' Public Function GetModule(name As String) As RowNode If _customModules.ContainsKey($"{name}") = False Then Return Nothing Return _customModules($"{name}") End Function Public Function GetFixedModule(name As FixedModuleEnum) As RowNode If _testModules.ContainsKey($"{name}") = False Then Return Nothing Return _testModules($"{name}") End Function Private Sub TestTime() While _testWatch IsNot Nothing If _testWatch.IsRunning Then RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) End If Thread.Sleep(100) End While End Sub ''' ''' 开始测试,此函数为正式测试调用 ''' Public Sub StartTest() _userVar.Clear() '清空全局变量 _testResult.ResetTestResult() '重置测试结果 DebugMode = False _exitTest = False RaiseEvent TestStart(Me, New EventArgs()) '重置测试进度 RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(0)) '测试主代码 TestFunction() '进度修改百分百 RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(100)) '测试完成 RaiseEvent TestEnd(Me, New TestEndEventArgs(_testResult)) End Sub ''' ''' 开始调试测试,此函数为正式测试调用 ''' Public Sub StartDebugTest() DebugMode = True _exitTest = False _userVar.Clear() '清空全局变量 _testResult.ResetTestResult() '重置测试结果 RaiseEvent TestStart(Me, New EventArgs()) '重置测试进度 RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(0)) '测试主代码 TestFunction() '进度修改百分百 RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(100)) '测试完成 RaiseEvent TestEnd(Me, New TestEndEventArgs(_testResult)) End Sub ''' ''' 流程修改后保存,更新模块索引 ''' ''' ''' Public Sub StationEditStatusChanged(sender As Object, e As StationEditStatusChangedEventArgs) If e.Status = StationEditStatusMonitor.StationEditStatusEnum.Saved Then '更新测试流程所有函数入口 'UpdateTestModule(ProcessStation.Packet.StationPlan.HeadNode.RowNodes) UpdateTestModule(CType(_processStation.Packet.StationPlan, StationTestPlan).RowNodes) '测试将重新执行设置模块 _setupModuleExecuted = False End If End Sub ''' ''' 更新测试模块入库 ''' Public Sub UpdateTestModule(rowNodes As RowNodeCollection) _testModules.Clear() GetTestModule(_testModules, rowNodes) End Sub ''' ''' 获取执行行节点集合中测试模块入口,并存储至内部模块入口集合 ''' ''' 存储测试模块入口集合 ''' 行节点集合 Private Sub GetTestModule(modules As Dictionary(Of String, RowNode), nodes As RowNodeCollection) For Each node As RowNode In nodes If node.RowType = RowNode.RowTypeEnum.FixedModule OrElse node.RowType = RowNode.RowTypeEnum.Module Then If String.IsNullOrWhiteSpace(node.Label) Then Continue For If modules.ContainsKey(node.Label) Then Continue For modules.Add(node.Label, node) End If If node.Label = $"{FixedModuleEnum.Custom}" Then _customModules.Clear() GetTestModule(_customModules, node.RowNodes) End If 'If node.RowNodes.Count > 0 Then ' GetTestModule(modules, node.RowNodes) 'End If Next End Sub Public Function GetCustomModuleName() As String() Return _customModules.Keys.ToArray() End Function ''' ''' 执行内置模块函数 ''' ''' ''' Public Function ExecuteFixedModule(moduleName As FixedModuleEnum) As TestCommandReturn Dim result As TestCommandReturn _testFixedModule = moduleName If _testModules.ContainsKey(moduleName.ToString()) Then Dim node As RowNode = _testModules(moduleName.ToString()) node.IsRetry = False '顶级节点最初重试状态为false result = ExecutePlan(node, Nothing) Else result = New TestCommandReturn() result.ExecuteResult = False result.ExecuteResultTipString = $"未搜索到[{moduleName}]模块" End If _testFixedModule = FixedModuleEnum.None '重置测试固定模块 Return result End Function #Region "获取特殊情况返回" ''' ''' 获取用户退出测试的执行返回结果 ''' ''' Private Function GetExitTestReturn() As TestCommandReturn Dim result As New TestCommandReturn result.ExecuteResult = False result.ExecuteResultTipString = $"用户结束测试过程" Return result End Function ''' ''' 获取不运行的节点的执行返回结果 ''' ''' Private Function GetNotActionNodeResult() As TestCommandReturn Dim result As New TestCommandReturn result.ExecuteResult = True result.ExecuteResultTipString = $"无需执行的测试节点" Return result End Function ''' ''' 获取未知的行节点类型的执行返回结果 ''' ''' 当前行节点 ''' Private Function GetUnknownTypeNodeResult(node As RowNode) As TestCommandReturn Dim result As New TestCommandReturn result.ExecuteResult = False result.ExecuteResultTipString = $"未知的节点类型:{node.RowType}" Return result End Function Private Function GetNullControlTypeResult() As TestCommandReturn Dim result As New TestCommandReturn result.ExecuteResult = True result.ExecuteResultTipString = $"无效的控制类型,默认跳过执行" Return result End Function Private Function GetUnknownControlTypeResult(node As RowNode) As TestCommandReturn Dim result As New TestCommandReturn result.ExecuteResult = False result.ExecuteResultTipString = $"未知的控制类型:{node.ControlType}" Return result End Function #End Region #Region "执行流程" Public Function ExecutePlan(node As RowNode, Optional localVariable As Dictionary(Of String, String) = Nothing) As TestCommandReturn Dim result As TestCommandReturn If _exitTest Then Return GetExitTestReturn() If node.Action = False Then Return GetNotActionNodeResult() If TestStatus = TestStatusEnum.Testing Then _testNode = node '节点测试开始 RaiseEvent TestNodeChanged(Me, New TestNodeChangedEventArgs(node)) '调试模式检测断点 If DebugMode Then '断点调试 While node.Pause OrElse _nextPause '已进入暂停状态 If _nodePaused = False Then _nodePaused = True RaiseEvent TestPause(Me, New TestPauseEventArgs(node)) End If If _exitPaused Then Exit While If _exitTest Then Return GetExitTestReturn() Thread.Sleep(100) End While _nodePaused = False _exitPaused = False End If '获取测试结果 Select Case node.RowType Case RowNode.RowTypeEnum.FixedModule, RowNode.RowTypeEnum.Module result = ExecuteModuleNode(node, localVariable) Case RowNode.RowTypeEnum.Control result = ExecuteControlNode(node, localVariable) Case RowNode.RowTypeEnum.Flow result = ExecuteFlowNode(node, localVariable) Case Else result = GetUnknownTypeNodeResult(node) End Select node.TestReturn = result '节点测试完成 RaiseEvent TestNodeCompleted(Me, New TestNodeCompletedEventArgs(node, result)) Return result End Function ''' ''' 执行模块流程 ''' ''' ''' Public Function ExecuteModuleNode(node As RowNode, Optional localVariable As Dictionary(Of String, String) = Nothing) As TestCommandReturn Dim result As New TestCommandReturn For retry As Integer = 0 To node.Retry '最大执行总数为:1+重试次数 '退出执行检测 If _exitTest Then Return GetExitTestReturn() '更新重试进度 Dim p As Double = CDbl(IIf(retry = 0, 100, (node.Retry - retry) / node.Retry * 100)) RaiseEvent RetryProgressChanged(Me, New TestProgressChangedEventArgs(p)) '判断节点是否为重试状态 If retry > 0 Then node.IsRetry = True If localVariable IsNot Nothing AndAlso localVariable.ContainsKey("CH") Then Console.WriteLine($"CH:{localVariable("CH")} Label:{node.Label} Desc:{node.Description} RetryCount:{retry} IsRetry:{node.IsRetry}") End If '重置模块测试结果 result.ExecuteResult = True '测试子节点 For Each rowNode As RowNode In node.RowNodes If _exitTest Then Return GetExitTestReturn() '退出执行检测 rowNode.IsRetry = node.IsRetry '将父节点的重试状态赋予子节点 If ExecutePlan(rowNode, localVariable).ExecuteResult = False Then result.ExecuteResult = False '节点测试失败则认为模块失败 If result.ExecuteResult Then Continue For '执行成功则执行下一流程 If TestFailMode = TestFailModeEnum.StepFail Then Exit For '单步失败模式下退出测试,不再执行 Next '模块测试成功则退出重试 If result.ExecuteResult Then Exit For Thread.Sleep(node.RetryInterval) '执行失败,休眠重试间隔 Next node.IsRetry = True 'todo:临时解决call命令调用函数时多层级模块 节点变更与节点完成的非唯一节点bug Return result End Function ''' ''' 执行控制流程 ''' ''' ''' 测试结果 Private Function ExecuteControlNode(node As RowNode, Optional localVariable As Dictionary(Of String, String) = Nothing) As TestCommandReturn If _exitTest Then Return GetExitTestReturn() '退出测试 If String.IsNullOrWhiteSpace(node.ControlType) Then Return GetNullControlTypeResult() Dim result As New TestCommandReturn Select Case node.ControlType Case "If" result.ExecuteResult = ExecuteIfControlNode(node).ExecuteResult Case "While" result.ExecuteResult = ExecuteWhileControlNode(node).ExecuteResult Case Else result = GetUnknownControlTypeResult(node) End Select Return result End Function Private Function ExecuteIfControlNode(node As RowNode, Optional localVariable As Dictionary(Of String, String) = Nothing) As TestCommandReturn '无子节点,默认通过 '判断成功,无Then节点,默认成功 '判断失败,无Else节点默认成功 '控制流程只有子节点失败才算失败,判断条件失败,忽略失败 Dim result As New TestCommandReturn Dim tmpResult As TestCommandReturn 'if分支的判断结果 tmpResult = ExecuteControlCondition(node, localVariable) '获取If判断条件的结果 For Each rowNode As RowNode In node.RowNodes If tmpResult.ExecuteResult Then If rowNode.ControlType = "Then" Then result = ExecuteModuleNode(rowNode, localVariable) Exit For End If Else Select Case rowNode.ControlType Case "ElseIf" '执行判断条件命令成功则认为匹配成功,返回执行子节点的结果 tmpResult = ExecuteControlCondition(rowNode, localVariable) If tmpResult.ExecuteResult Then '判断条件成立 result = ExecuteModuleNode(rowNode, localVariable) Exit For End If Case "Else" result = ExecuteModuleNode(rowNode, localVariable) Exit For End Select End If Next Return result End Function Private Function ExecuteWhileControlNode(node As RowNode, Optional localVariable As Dictionary(Of String, String) = Nothing) As TestCommandReturn Dim result As TestCommandReturn result = ExecuteControlCondition(node, localVariable) '执行while节点判断条件 If result.ExecuteResult Then result = ExecuteModuleNode(node, localVariable) '执行While内部流程 '内部循环节点成功执行成功则递归调用本身,直至while条件不成立 If result.ExecuteResult Then result = ExecuteWhileControlNode(node) Else '执行判断条件失败则退出While,并认为执行成功 result.ExecuteResult = True End If Return result End Function ''' ''' 执行控制结构的条件部分 ''' ''' ''' Private Function ExecuteControlCondition(node As RowNode, Optional localVariable As Dictionary(Of String, String) = Nothing) As TestCommandReturn Dim result As New TestCommandReturn If String.IsNullOrWhiteSpace(node.Command) Then Return result Dim cmd As New TestCommand(node) '获取执行参数 ReplaceValue(cmd) '执行前变量替换 Dim executor As TestCommandExecutor = TestCommandManger.CreateExecutor(cmd) '创建执行器 result = executor.Execute() '获取执行返回 If String.IsNullOrWhiteSpace(node.RecordName) = False Then '处理需要入库的数据 Dim filedName As String = ReplaceString(node.RecordName, localVariable) '替换记录名称中变量 If _userVar.ContainsKey(filedName) Then _userVar(filedName) = result.RecordValue Else _userVar.Add(filedName, result.RecordValue) End If If node.SaveToDb Then '添加内容至数据库字段中 _testResult.AddCustomRecord(filedName, result.RecordValue) End If End If Return result End Function ''' ''' 执行类型为普通流程的行节点 ''' ''' ''' ''' Public Function ExecuteFlowNode(node As RowNode, Optional localVariable As Dictionary(Of String, String) = Nothing) As TestCommandReturn Dim result As New TestCommandReturn If String.IsNullOrWhiteSpace(node.Command) Then Return result Dim watch As Stopwatch = Stopwatch.StartNew() '开启单步计时 Dim cmd As New TestCommand(node) '获取执行参数 ReplaceValue(cmd, localVariable) '执行前变量替换 Dim executor As TestCommandExecutor = TestCommandManger.CreateExecutor(cmd) '创建执行器 node.Desc4Record = ReplaceString(node.Description, localVariable) '替换记录名称中变量 '最大执行总数为:1+重试次数 For retry As Integer = 0 To node.Retry If _exitTest Then Exit For '更新重试进度 Dim p As Double = CDbl(IIf(retry = 0, 100, (node.Retry - retry) / node.Retry * 100)) RaiseEvent RetryProgressChanged(Me, New TestProgressChangedEventArgs(p)) '更新命令是否处于重试状态 If retry > 0 Then node.IsRetry = True executor.IsRetry = node.IsRetry '执行成功一次则判定成功,退出执行 result = executor.Execute() RaiseEvent TestNodeResultChanged(Me, New TestNodeResultChangedEventArgs(node, result)) If result.ExecuteResult Then Exit For '执行失败,休眠重试间隔 Thread.Sleep(node.RetryInterval) Next watch.Stop() result.StepTimeSpan = watch.Elapsed '进度修改 If node.RowListIndex > _startTestIndex AndAlso node.RowListIndex < _endTestIndex Then Dim p As Double = (node.RowListIndex - _startTestIndex) / _testCount * 100 RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(p)) End If 'todo:节点测试数据,考虑是否与节点测试完成事件合并 If String.IsNullOrWhiteSpace(node.RecordName) = False Then '处理需要入库的数据 Dim filedName As String = ReplaceString(node.RecordName, localVariable) '替换记录名称中变量 If _userVar.ContainsKey(filedName) Then _userVar(filedName) = result.RecordValue Else _userVar.Add(filedName, result.RecordValue) End If If node.SaveToDb Then '添加内容至数据库字段中 _testResult.AddCustomRecord(filedName, result.RecordValue) End If End If Return result End Function ''' ''' 获取指定变量名的变量值 ''' ''' 变量名 ''' 调用模块时传入的局部变量 ''' Private Function ReplaceVar(varName As String, Optional localVariable As Dictionary(Of String, String) = Nothing) As String '替换变量的逻辑顺序 '优先替换局部变量,也就是传进模块的变量 '其次使用用户变量,也就是记录入库的变量 '最后匹配系统变量,也就是预设带有特殊意义的字符串 If localVariable IsNot Nothing AndAlso localVariable.ContainsKey(varName) Then Return localVariable(varName) Else If _userVar.ContainsKey(varName) Then Return _userVar(varName) Else Select Case varName Case "ResourceDir" Return UtsPath.StationPacketResourceDirPath Case "StartDir" Return UtsPath.SystemDirPath Case Else Return String.Empty '返回空字符 End Select End If End If End Function ''' ''' 替换字符串中使用的变量,返回替换后的字符串 ''' ''' 原字符串 ''' 调用模块时传入的局部变量 ''' 替换后的字符串 Private Function ReplaceString(sourceString As String, Optional localVariable As Dictionary(Of String, String) = Nothing) As String Dim strBuilder As New StringBuilder Dim varName As New StringBuilder Dim findVar As Boolean For Each c As Char In sourceString If c = "{"c Then If findVar Then findVar = False strBuilder.Append("{") Else findVar = True End If ElseIf c = "}"c Then If findVar Then strBuilder.Append(ReplaceVar(varName.ToString(), localVariable)) varName.Clear() findVar = False Else strBuilder.Append("}") End If Else If findVar Then varName.Append(c) Else strBuilder.Append(c) End If End If Next Return strBuilder.ToString End Function ''' ''' 替换测试命令参数中的变量(变量格式:{var}),待删除 ''' ''' ''' Private Function ReplaceValue(cmd As TestCommand, Optional localVariable As Dictionary(Of String, String) = Nothing) As TestCommand Dim strBuilder As New StringBuilder Dim varName As New StringBuilder Dim findVar As Boolean For i As Integer = 0 To cmd.Parameter.Count - 1 findVar = False varName.Clear() strBuilder.Clear() For Each c As Char In cmd.Parameter(i) If c = "{"c Then If findVar Then findVar = False strBuilder.Append("{") Else findVar = True End If ElseIf c = "}"c Then If findVar Then strBuilder.Append(ReplaceVar(varName.ToString(), localVariable)) varName.Clear() findVar = False Else strBuilder.Append("}") End If Else If findVar Then varName.Append(c) Else strBuilder.Append(c) End If End If Next cmd.Parameter(i) = strBuilder.ToString() Next Return cmd End Function Public Sub StepTest() If TestStatus <> TestStatusEnum.Testing Then Return _nextPause = True If _nodePaused Then _exitPaused = True End If End Sub Public Sub ContinueTest() If TestStatus <> TestStatusEnum.Testing Then Return _nextPause = False _exitPaused = True End Sub ''' ''' 退出执行,测试结果为失败 ''' Public Sub ExitTest() If TestStatus <> TestStatusEnum.Testing Then Return _exitTest = True _nextPause = False _exitPaused = True MsgBox($"{TestStatus}:{_exitTest}:{_nextPause}:{_exitPaused}") End Sub #End Region #Region "测试函数集合" ''' ''' 测试主函数,测试Main模块,根据测试结果测试Pass/Fail模块 ''' Private Sub TestFunction() _testResult.ResetTestResult() '重置测试结果信息 '初始化测试总项数据,用于进度条计算 _startTestIndex = _testModules(FixedModuleEnum.Main.ToString).RowListIndex _endTestIndex = _startTestIndex + _testModules(FixedModuleEnum.Main.ToString).AllChildCount _testCount = _testModules(FixedModuleEnum.Main.ToString).AllChildCount TestStatus = TestStatusEnum.Testing RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) Dim result As TestCommandReturn If _setupModuleExecuted = False Then '设定模块未执行 result = ExecuteFixedModule(FixedModuleEnum.Setup) If result.ExecuteResult Then _setupModuleExecuted = True Else result.ExecuteResultTipString &= $"[{FixedModuleEnum.Setup}]模块执行失败,{result.ExecuteResultTipString}" TestStatus = TestStatusEnum.TestFail RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) 'todo:结束测试 ' TestEnd Return End If End If _testWatch.Restart() RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) result = ExecuteFixedModule(FixedModuleEnum.Main) If result.ExecuteResult Then '执行测试主模块 _testPassCount += 1 _testResult.TestResult = TestResult.TestResultEnum.Pass ExecuteFixedModule(FixedModuleEnum.Pass) '执行测试成功模块 RaiseEvent TestPass(Me, New EventArgs()) TestStatus = TestStatusEnum.TestPass RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) Else _testFailCount += 1 _testResult.TestResult = TestResult.TestResultEnum.Fail _testResult.FailSteps.Add(_testNode) _testResult.ErrCode = _testNode.ErrorCode ExecuteFixedModule(FixedModuleEnum.Fail) '执行测试失败模块 RaiseEvent TestFail(Me, New TestFailEventArgs(_testNode)) TestStatus = TestStatusEnum.TestFail RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) End If RaiseEvent TestCountChanged(Me, New TestCountChangedEventArgs(_testPassCount, _testFailCount)) _testWatch.Stop() RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) _testResult.UserID = ProcessStation.UserId _testResult.UsedTime = _testWatch.Elapsed _testResult.OrderID = DbConnector.SearchOrderID(_processStation.ParentProject.Index, _testResult.DUT_SN) End Sub ''' ''' 调试测试当前节点及其子节点 ''' ''' 节点对象 Public Sub TestNode(obj As Object) Dim node As RowNode = CType(obj, RowNode) DebugMode = True '初始化测试总项数据,用于进度条计算 _startTestIndex = node.RowListIndex _endTestIndex = _startTestIndex + node.AllChildCount _testCount = node.AllChildCount _exitTest = False _testResult.ResetTestResult() '重置测试结果信息 RaiseEvent TestStart(Me, New EventArgs()) _userVar.Clear() '清空全局变量 TestStatus = TestStatusEnum.Testing RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testWatch.Restart() RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) Dim result As TestCommandReturn = ExecutePlan(node, Nothing) If result.ExecuteResult Then TestStatus = TestStatusEnum.TestPass RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testFailCount += 1 _testResult.TestResult = TestResult.TestResultEnum.Fail RaiseEvent TestPass(Me, New EventArgs()) Else TestStatus = TestStatusEnum.TestFail RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testFailCount += 1 _testResult.TestResult = TestResult.TestResultEnum.Fail RaiseEvent TestFail(Me, New TestFailEventArgs(_testNode)) End If _testWatch.Stop() RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) '进度修改百分百 RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(100)) RaiseEvent TestEnd(Me, New TestEndEventArgs(_testResult)) End Sub ''' ''' 从当前节点调试测试,直到测试完当前顶级模块 ''' ''' 节点对象 Public Sub TestBeginWithNode(obj As Object) Dim node As RowNode = CType(obj, RowNode) '获取顶级节点 Dim tmpNode As RowNode = node While tmpNode.RowLever > 0 tmpNode = tmpNode.ParentNode End While '初始化测试总项数据,用于进度条计算 _startTestIndex = node.RowListIndex _endTestIndex = tmpNode.RowIndex + tmpNode.AllChildCount _testCount = _endTestIndex - _startTestIndex DebugMode = True _exitTest = False _testResult.ResetTestResult() '重置测试结果信息 RaiseEvent TestStart(Me, New EventArgs()) _userVar.Clear() '清空全局变量 TestStatus = TestStatusEnum.Testing RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testWatch.Restart() RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) Dim result As TestCommandReturn = BeginWithNode(node) If result.ExecuteResult Then TestStatus = TestStatusEnum.TestPass RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testFailCount += 1 _testResult.TestResult = TestResult.TestResultEnum.Fail RaiseEvent TestPass(Me, New EventArgs()) Else TestStatus = TestStatusEnum.TestFail RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testFailCount += 1 _testResult.TestResult = TestResult.TestResultEnum.Fail RaiseEvent TestFail(Me, New TestFailEventArgs(_testNode)) End If _testWatch.Stop() RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) '进度修改百分百 RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(100)) RaiseEvent TestEnd(Me, New TestEndEventArgs(_testResult)) End Sub ''' ''' 测试单节点及之后的所有节点 ''' ''' Private Function BeginWithNode(node As RowNode) As TestCommandReturn Dim result As New TestCommandReturn While node IsNot Nothing If _exitTest Then Return GetExitTestReturn() result = ExecutePlan(node, Nothing) If result.ExecuteResult = False Then If TestFailMode = TestFailModeEnum.StepFail Then Exit While '单步失败模式下退出测试,不再执行 End If End If If node.RowLever = 0 Then Exit While If node.NextNode Is Nothing Then node = node.ParentNode.NextNode Else node = node.NextNode End If End While Return result End Function ''' ''' 调试测试节点数组 ''' ''' Public Sub TestNodes(nodes() As RowNode) _exitTest = False _testResult.ResetTestResult() '重置测试结果信息 RaiseEvent TestStart(Me, New EventArgs()) _userVar.Clear() '清空全局变量 TestStatus = TestStatusEnum.Testing RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testWatch.Restart() RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) Dim result As TestCommandReturn = TestNodesFunction(nodes) If result.ExecuteResult Then TestStatus = TestStatusEnum.TestPass RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testFailCount += 1 _testResult.TestResult = TestResult.TestResultEnum.Fail RaiseEvent TestPass(Me, New EventArgs()) Else TestStatus = TestStatusEnum.TestFail RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testFailCount += 1 _testResult.TestResult = TestResult.TestResultEnum.Fail RaiseEvent TestFail(Me, New TestFailEventArgs(_testNode)) End If _testWatch.Stop() RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) '进度修改百分百 RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(100)) RaiseEvent TestEnd(Me, New TestEndEventArgs(_testResult)) End Sub ''' ''' 调试测试节点数组,包含其子节点 ''' ''' Public Function TestNodesFunction(nodes() As RowNode) As TestCommandReturn Dim result As New TestCommandReturn For Each node As RowNode In nodes If _exitTest Then Return GetExitTestReturn() '退出测试 result = ExecutePlan(node, Nothing) If result.ExecuteResult Then Continue For '执行成功则执行下一流程 If TestFailMode = TestFailModeEnum.StepFail Then Exit For '单步失败模式下退出测试,不再执行 Next Return result End Function ''' ''' 调试测试子节点集合 ''' ''' Public Sub TestChildNodes(nodes As RowNodeCollection) _exitTest = False _testResult.ResetTestResult() '重置测试结果信息 RaiseEvent TestStart(Me, New EventArgs()) _userVar.Clear() '清空全局变量 TestStatus = TestStatusEnum.Testing RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testWatch.Restart() RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) Dim result As TestCommandReturn = TestNodesFunction(nodes) If result.ExecuteResult Then TestStatus = TestStatusEnum.TestPass RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testFailCount += 1 _testResult.TestResult = TestResult.TestResultEnum.Fail RaiseEvent TestPass(Me, New EventArgs()) Else TestStatus = TestStatusEnum.TestFail RaiseEvent TestStatusChanged(Me, New TestStatusChangedEventArgs(TestStatus)) _testFailCount += 1 _testResult.TestResult = TestResult.TestResultEnum.Fail RaiseEvent TestFail(Me, New TestFailEventArgs(_testNode)) End If _testWatch.Stop() RaiseEvent TestTimeChanged(Me, New TestTimeEventArgs(_testWatch.Elapsed)) '进度修改百分百 RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(100)) RaiseEvent TestEnd(Me, New TestEndEventArgs(_testResult)) End Sub ''' ''' 调试测试节点集合,及其子节点 ''' ''' Public Function TestNodesFunction(nodes As RowNodeCollection) As TestCommandReturn Dim result As New TestCommandReturn For Each node As RowNode In nodes If _exitTest Then Return GetExitTestReturn() '退出测试 result = ExecutePlan(node, Nothing) If result.ExecuteResult Then Continue For '执行成功则执行下一流程 If TestFailMode = TestFailModeEnum.StepFail Then Exit For '单步失败模式下退出测试,不再执行 Next Return result End Function Public Sub TestFixedModule([module] As FixedModuleEnum) TestNode(_testModules($"{[module]}")) End Sub Public Sub TestSetupModule() TestFixedModule(FixedModuleEnum.Setup) End Sub Public Sub TestMainModule() TestFixedModule(FixedModuleEnum.Main) End Sub Public Sub TestPassModule() TestFixedModule(FixedModuleEnum.Pass) End Sub Public Sub TestFailModule() TestFixedModule(FixedModuleEnum.Fail) End Sub Public Sub TestCleanupModule() TestFixedModule(FixedModuleEnum.Cleanup) End Sub #End Region Enum TestFailModeEnum ''' ''' 单步测试失败后退出测试,判定测试失败 ''' StepFail ''' ''' 单步测试失败后继续测试,执行所有测试流程后,判定测试失败 ''' AllFail End Enum Enum NodeDebugMode ''' ''' 仅测试当前节点及其子节点 ''' OnlyNode ''' ''' 从节点开始往下测试 ''' BeginNode End Enum End Class End Namespace