[Windows] Refactor test helpers (#8889)

This commit is contained in:
Vasilii Polikarpov
2023-11-27 11:37:49 +01:00
committed by GitHub
parent 79c347765a
commit 9492109c62
5 changed files with 96 additions and 81 deletions

View File

@@ -33,11 +33,11 @@ Describe "Haskell" {
} }
It "GHC <ghcVersion> is installed" -TestCases $ghcTestCases { It "GHC <ghcVersion> is installed" -TestCases $ghcTestCases {
"$binGhcPath --version" | Should -MatchCommandOutput $ghcShortVersion "$binGhcPath --version" | Should -OutputTextMatchingRegex $ghcShortVersion
} }
It "GHC <defaultGhcVersion> is the default version and should be the latest installed" -TestCases $ghcDefaultCases { It "GHC <defaultGhcVersion> is the default version and should be the latest installed" -TestCases $ghcDefaultCases {
"ghc --version" | Should -MatchCommandOutput $defaultGhcShortVersion "ghc --version" | Should -OutputTextMatchingRegex $defaultGhcShortVersion
} }
It "Cabal is installed" { It "Cabal is installed" {

View File

@@ -1,25 +1,6 @@
[CmdletBinding()] [CmdletBinding()]
param() param()
function Get-CommandResult {
Param (
[Parameter(Mandatory)][string] $Command
)
# CMD trick to suppress and show error output because some commands write to stderr (for example, "python --version")
[string[]]$output = & $env:comspec /c "$Command 2>&1"
$exitCode = $LASTEXITCODE
return @{
Output = $output
ExitCode = $exitCode
}
}
# Gets path to the tool, analogue of 'which tool'
function Get-WhichTool($tool) {
return (Get-Command $tool).Path
}
# Gets value of environment variable by the name # Gets value of environment variable by the name
function Get-EnvironmentVariable($variable) { function Get-EnvironmentVariable($variable) {
return [System.Environment]::GetEnvironmentVariable($variable, "Machine") return [System.Environment]::GetEnvironmentVariable($variable, "Machine")
@@ -37,8 +18,34 @@ function Update-Environment {
$env:PATH = [Environment]::GetEnvironmentVariable("PATH", "Machine") $env:PATH = [Environment]::GetEnvironmentVariable("PATH", "Machine")
} }
# Run Pester tests for specific tool
function Invoke-PesterTests { function Invoke-PesterTests {
<#
.SYNOPSIS
Runs Pester tests based on the provided test file and test name.
.DESCRIPTION
The Invoke-PesterTests function runs Pester tests based on the provided test file and test name.
It supports filtering tests by name and generating test result output.
.PARAMETER TestFile
The name of the test file to run. This should be the base name of the test file without the extension.
.PARAMETER TestName
The name of the specific test to run. If provided, only the test with the matching name will be executed.
.EXAMPLE
Invoke-PesterTests -TestFile "MyTests" -TestName "Test1"
Runs the test named "Test1" from the test file "MyTests.Tests.ps1".
.EXAMPLE
Invoke-PesterTests -TestFile "*" -TestName "Test2"
Runs all tests from all test files and generates the test result output.
.NOTES
This function requires the Pester module to be installed.
#>
Param( Param(
[Parameter(Mandatory)][string] $TestFile, [Parameter(Mandatory)][string] $TestFile,
[string] $TestName [string] $TestName
@@ -77,23 +84,47 @@ function Invoke-PesterTests {
} }
} }
# Pester Assert to check exit code of command
function ShouldReturnZeroExitCode { function ShouldReturnZeroExitCode {
<#
.SYNOPSIS
Implements a custom Should-operator for the Pester framework.
.DESCRIPTION
This function is used to check if a command has returned a zero exit code.
It can be used by registering it using the Add-ShouldOperator function in Pester.
.PARAMETER ActualValue
The actual value to be checked.
.PARAMETER Negate
A switch parameter that, when specified, negates the result of the check.
.PARAMETER Because
An optional string that provides additional context or explanation for the check.
.NOTES
This function is designed to be used with the Pester framework.
.LINK
https://pester.dev/docs/assertions/custom-assertions
#>
Param( Param(
[String] $ActualValue, [string] $ActualValue,
[switch] $Negate, [switch] $Negate,
[string] $Because [string] $Because
) )
$result = Get-CommandResult $ActualValue $outputLines = (& $env:comspec /c "$ActualValue 2>&1") -as [string[]]
$exitCode = $LASTEXITCODE
[bool]$succeeded = $result.ExitCode -eq 0 [bool] $succeeded = $exitCode -eq 0
if ($Negate) { $succeeded = -not $succeeded } if ($Negate) { $succeeded = -not $succeeded }
if (-not $succeeded) { if (-not $succeeded) {
$commandOutputIndent = " " * 4 $commandOutputIndent = " " * 4
$commandOutput = ($result.Output | ForEach-Object { "${commandOutputIndent}${_}" }) -join "`n" $commandOutput = ($outputLines | ForEach-Object { "${commandOutputIndent}${_}" }) -join "`n"
$failureMessage = "Command '${ActualValue}' has finished with exit code ${actualExitCode}`n${commandOutput}" $failureMessage = "Command '${ActualValue}' has finished with exit code ${exitCode} and output:`n${commandOutput}"
} }
return [PSCustomObject] @{ return [PSCustomObject] @{
@@ -102,53 +133,41 @@ function ShouldReturnZeroExitCode {
} }
} }
# Pester Assert to check exit code of command with given parameter, the assertion performed up to 3 checks (without '-', with 1 and 2 '-') until succeeded function ShouldOutputTextMatchingRegex {
function ShouldReturnZeroExitCodeWithParam { <#
param ( .SYNOPSIS
[Parameter(Mandatory)] [string] $ActualValue, Implements a custom Should-operator for the Pester framework.
[switch] $Negate,
[string] $CallParameter = "version",
[string] $CallerSessionState
)
$delimiterCharacter = "" .DESCRIPTION
This function is used to check if a command outputs text that matches a regular expression.
It can be used by registering it using the Add-ShouldOperator function in Pester.
while ($delimiterCharacter.Length -le 2) { .PARAMETER ActualValue
$callParameterWithDelimiter = $delimiterCharacter + $CallParameter The actual value to be checked.
$commandToCheck = "$ActualValue $callParameterWithDelimiter"
[bool]$succeeded = (ShouldReturnZeroExitCode -ActualValue $commandToCheck).Succeeded
if ($succeeded) { .PARAMETER Negate
break A switch parameter that, when specified, negates the result of the check.
}
$delimiterCharacter += '-'
}
if ($Negate) { $succeeded = -not $succeeded }
if (-not $succeeded) { .PARAMETER Because
$failureMessage = "Tool '$ActualValue' has not returned 0 exit code for any of these flags: '$CallParameter' or '-$CallParameter' or '--$CallParameter'" An optional string that provides additional context or explanation for the check.
}
return [PSCustomObject] @{ .NOTES
Succeeded = $succeeded This function is designed to be used with the Pester framework.
FailureMessage = $failureMessage
} .LINK
} https://pester.dev/docs/assertions/custom-assertions
#>
# Pester Assert to match output of command
function ShouldMatchCommandOutput {
Param( Param(
[String] $ActualValue, [String] $ActualValue,
[String] $RegularExpression, [String] $RegularExpression,
[switch] $Negate [switch] $Negate
) )
$output = (Get-CommandResult $ActualValue).Output | Out-String [string] $output = (& $env:comspec /c "$ActualValue 2>&1")
[bool] $succeeded = $output -cmatch $RegularExpression [bool] $succeeded = $output -cmatch $RegularExpression
if ($Negate) { if ($Negate) { $succeeded = -not $succeeded }
$succeeded = -not $succeeded
}
$failureMessage = '' $failureMessage = ''
@@ -168,11 +187,10 @@ function ShouldMatchCommandOutput {
If (Get-Command -Name Add-ShouldOperator -ErrorAction SilentlyContinue) { If (Get-Command -Name Add-ShouldOperator -ErrorAction SilentlyContinue) {
Add-ShouldOperator -Name ReturnZeroExitCode -InternalName ShouldReturnZeroExitCode -Test ${function:ShouldReturnZeroExitCode} Add-ShouldOperator -Name ReturnZeroExitCode -InternalName ShouldReturnZeroExitCode -Test ${function:ShouldReturnZeroExitCode}
Add-ShouldOperator -Name ReturnZeroExitCodeWithParam -InternalName ShouldReturnZeroExitCodeWithParam -Test ${function:ShouldReturnZeroExitCodeWithParam} Add-ShouldOperator -Name OutputTextMatchingRegex -InternalName ShouldOutputTextMatchingRegex -Test ${function:ShouldOutputTextMatchingRegex}
Add-ShouldOperator -Name MatchCommandOutput -InternalName ShouldMatchCommandOutput -Test ${function:ShouldMatchCommandOutput}
} }
Function Get-ModuleVersionAsJob { function Get-ModuleVersionAsJob {
Param ( Param (
[Parameter(Mandatory)] [Parameter(Mandatory)]
[String] $modulePath, [String] $modulePath,
@@ -197,10 +215,7 @@ Function Get-ModuleVersionAsJob {
Remove-Job $testJob Remove-Job $testJob
} }
Export-ModuleMember -Function @( Export-ModuleMember -Function @(
'Get-CommandResult'
'Get-WhichTool'
'Get-EnvironmentVariable' 'Get-EnvironmentVariable'
'Invoke-PesterTests' 'Invoke-PesterTests'
'Get-ModuleVersionAsJob' 'Get-ModuleVersionAsJob'

View File

@@ -28,13 +28,13 @@ Describe "Java" {
$javaVariableValue | Should -Not -BeNullOrEmpty $javaVariableValue | Should -Not -BeNullOrEmpty
$javaPath = Join-Path $javaVariableValue "bin\java" $javaPath = Join-Path $javaVariableValue "bin\java"
$result = Get-CommandResult "`"$javaPath`" -version"
$result.ExitCode | Should -Be 0
if ($Version -eq 8) { if ($Version -eq 8) {
$Version = "1.${Version}" $Version = "1.${Version}"
} }
$outputPattern = "openjdk version `"${Version}" $outputPattern = "openjdk version `"${Version}"
$result.Output[0] | Should -Match $outputPattern
$outputLines = (& $env:comspec /c "`"$javaPath`" -version 2>&1") -as [string[]]
$LASTEXITCODE | Should -Be 0
$outputLines[0] | Should -Match $outputPattern
} }
} }

View File

@@ -28,7 +28,7 @@ Describe "MSYS2 packages" {
} }
It "<ToolName> is avaialable" -TestCases $TestCases { It "<ToolName> is avaialable" -TestCases $TestCases {
"$ToolName" | Should -ReturnZeroExitCodeWithParam "$ToolName --version" | Should -ReturnZeroExitCode
} }
AfterEach { AfterEach {
@@ -43,7 +43,7 @@ foreach ($mingwType in $mingwTypes) {
$execDir = Join-Path "C:\msys64" $mingwType.exec_dir | Join-Path -ChildPath "bin" $execDir = Join-Path "C:\msys64" $mingwType.exec_dir | Join-Path -ChildPath "bin"
foreach ($tool in $tools) { foreach ($tool in $tools) {
Context "$($tool.name) package"{ Context "$($tool.name) package" {
$executables = $tool.executables | ForEach-Object { $executables = $tool.executables | ForEach-Object {
@{ @{
ExecName = $_ ExecName = $_
@@ -60,7 +60,7 @@ foreach ($mingwType in $mingwTypes) {
} }
It "<ExecName> is available" -TestCases $executables { It "<ExecName> is available" -TestCases $executables {
"$ExecName" | Should -ReturnZeroExitCodeWithParam "$ExecName --version" | Should -ReturnZeroExitCode
} }
AfterEach { AfterEach {

View File

@@ -49,13 +49,13 @@ function Test-DefaultVersion {
$binaryName = [IO.Path]::GetFileNameWithoutExtension($ToolExecs[0].Binary) $binaryName = [IO.Path]::GetFileNameWithoutExtension($ToolExecs[0].Binary)
$testCase = @{ Binary = $binaryName; Arguments = $ToolExecs[0].Arguments; ExpectedVersion = $ExpectedVersion } $testCase = @{ Binary = $binaryName; Arguments = $ToolExecs[0].Arguments; ExpectedVersion = $ExpectedVersion }
It "<ExpectedVersion> is default version" -TestCases $testCase { It "<ExpectedVersion> is default version" -TestCases $testCase {
$commandResult = Get-CommandResult "$Binary $Arguments" $outputLines = (& $env:comspec /c "$Binary $Arguments 2>&1") -as [string[]]
$commandResult.ExitCode | Should -Be 0 $LASTEXITCODE | Should -Be 0
$commandResult.Output | Should -Match $ExpectedVersion $outputLines | Should -Match $ExpectedVersion
} }
It "default version is located in tool-cache" -TestCases $testCase { It "default version is located in tool-cache" -TestCases $testCase {
$binaryFullPath = Get-WhichTool $Binary $binaryFullPath = (Get-Command $Binary).Path
$toolcacheDirectory = Get-TCToolPath -ToolName $Name $toolcacheDirectory = Get-TCToolPath -ToolName $Name
$binaryFullPath | Should -Match ([Regex]::Escape($toolcacheDirectory)) $binaryFullPath | Should -Match ([Regex]::Escape($toolcacheDirectory))
} }