This repository has been archived on 2025-11-27. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
AUTS_OLD/UTS_Core/UTSModule/Test/UtsTester.vb

1317 lines
48 KiB
VB.net
Raw Normal View History

2024-03-11 16:32:52 +08:00
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 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
''' <summary>
''' 当前百分比
''' </summary>
''' <returns></returns>
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
'''<summary>测试开始事件</summary>
Public Event TestStart(sender As Object, e As EventArgs)
'''<summary>测试暂停事件</summary>
Public Event TestPause(sender As Object, e As TestPauseEventArgs)
'''<summary>测试成功事件</summary>
Public Event TestPass(sender As Object, e As EventArgs)
'''<summary>测试失败事件</summary>
Public Event TestFail(sender As Object, e As TestFailEventArgs)
'''<summary>测试结束事件</summary>
Public Event TestEnd(sender As Object, e As TestEndEventArgs)
'''<summary>测试状态变更事件</summary>
Public Event TestStatusChanged(sender As Object, e As TestStatusChangedEventArgs)
'''<summary>测试计数变更事件</summary>
Public Event TestCountChanged(sender As Object, e As TestCountChangedEventArgs)
'''<summary>测试节点变更事件</summary>
Public Event TestNodeChanged(sender As Object, e As TestNodeChangedEventArgs)
'''<summary>测试节点完成事件</summary>
Public Event TestNodeCompleted(sender As Object, e As TestNodeCompletedEventArgs)
'''<summary>测试时间变更事件</summary>
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)
''' <summary>当前测试节点</summary>
Private _testNode As RowNode
''' <summary> 当前测试固定模块</summary>
Private _testFixedModule As FixedModuleEnum = FixedModuleEnum.None
2024-03-11 16:32:52 +08:00
''' <summary>测试耗时计时器</summary>
Private ReadOnly _testWatch As New Stopwatch
''' <summary>单步执行耗时计时器</summary>
Private ReadOnly _stepWatch As New Stopwatch
''' <summary>程序运行后,测试通过总数</summary>
Private _testPassCount As Integer
''' <summary>程序运行后,测试失败总数</summary>
Private _testFailCount As Integer
''' <summary>是否已执行设置模块</summary>
Private _setupModuleExecuted As Boolean
''' <summary>是否处于调试断点</summary>
Private _nodePaused As Boolean
''' <summary>是否退出调试断点</summary>
Private _exitPaused As Boolean
''' <summary>是否下一节点调试断点</summary>
Private _nextPause As Boolean
''' <summary>内置模块入口集合</summary>
Private ReadOnly _testModules As Dictionary(Of String, RowNode)
''' <summary>自定义模块下函数入口集合</summary>
Private ReadOnly _customModules As Dictionary(Of String, RowNode)
''' <summary>测试结果内容</summary>
Private ReadOnly _testResult As TestResult
''' <summary>是否退出测试</summary>
Private _exitTest As Boolean
''' <summary>测试时间线程</summary>
Private ReadOnly _timeThread As Thread
''' <summary>测试过程中,产生的变量存储</summary>
Private ReadOnly _userVar As New Dictionary(Of String, String)
''' <summary>测试过程中,全局变量存储</summary>
Private ReadOnly _globalVar As New Dictionary(Of String, String)
''' <summary>测试过程中,使用的测试站位</summary>
Private _processStation As ProcessStation
''' <summary>测试器句柄,全局唯一</summary>
Private Shared _tester As UtsTester
''' <summary>初始化测试器线程锁</summary>
Private Shared ReadOnly InitLock As New Object()
Private _startTestIndex As Integer
Private _endTestIndex As Integer
Private _testCount As Integer
''' <summary>
''' 创建测试器,若测试器已经创建则返回句柄
''' </summary>
''' <returns></returns>
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
''' <summary>测试状态</summary>
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
2024-03-11 16:32:52 +08:00
''' <summary>
''' 判定测试失败的模式
''' </summary>
''' <returns></returns>
Public Property TestFailMode() As TestFailModeEnum
''' <summary>
''' 测试时,重新执行Setup模块
''' </summary>
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
''' <summary>
''' 获取指定名称的模块节点
''' </summary>
''' <param name="name"></param>
''' <returns></returns>
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
''' <summary>
''' 开始测试,此函数为正式测试调用
''' </summary>
Public Sub StartTest()
_userVar.Clear() '清空全局变量
_testResult.ResetTestResult() '重置测试结果
DebugMode = False
_exitTest = False
RaiseEvent TestStart(Me, New EventArgs())
'重置测试进度
RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(0))
2024-03-11 16:32:52 +08:00
'测试主代码
TestFunction()
'进度修改百分百
RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(100))
'测试完成
RaiseEvent TestEnd(Me, New TestEndEventArgs(_testResult))
End Sub
''' <summary>
''' 开始调试测试,此函数为正式测试调用
''' </summary>
Public Sub StartDebugTest()
DebugMode = True
_exitTest = False
2024-03-11 16:32:52 +08:00
_userVar.Clear() '清空全局变量
_testResult.ResetTestResult() '重置测试结果
RaiseEvent TestStart(Me, New EventArgs())
2024-03-11 16:32:52 +08:00
'重置测试进度
RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(0))
2024-03-11 16:32:52 +08:00
'测试主代码
TestFunction()
'进度修改百分百
RaiseEvent TestProgressChanged(Me, New TestProgressChangedEventArgs(100))
'测试完成
RaiseEvent TestEnd(Me, New TestEndEventArgs(_testResult))
End Sub
''' <summary>
''' 流程修改后保存,更新模块索引
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
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
''' <summary>
''' 更新测试模块入库
''' </summary>
Public Sub UpdateTestModule(rowNodes As RowNodeCollection)
_testModules.Clear()
GetTestModule(_testModules, rowNodes)
End Sub
''' <summary>
''' 获取执行行节点集合中测试模块入口,并存储至内部模块入口集合
''' </summary>
''' <param name="modules">存储测试模块入口集合</param>
''' <param name="nodes">行节点集合</param>
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
''' <summary>
''' 执行内置模块函数
''' </summary>
''' <param name="moduleName"></param>
''' <returns></returns>
Public Function ExecuteFixedModule(moduleName As FixedModuleEnum) As TestCommandReturn
Dim result As TestCommandReturn
_testFixedModule = moduleName
2024-03-11 16:32:52 +08:00
If _testModules.ContainsKey(moduleName.ToString()) Then
Dim node As RowNode = _testModules(moduleName.ToString())
node.IsRetry = False '顶级节点最初重试状态为false
result = ExecutePlan(node Nothing)
2024-03-11 16:32:52 +08:00
Else
result = New TestCommandReturn()
result.ExecuteResult = False
result.ExecuteResultTipString = $"未搜索到[{moduleName}]模块"
End If
_testFixedModule = FixedModuleEnum.None '重置测试固定模块
2024-03-11 16:32:52 +08:00
Return result
End Function
#Region "获取特殊情况返回"
''' <summary>
''' 获取用户退出测试的执行返回结果
''' </summary>
''' <returns></returns>
Private Function GetExitTestReturn() As TestCommandReturn
Dim result As New TestCommandReturn
result.ExecuteResult = False
result.ExecuteResultTipString = $"用户结束测试过程"
Return result
End Function
''' <summary>
''' 获取不运行的节点的执行返回结果
''' </summary>
''' <returns></returns>
Private Function GetNotActionNodeResult() As TestCommandReturn
Dim result As New TestCommandReturn
result.ExecuteResult = True
result.ExecuteResultTipString = $"无需执行的测试节点"
Return result
End Function
''' <summary>
''' 获取未知的行节点类型的执行返回结果
''' </summary>
''' <param name="node">当前行节点</param>
''' <returns></returns>
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
''' <summary>
''' 执行模块流程
''' </summary>
''' <param name="node"></param>
''' <returns></returns>
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
2024-03-11 16:32:52 +08:00
'重置模块测试结果
result.ExecuteResult = True
'测试子节点
For Each rowNode As RowNode In node.RowNodes
If _exitTest Then Return GetExitTestReturn() '退出执行检测
rowNode.IsRetry = node.IsRetry '将父节点的重试状态赋予子节点
2024-03-11 16:32:52 +08:00
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
Return result
End Function
''' <summary>
''' 执行控制流程
''' </summary>
''' <param name="node"></param>
''' <returns>测试结果</returns>
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
''' <summary>
''' 执行控制结构的条件部分
''' </summary>
''' <param name="node"></param>
''' <returns></returns>
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
''' <summary>
''' 执行类型为普通流程的行节点
''' </summary>
''' <param name="node"></param>
''' <param name="localVariable"></param>
''' <returns></returns>
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
2024-04-18 05:23:04 +08:00
Dim watch As Stopwatch = Stopwatch.StartNew() '开启单步计时
2024-03-11 16:32:52 +08:00
Dim cmd As New TestCommand(node) '获取执行参数
ReplaceValue(cmd, localVariable) '执行前变量替换
Dim executor As TestCommandExecutor = TestCommandManger.CreateExecutor(cmd) '创建执行器
node.Desc4Record = ReplaceString(node.Description, localVariable) '替换记录名称中变量
2024-03-11 16:32:52 +08:00
'最大执行总数为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
2024-03-11 16:32:52 +08:00
'执行成功一次则判定成功,退出执行
result = executor.Execute()
If result.ExecuteResult Then Exit For
'执行失败,休眠重试间隔
Thread.Sleep(node.RetryInterval)
Next
2024-04-18 05:23:04 +08:00
watch.Stop()
result.StepTimeSpan = watch.Elapsed
2024-03-11 16:32:52 +08:00
'进度修改
If node.RowListIndex > _startTestIndex AndAlso node.RowListIndex < _endTestIndex Then
Dim p As Double = (node.RowListIndex - _startTestIndex) / _testCount * 100
2024-03-11 16:32:52 +08:00
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
''' <summary>
''' 获取指定变量名的变量值
''' </summary>
''' <param name="varName">变量名</param>
''' <param name="localVariable">调用模块时传入的局部变量</param>
''' <returns></returns>
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
''' <summary>
''' 替换字符串中使用的变量,返回替换后的字符串
''' </summary>
''' <param name="sourceString">原字符串</param>
''' <param name="localVariable">调用模块时传入的局部变量</param>
''' <returns>替换后的字符串</returns>
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
''' <summary>
''' 替换测试命令参数中的变量(变量格式:{var}),待删除
''' </summary>
''' <param name="cmd"></param>
''' <returns></returns>
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
''' <summary>
''' 退出执行,测试结果为失败
''' </summary>
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 "测试函数集合"
''' <summary>
''' 测试主函数测试Main模块根据测试结果测试Pass/Fail模块
''' </summary>
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
''' <summary>
''' 调试测试当前节点及其子节点
''' </summary>
''' <param name="obj">节点对象</param>
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
''' <summary>
''' 从当前节点调试测试,直到测试完当前顶级模块
''' </summary>
''' <param name="obj">节点对象</param>
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
''' <summary>
''' 测试单节点及之后的所有节点
''' </summary>
''' <param name="node"></param>
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
''' <summary>
''' 调试测试节点数组
''' </summary>
''' <param name="nodes"></param>
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
''' <summary>
''' 调试测试节点数组,包含其子节点
''' </summary>
''' <param name="nodes"></param>
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
''' <summary>
''' 调试测试子节点集合
''' </summary>
''' <param name="nodes"></param>
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
''' <summary>
''' 调试测试节点集合,及其子节点
''' </summary>
''' <param name="nodes"></param>
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
''' <summary>
''' 单步测试失败后退出测试,判定测试失败
''' </summary>
StepFail
''' <summary>
''' 单步测试失败后继续测试,执行所有测试流程后,判定测试失败
''' </summary>
AllFail
End Enum
Enum NodeDebugMode
''' <summary>
''' 仅测试当前节点及其子节点
''' </summary>
OnlyNode
''' <summary>
''' 从节点开始往下测试
''' </summary>
BeginNode
End Enum
End Class
End Namespace