Private/New-QAFrameworkTestMetadata.ps1
|
function New-QAFrameworkTestMetadata { <# .SYNOPSIS Builds a schema v1 QAFramework test metadata object for a single test. .DESCRIPTION Merges the values found in the C# class attribute block with the values found in the legacy .meta file and fills every remaining field with the legacy default. Attribute values always win; the .meta file only fills gaps, which keeps legacy RTManager tests (that carry no attributes at all) working. .PARAMETER CsPath Path to the test .cs file. Optional for legacy .meta-only tests. .PARAMETER MetaPath Path to the .meta file. Optional for attribute-only tests. .PARAMETER ClassName Restricts the attribute block lookup to a specific class in the .cs file. .PARAMETER Name Fallback test name when no fixture attribute supplies one. .PARAMETER RegressionTestsRoot Root used to make the source paths in the output relative. .PARAMETER FolderTag Automation script folder tag, e.g. 'QAOps\MyPackage\Team\Test'. .OUTPUTS PSCustomObject following schema v1. #> [CmdletBinding()] [OutputType([pscustomobject])] param( [string]$CsPath, [string]$MetaPath, [string]$ClassName, [string]$Name, [string]$RegressionTestsRoot, [string]$FolderTag ) $fromAttributes = @{} $methodFlags = @{ hasBeforeSwitch = $false; hasAfterSwitch = $false; hasAfterSwitchBack = $false } if ($CsPath -and (Test-Path -LiteralPath $CsPath)) { $content = Get-Content -LiteralPath $CsPath -Raw $blockParams = @{ Content = $content } if ($ClassName) { $blockParams['ClassName'] = $ClassName } $block = Get-QAFrameworkClassAttributeBlock @blockParams if ($block) { $fromAttributes = ConvertFrom-QAFrameworkAttributeBlock -Block $block } $methodFlags = Get-QAFrameworkMethodAttributeFlag -Content $content } $fromMeta = @{} if ($MetaPath -and (Test-Path -LiteralPath $MetaPath)) { $fromMeta = ConvertFrom-QAFrameworkMetaFile -Path $MetaPath } # Attributes win, .meta fills the gaps. $merged = @{} foreach ($key in $fromMeta.Keys) { $merged[$key] = $fromMeta[$key] } foreach ($key in $fromAttributes.Keys) { $merged[$key] = $fromAttributes[$key] } $resolvedName = $merged['name'] if ([string]::IsNullOrWhiteSpace($resolvedName)) { $resolvedName = $Name } if ([string]::IsNullOrWhiteSpace($resolvedName) -and $CsPath) { $resolvedName = [IO.Path]::GetFileNameWithoutExtension($CsPath) } if ([string]::IsNullOrWhiteSpace($resolvedName) -and $MetaPath) { $resolvedName = [IO.Path]::GetFileNameWithoutExtension($MetaPath) } $fixture = if ($merged.ContainsKey('fixture')) { $merged['fixture'] } else { 'Standard' } $failover = $null if ($fixture -eq 'Failover') { $failover = if ($merged.ContainsKey('failover')) { $merged['failover'].Clone() } else { @{ runDirectBeforeSwitch = $false; runDirectAfterSwitch = $false; runOnNonFailoverSystems = $false } } foreach ($key in $methodFlags.Keys) { $failover[$key] = $methodFlags[$key] } $failover = [pscustomobject]$failover } $diagnosticRunType = $null if ($fixture -eq 'Diagnostic') { $diagnosticRunType = if ($merged.ContainsKey('diagnosticRunType')) { $merged['diagnosticRunType'] } else { 'BeforeAndAfter' } } $disabled = $null if ($merged.ContainsKey('disabled') -and $merged['disabled']) { $disabled = [pscustomobject]@{ reason = [string]$merged['disabled']['reason'] } } $minVersion = if ($merged.ContainsKey('minVersion')) { [pscustomobject]$merged['minVersion'] } else { [pscustomobject]@{ featureRelease = ''; nextMainRelease = ''; mainRelease = '' } } $solution = if ($merged.ContainsKey('solution')) { [pscustomobject]$merged['solution'] } else { [pscustomobject]@{ name = 'None'; minVersion = '0.0.0' } } $arrayKeys = @('keywords', 'squads', 'maintainers', 'customers', 'localDbs', 'dcpIds', 'rnIds', 'projectIds', 'dllReferences') $arrays = @{} foreach ($key in $arrayKeys) { $values = [string[]]@() if ($merged.ContainsKey($key) -and $null -ne $merged[$key]) { $values = [string[]]@($merged[$key]) } $arrays[$key] = $values } $getBool = { param([string]$Key, [bool]$Default) if ($merged.ContainsKey($Key) -and $null -ne $merged[$Key]) { [bool]$merged[$Key] } else { $Default } } $relative = { param([string]$FullPath) if (-not $FullPath) { return $null } if ($RegressionTestsRoot) { try { $root = (Resolve-Path -LiteralPath $RegressionTestsRoot -ErrorAction Stop).ProviderPath $full = (Resolve-Path -LiteralPath $FullPath -ErrorAction Stop).ProviderPath if ($full.StartsWith($root, [StringComparison]::OrdinalIgnoreCase)) { return $full.Substring($root.Length).TrimStart([IO.Path]::DirectorySeparatorChar, [IO.Path]::AltDirectorySeparatorChar) } } catch { # The path could not be resolved, so the full path is returned as is. } } return $FullPath } return [pscustomobject]@{ name = $resolvedName fixture = $fixture diagnosticRunType = $diagnosticRunType failover = $failover disabled = $disabled weight = if ($merged.ContainsKey('weight')) { [int]$merged['weight'] } else { 1 } canRunConcurrently = & $getBool 'canRunConcurrently' $true targetDma = if ($merged.ContainsKey('targetDma')) { [string]$merged['targetDma'] } else { 'One' } keywords = $arrays['keywords'] squads = $arrays['squads'] maintainers = $arrays['maintainers'] customers = $arrays['customers'] minVersion = $minVersion localDbs = $arrays['localDbs'] solution = $solution isCentralizedOnly = & $getBool 'isCentralizedOnly' $false isNonCentralizedOnly = & $getBool 'isNonCentralizedOnly' $false isRedGreen = & $getBool 'isRedGreen' $false isBaseline = & $getBool 'isBaseline' $false isLeakTest = & $getBool 'isLeakTest' $false dcpIds = $arrays['dcpIds'] rnIds = $arrays['rnIds'] projectIds = $arrays['projectIds'] source = [pscustomobject]@{ cs = & $relative $CsPath meta = & $relative $MetaPath folderTag = $FolderTag } dllReferences = $arrays['dllReferences'] } } |