From 1a454b5ca818eb01cf64a70b0349dbc0b9270798 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Wed, 22 Jan 2025 21:09:36 +0100 Subject: [PATCH 001/176] Remove main script and add GitHub workflows for release notes, dependency updates, linters, and action configuration --- .github/CODEOWNERS | 50 ++++++ .github/dependabot.yml | 11 ++ .github/linters/.markdown-lint.yml | 25 +++ .../linters/.powershell-psscriptanalyzer.psd1 | 18 ++ .github/release.yml | 18 ++ action.yml | 73 ++++++-- scripts/main.ps1 | 166 +++++++++++++++++- scripts/main.sh | 4 - 8 files changed, 340 insertions(+), 25 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/dependabot.yml create mode 100644 .github/linters/.markdown-lint.yml create mode 100644 .github/linters/.powershell-psscriptanalyzer.psd1 create mode 100644 .github/release.yml delete mode 100644 scripts/main.sh diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..beae856d --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,50 @@ +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners +# Each line is a file pattern followed by one or more owners. + +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @global-owner1 and @global-owner2 will be requested for +# review when someone opens a pull request. +* @PSModule/framework-maintainers + +# Order is important; the last matching pattern takes the most +# precedence. When someone opens a pull request that only +# modifies JS files, only @js-owner and not the global +# owner(s) will be requested for a review. +# *.js @js-owner + +# You can also use email addresses if you prefer. They'll be +# used to look up users just like we do for commit author +# emails. +# *.go docs@example.com + +# Teams can be specified as code owners as well. Teams should +# be identified in the format @org/team-name. Teams must have +# explicit write access to the repository. In this example, +# the octocats team in the octo-org organization owns all .txt files. +# *.txt @octo-org/octocats + +# In this example, @doctocat owns any files in the build/logs +# directory at the root of the repository and any of its +# subdirectories. +# /build/logs/ @doctocat + +# The `docs/*` pattern will match files like +# `docs/getting-started.md` but not further nested files like +# `docs/build-app/troubleshooting.md`. +# docs/* docs@example.com + +# In this example, @octocat owns any file in an apps directory +# anywhere in your repository. +# apps/ @octocat + +# In this example, @doctocat owns any file in the `/docs` +# directory in the root of your repository and any of its +# subdirectories. +# /docs/ @doctocat + +# In this example, @octocat owns any file in the `/apps` +# directory in the root of your repository except for the `/apps/github` +# subdirectory, as its owners are left empty. +# /apps/ @octocat +# /apps/github diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..f57e1e95 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: github-actions # See documentation for possible values + directory: / # Location of package manifests + schedule: + interval: weekly diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml new file mode 100644 index 00000000..b9ecdfa9 --- /dev/null +++ b/.github/linters/.markdown-lint.yml @@ -0,0 +1,25 @@ +########################### +## Markdown Linter rules ## +########################### + +# Linter rules doc: +# - https://github.com/DavidAnson/markdownlint + +############### +# Rules by id # +############### +MD004: false # Unordered list style +MD007: + indent: 2 # Unordered list indentation +MD013: + line_length: 808 # Line length +MD026: + punctuation: ".,;:!。,;:" # List of not allowed +MD029: false # Ordered list item prefix +MD033: false # Allow inline HTML +MD036: false # Emphasis used instead of a heading + +################# +# Rules by tags # +################# +blank_lines: false # Error on blank lines diff --git a/.github/linters/.powershell-psscriptanalyzer.psd1 b/.github/linters/.powershell-psscriptanalyzer.psd1 new file mode 100644 index 00000000..40d11d60 --- /dev/null +++ b/.github/linters/.powershell-psscriptanalyzer.psd1 @@ -0,0 +1,18 @@ +#Documentation: https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-settings +@{ + #CustomRulePath='path\to\CustomRuleModule.psm1' + #RecurseCustomRulePath='path\of\customrules' + #Severity = @( + # 'Error' + # 'Warning' + #) + #IncludeDefaultRules=${true} + ExcludeRules = @( + 'PSMissingModuleManifestField' + 'PSAvoidUsingWriteHost' + ) + #IncludeRules = @( + # 'PSAvoidUsingWriteHost', + # 'MyCustomRuleName' + #) +} diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 00000000..35c6ae86 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,18 @@ +# https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#configuring-automatically-generated-release-notes + +changelog: + exclude: + labels: + - NoRelease + categories: + - title: 🌟 Breaking Changes + labels: + - Major + - Breaking + - title: 🚀 New Features + labels: + - Minor + - Feature + - title: Other Changes + labels: + - '*' diff --git a/action.yml b/action.yml index 0a56ffb2..6cabe692 100644 --- a/action.yml +++ b/action.yml @@ -1,27 +1,68 @@ -name: '{{ NAME }}' -description: '{{ DESCRIPTION }}' +name: Invoke-Pester +description: Runs test based on PowerShell. author: PSModule branding: - icon: upload-cloud - color: white + icon: check-square + color: gray-dark inputs: - working-directory: - description: The working directory where Terraform will be executed + Name: + description: The name of the module to test. The name of the repository is used if not specified. required: false - subject: - description: The subject to greet + Path: + description: The path to the code to test. + required: true + TestsPath: + description: The path to the tests to run. required: false - default: World + default: tests + StackTraceVerbosity: + description: "Verbosity level of the stack trace. Allowed values: 'None', 'FirstLine', 'Filtered', 'Full'." + required: false + default: Filtered + Verbosity: + description: "Verbosity level of the test output. Allowed values: 'None', 'Normal', 'Detailed', 'Diagnostic'." + required: false + default: 'Detailed' + Debug: + description: Enable debug output. + required: false + default: 'false' + Verbose: + description: Enable verbose output. + required: false + default: 'false' + Version: + description: Specifies the version of the GitHub module to be installed. The value must be an exact version. + required: false + Prerelease: + description: Allow prerelease versions if available. + required: false + default: 'false' + +outputs: + result: + description: If the tests passed. + value: ${{ fromJSON(steps.test.outputs.result).result }} runs: using: composite steps: - - name: '{{ NAME }}' - shell: pwsh - working-directory: ${{ inputs.working-directory }} + - name: Invoke-Pester + uses: PSModule/GitHub-Script@v1 + id: test env: - GITHUB_ACTION_INPUT_subject: ${{ inputs.subject }} - run: | - # '{{ NAME }}' - . "${{ github.action_path }}\scripts\main.ps1" -Verbose + GITHUB_ACTION_INPUT_Name: ${{ inputs.Name }} + GITHUB_ACTION_INPUT_Path: ${{ inputs.Path }} + GITHUB_ACTION_INPUT_TestsPath: ${{ inputs.TestsPath }} + GITHUB_ACTION_INPUT_StackTraceVerbosity: ${{ inputs.StackTraceVerbosity }} + GITHUB_ACTION_INPUT_Verbosity: ${{ inputs.Verbosity }} + with: + Debug: ${{ inputs.Debug }} + Prerelease: ${{ inputs.Prerelease }} + Verbose: ${{ inputs.Verbose }} + Version: ${{ inputs.Version }} + ShowOutput: true + Script: | + # Invoke-Pester + ${{ github.action_path }}\scripts\main.ps1 diff --git a/scripts/main.ps1 b/scripts/main.ps1 index b054fccf..df2155d3 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -1,7 +1,163 @@ [CmdletBinding()] -param( - [Parameter()] - [string] $Subject = $env:GITHUB_ACTION_INPUT_subject -) +param() -Write-Host "Hello, $subject!" +LogGroup 'Loading inputs' { + $codeToTest = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath $env:GITHUB_ACTION_INPUT_Path + if (-not (Test-Path -Path $codeToTest)) { + throw "Path [$codeToTest] does not exist." + } + + if (-not (Test-Path -Path $env:GITHUB_ACTION_INPUT_TestsPath)) { + throw "Path [$env:GITHUB_ACTION_INPUT_TestsPath] does not exist." + } + + [pscustomobject]@{ + CodeToTest = $codeToTest + TestsPath = $env:GITHUB_ACTION_INPUT_TestsPath + StackTraceVerbosity = $env:GITHUB_ACTION_INPUT_StackTraceVerbosity + Verbosity = $env:GITHUB_ACTION_INPUT_Verbosity + } | Format-List +} + +############################################################################################ + +$moduleName = Split-Path -Path $Path -Leaf +$testSourceCode = $TestType -eq 'SourceCode' +$testModule = $TestType -eq 'Module' +$moduleTestsPath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath $TestsPath + +LogGroup 'Get test kit versions' { + $PSSAModule = Get-PSResource -Name PSScriptAnalyzer -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 + $pesterModule = Get-PSResource -Name Pester -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 + + [PSCustomObject]@{ + PowerShell = $PSVersionTable.PSVersion.ToString() + Pester = $pesterModule.version + PSScriptAnalyzer = $PSSAModule.version + } | Format-List +} + +LogGroup 'Add test - Common - PSScriptAnalyzer' { + $containers = @() + $PSSATestsPath = Join-Path -Path $PSScriptRoot -ChildPath '..\tests\PSScriptAnalyzer' + $settingsFileName = if ($testModule) { 'Settings.Module.psd1' } else { 'Settings.SourceCode.psd1' } + $settingsFilePath = Join-Path -Path $PSSATestsPath -ChildPath $settingsFileName + $containerParams = @{ + Path = Join-Path $PSSATestsPath 'PSScriptAnalyzer.Tests.ps1' + Data = @{ + Path = $Path + SettingsFilePath = $settingsFilePath + Debug = $false + Verbose = $false + } + } + Write-Host ($containerParams | ConvertTo-Json) + $containers += New-PesterContainer @containerParams +} + +LogGroup 'Add test - Common - PSModule' { + $containerParams = @{ + Path = Join-Path -Path $PSScriptRoot -ChildPath '..\tests\PSModule\Common.Tests.ps1' + Data = @{ + Path = $Path + Debug = $false + Verbose = $false + } + } + Write-Host ($containerParams | ConvertTo-Json) + $containers += New-PesterContainer @containerParams +} + +if ($testModule) { + LogGroup 'Add test - Module - PSModule' { + $containerParams = @{ + Path = Join-Path -Path $PSScriptRoot -ChildPath '..\tests\PSModule\Module.Tests.ps1' + Data = @{ + Path = $Path + Debug = $false + Verbose = $false + } + } + Write-Host ($containerParams | ConvertTo-Json) + $containers += New-PesterContainer @containerParams + } +} + +if ($testSourceCode) { + LogGroup 'Add test - SourceCode - PSModule' { + $containerParams = @{ + Path = Join-Path -Path $PSScriptRoot -ChildPath '..\tests\PSModule\SourceCode.Tests.ps1' + Data = @{ + Path = $Path + TestsPath = $moduleTestsPath + Debug = $false + Verbose = $false + } + } + Write-Host ($containerParams | ConvertTo-Json) + $containers += New-PesterContainer @containerParams + } +} + +if ($testModule) { + if (Test-Path -Path $moduleTestsPath) { + LogGroup "Add test - Module - $moduleName" { + $containerParams = @{ + Path = $moduleTestsPath + } + Write-Host ($containerParams | ConvertTo-Json) + $containers += New-PesterContainer @containerParams + } + } else { + Write-GitHubWarning "⚠️ No tests found - [$moduleTestsPath]" + } +} + +LogGroup 'Pester config' { + $pesterParams = @{ + Configuration = @{ + Run = @{ + Path = $Path + Container = $containers + PassThru = $true + } + TestResult = @{ + Enabled = $testModule + OutputFormat = 'NUnitXml' + OutputPath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'outputs\Test-Report.xml' + TestSuiteName = 'Unit tests' + } + CodeCoverage = @{ + Enabled = $testModule + OutputPath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'outputs\CodeCoverage-Report.xml' + OutputFormat = 'JaCoCo' + OutputEncoding = 'UTF8' + CoveragePercentTarget = 75 + } + Output = @{ + CIFormat = 'Auto' + StackTraceVerbosity = $StackTraceVerbosity + Verbosity = $Verbosity + } + } + } + Write-Host ($pesterParams | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) +} + +$testResults = Invoke-Pester @pesterParams + +LogGroup 'Test results' { + $testResults | Format-List + $failedTests = [int]$testResults.FailedCount + + if (($failedTests -gt 0) -or ($testResults.Result -ne 'Passed')) { + Write-GitHubError "❌ Some [$failedTests] tests failed." + } + if ($failedTests -eq 0) { + Write-GitHubNotice '✅ All tests passed.' + } + + Set-GitHubOutput -Name 'results' -Value $testResults +} + +exit $failedTests diff --git a/scripts/main.sh b/scripts/main.sh deleted file mode 100644 index 8589a85d..00000000 --- a/scripts/main.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -# Run 'git add --chmod=+x scripts\main.sh' to make the script executable - -echo "Hello, $SUBJECT!" From e8f22cbc8c1164c1900eeb21f872d2e008bc3bd8 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 10 Feb 2025 20:54:16 +0100 Subject: [PATCH 002/176] Add initial test scripts and configuration for Cars, Animals, and Planets modules --- .github/workflows/Auto-Configure.yml | 34 ------------ .github/workflows/Auto-Document.yml | 31 ----------- action.yml | 45 ---------------- scripts/Pester.Configuration.ps1 | 24 +++++++++ scripts/test.ps1 | 55 ++++++++++++++++++++ tests/Advanced/Animals/Animals.Container.ps1 | 8 +++ tests/Advanced/Animals/Animals.Data.ps1 | 8 +++ tests/Advanced/Animals/Animals.Tests.ps1 | 43 +++++++++++++++ tests/Advanced/Cars/Cars.Container.ps1 | 8 +++ tests/Advanced/Cars/Cars.Data.ps1 | 8 +++ tests/Advanced/Cars/Cars.Tests.ps1 | 21 ++++++++ tests/Advanced/Pester.Configuration.ps1 | 55 ++++++++++++++++++++ tests/Advanced/Planets/Planets.Container.ps1 | 8 +++ tests/Advanced/Planets/Planets.Data.ps1 | 8 +++ tests/Advanced/Planets/Planets.Tests.ps1 | 30 +++++++++++ tests/Simple/Get-Emoji.Tests.ps1 | 49 +++++++++++++++++ 16 files changed, 325 insertions(+), 110 deletions(-) delete mode 100644 .github/workflows/Auto-Configure.yml delete mode 100644 .github/workflows/Auto-Document.yml create mode 100644 scripts/Pester.Configuration.ps1 create mode 100644 scripts/test.ps1 create mode 100644 tests/Advanced/Animals/Animals.Container.ps1 create mode 100644 tests/Advanced/Animals/Animals.Data.ps1 create mode 100644 tests/Advanced/Animals/Animals.Tests.ps1 create mode 100644 tests/Advanced/Cars/Cars.Container.ps1 create mode 100644 tests/Advanced/Cars/Cars.Data.ps1 create mode 100644 tests/Advanced/Cars/Cars.Tests.ps1 create mode 100644 tests/Advanced/Pester.Configuration.ps1 create mode 100644 tests/Advanced/Planets/Planets.Container.ps1 create mode 100644 tests/Advanced/Planets/Planets.Data.ps1 create mode 100644 tests/Advanced/Planets/Planets.Tests.ps1 create mode 100644 tests/Simple/Get-Emoji.Tests.ps1 diff --git a/.github/workflows/Auto-Configure.yml b/.github/workflows/Auto-Configure.yml deleted file mode 100644 index e2321e42..00000000 --- a/.github/workflows/Auto-Configure.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Auto-Configure - -run-name: "Auto-Configure - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}" - -on: - pull_request_target: - branches: - - main - types: - - closed - - opened - - reopened - - synchronize - - labeled - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: - contents: write # Required to create releases - pull-requests: write # Required to create comments on the PRs - -jobs: - Auto-Configure: - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Auto-Configure - uses: PSModule/Auto-Configure@v1 - env: - GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/Auto-Document.yml b/.github/workflows/Auto-Document.yml deleted file mode 100644 index 6a62053a..00000000 --- a/.github/workflows/Auto-Document.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Auto-Document - -run-name: "Auto-Document - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}" - -on: - pull_request_target: - branches: - - main - types: - - opened - - reopened - - synchronize - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: - contents: write # Required to push to the branch - -jobs: - Auto-Document: - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Auto-Document - uses: PSModule/Auto-Document@v1 - env: - GITHUB_TOKEN: ${{ github.token }} diff --git a/action.yml b/action.yml index 6cabe692..673a6858 100644 --- a/action.yml +++ b/action.yml @@ -5,41 +5,6 @@ branding: icon: check-square color: gray-dark -inputs: - Name: - description: The name of the module to test. The name of the repository is used if not specified. - required: false - Path: - description: The path to the code to test. - required: true - TestsPath: - description: The path to the tests to run. - required: false - default: tests - StackTraceVerbosity: - description: "Verbosity level of the stack trace. Allowed values: 'None', 'FirstLine', 'Filtered', 'Full'." - required: false - default: Filtered - Verbosity: - description: "Verbosity level of the test output. Allowed values: 'None', 'Normal', 'Detailed', 'Diagnostic'." - required: false - default: 'Detailed' - Debug: - description: Enable debug output. - required: false - default: 'false' - Verbose: - description: Enable verbose output. - required: false - default: 'false' - Version: - description: Specifies the version of the GitHub module to be installed. The value must be an exact version. - required: false - Prerelease: - description: Allow prerelease versions if available. - required: false - default: 'false' - outputs: result: description: If the tests passed. @@ -51,17 +16,7 @@ runs: - name: Invoke-Pester uses: PSModule/GitHub-Script@v1 id: test - env: - GITHUB_ACTION_INPUT_Name: ${{ inputs.Name }} - GITHUB_ACTION_INPUT_Path: ${{ inputs.Path }} - GITHUB_ACTION_INPUT_TestsPath: ${{ inputs.TestsPath }} - GITHUB_ACTION_INPUT_StackTraceVerbosity: ${{ inputs.StackTraceVerbosity }} - GITHUB_ACTION_INPUT_Verbosity: ${{ inputs.Verbosity }} with: - Debug: ${{ inputs.Debug }} - Prerelease: ${{ inputs.Prerelease }} - Verbose: ${{ inputs.Verbose }} - Version: ${{ inputs.Version }} ShowOutput: true Script: | # Invoke-Pester diff --git a/scripts/Pester.Configuration.ps1 b/scripts/Pester.Configuration.ps1 new file mode 100644 index 00000000..da8c8a85 --- /dev/null +++ b/scripts/Pester.Configuration.ps1 @@ -0,0 +1,24 @@ +@{ + Run = @{ + Path = $Path + PassThru = $true + } + TestResult = @{ + Enabled = $true + OutputFormat = 'NUnitXml' + OutputPath = 'outputs\Test-Report.xml' + TestSuiteName = 'Unit tests' + } + CodeCoverage = @{ + Enabled = $true + OutputPath = 'outputs\CodeCoverage-Report.xml' + OutputFormat = 'JaCoCo' + OutputEncoding = 'UTF8' + CoveragePercentTarget = 75 + } + Output = @{ + CIFormat = 'Auto' + StackTraceVerbosity = 'Normal' + Verbosity = 'Detailed' + } +} diff --git a/scripts/test.ps1 b/scripts/test.ps1 new file mode 100644 index 00000000..38f3e239 --- /dev/null +++ b/scripts/test.ps1 @@ -0,0 +1,55 @@ +# Run all files with the name like *.Containers.ps1 in the current directory recursively. + +function Get-PesterContainer { + param( + [string] $Path + ) + + Get-ChildItem -Path $Path -Recurse -Filter *.Container.ps* | ForEach-Object { + $file = $_ + $param = switch ($file.Extension) { + '.ps1' { + . $file + } + '.psd1' { + Import-PowerShellDataFile -Path $file + } + } + New-PesterContainer @param + } +} + +function Get-PesterConfiguration { + param( + [string] $Path + ) + + $config = Get-ChildItem -Path $Path -Filter *.Configuration.ps* | ForEach-Object { + $file = $_ + switch ($file.Extension) { + '.ps1' { + . $file + } + '.psd1' { + Import-PowerShellDataFile -Path $file + } + } + } + New-PesterConfiguration -Hashtable $config +} + + +$Path = 'C:\Repos\GitHub\PSModule\Action\Invoke-Pester\tests\Advanced' +$containers = Get-PesterContainer -Path $Path + + +$Configuration = Get-PesterConfiguration -Path $Path +$Configuration.Run.Container = $containers + +$Configuration.Run.Container.Value + + +$Configuration | Convertto-Json -Depth 100 | Clip +$Configuration.Container | ConvertTo-Json -Depth 100 | Clip + +Invoke-Pester -Configuration $Configuration diff --git a/tests/Advanced/Animals/Animals.Container.ps1 b/tests/Advanced/Animals/Animals.Container.ps1 new file mode 100644 index 00000000..5bdeb19d --- /dev/null +++ b/tests/Advanced/Animals/Animals.Container.ps1 @@ -0,0 +1,8 @@ +@{ + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 + Data = @{ + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 + Debug = $false + Verbose = $false + } +} diff --git a/tests/Advanced/Animals/Animals.Data.ps1 b/tests/Advanced/Animals/Animals.Data.ps1 new file mode 100644 index 00000000..0e070679 --- /dev/null +++ b/tests/Advanced/Animals/Animals.Data.ps1 @@ -0,0 +1,8 @@ +# Animals.Settings.ps1 +$AnimalsSettings = @{ + # Expected number of animal types for testing + AnimalCount = 5 + + # Expected list of animal names for testing + AnimalNames = @('Lion', 'Tiger', 'Bear', 'Elephant', 'Giraffe') +} diff --git a/tests/Advanced/Animals/Animals.Tests.ps1 b/tests/Advanced/Animals/Animals.Tests.ps1 new file mode 100644 index 00000000..e33a1fae --- /dev/null +++ b/tests/Advanced/Animals/Animals.Tests.ps1 @@ -0,0 +1,43 @@ +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string] $Path +) + +BeforeAll { + . $Path +} + +Describe 'Animals Module Tests' { + Context 'Animal Count' { + It 'Should return the expected number of animals' { + $expectedCount = $AnimalsSettings.AnimalCount + $actualCount = $AnimalsSettings.AnimalNames.Count + $actualCount | Should -Be $expectedCount + } + } + Context 'Animal Names' { + It 'Should return the expected list of animal names' { + $expectedNames = $AnimalsSettings.AnimalNames + $actualNames = $AnimalsSettings.AnimalNames + $actualNames | Should -BeExactly $expectedNames + } + } +} + +Describe 'Animals Module Tests' { + Context 'Animal Count' { + It 'Should return the expected number of animals' { + $expectedCount = $AnimalsSettings.AnimalCount + $actualCount = $AnimalsSettings.AnimalNames.Count + $actualCount | Should -Be $expectedCount + } + } + Context 'Animal Names' { + It 'Should return the expected list of animal names' { + $expectedNames = $AnimalsSettings.AnimalNames + $actualNames = $AnimalsSettings.AnimalNames + $actualNames | Should -BeExactly $expectedNames + } + } +} diff --git a/tests/Advanced/Cars/Cars.Container.ps1 b/tests/Advanced/Cars/Cars.Container.ps1 new file mode 100644 index 00000000..5bdeb19d --- /dev/null +++ b/tests/Advanced/Cars/Cars.Container.ps1 @@ -0,0 +1,8 @@ +@{ + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 + Data = @{ + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 + Debug = $false + Verbose = $false + } +} diff --git a/tests/Advanced/Cars/Cars.Data.ps1 b/tests/Advanced/Cars/Cars.Data.ps1 new file mode 100644 index 00000000..d6394eee --- /dev/null +++ b/tests/Advanced/Cars/Cars.Data.ps1 @@ -0,0 +1,8 @@ +# Cars.Settings.ps1 +$CarsSettings = @{ + # Expected number of car models for testing + CarCount = 3 + + # Expected list of car models for testing + CarModels = @('Sedan', 'SUV', 'Coupe') +} diff --git a/tests/Advanced/Cars/Cars.Tests.ps1 b/tests/Advanced/Cars/Cars.Tests.ps1 new file mode 100644 index 00000000..b6a1efaa --- /dev/null +++ b/tests/Advanced/Cars/Cars.Tests.ps1 @@ -0,0 +1,21 @@ + +. "$PSScriptRoot\Cars.Settings.ps1" + +Describe 'Cars Module Tests' { + + Context 'Car Count' { + It 'Should return the expected number of car models' { + $expectedCount = $CarsSettings.CarCount + $actualCount = $CarsSettings.CarModels.Count + $actualCount | Should -Be $expectedCount + } + } + + Context 'Car Models' { + It 'Should return the expected list of car models' { + $expectedModels = $CarsSettings.CarModels + $actualModels = $CarsSettings.CarModels + $actualModels | Should -BeExactly $expectedModels + } + } +} diff --git a/tests/Advanced/Pester.Configuration.ps1 b/tests/Advanced/Pester.Configuration.ps1 new file mode 100644 index 00000000..96ef58a1 --- /dev/null +++ b/tests/Advanced/Pester.Configuration.ps1 @@ -0,0 +1,55 @@ +@{ + # Define run settings for Pester + Run = @{ + # Include specific test tags. For example, you might tag tests with "Planets", "Animals", or "Cars" + Include = @('Planets', 'Animals', 'Cars') + + # Exclude tests with certain tags (e.g., integration tests that are not run on every build) + Exclude = @('Integration') + + # Configure parallel test execution to speed up test runs. + Parallel = @{ + Enabled = $true + MaxRunspaceCount = 4 # Adjust based on your system's capabilities. + } + } + + # Output configuration: adjust verbosity, colors, and format. + Output = @{ + # Toggle verbose output for more details during test runs. + Verbose = $true + + # Define color output for test results (if your terminal supports color). + Color = @{ + Success = 'Green' + Failure = 'Red' + Error = 'Yellow' + } + + # Choose an output format; "Detailed" shows more information than "Short". + Format = 'Detailed' + } + + # Test-specific settings. + Test = @{ + # Timeout for individual tests, in milliseconds. + Timeout = 60000 + } + + # Code coverage settings. + CodeCoverage = @{ + Enabled = $true + + # Specify what files to include in code coverage calculations. + Include = @('*.ps1', '*.psm1') + + # Exclude test files to prevent them from skewing coverage results. + Exclude = @('*.Tests.ps1', '*Tests.ps1') + + # Output format can be "Cobertura", "Html", etc. + OutputFormat = 'Cobertura' + + # Define where the code coverage report should be saved. + OutputPath = "$PSScriptRoot\coverage.xml" + } +} diff --git a/tests/Advanced/Planets/Planets.Container.ps1 b/tests/Advanced/Planets/Planets.Container.ps1 new file mode 100644 index 00000000..5bdeb19d --- /dev/null +++ b/tests/Advanced/Planets/Planets.Container.ps1 @@ -0,0 +1,8 @@ +@{ + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 + Data = @{ + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 + Debug = $false + Verbose = $false + } +} diff --git a/tests/Advanced/Planets/Planets.Data.ps1 b/tests/Advanced/Planets/Planets.Data.ps1 new file mode 100644 index 00000000..31a192d8 --- /dev/null +++ b/tests/Advanced/Planets/Planets.Data.ps1 @@ -0,0 +1,8 @@ +# Planets.Settings.ps1 +$PlanetsSettings = @{ + # Expected number of planets (classical count excluding dwarf planets) + PlanetCount = 8 + + # Expected list of planet names in order from the Sun + PlanetNames = @('Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune') +} diff --git a/tests/Advanced/Planets/Planets.Tests.ps1 b/tests/Advanced/Planets/Planets.Tests.ps1 new file mode 100644 index 00000000..488a186e --- /dev/null +++ b/tests/Advanced/Planets/Planets.Tests.ps1 @@ -0,0 +1,30 @@ +<# +.SYNOPSIS + Pester tests for planet-related functions. +.DESCRIPTION + This script loads settings from Planets.Settings.ps1 and validates functions that return planet data. +.NOTES + Ensure that functions like Get-PlanetCount and Get-PlanetNames are available (e.g. from your module). +#> + +# Dot-source the settings file to import $PlanetsSettings +. "$PSScriptRoot\Planets.Settings.ps1" + +Describe 'Planets Module Tests' { + + Context 'Planet Count' { + It 'Should return the expected number of planets' { + $expectedCount = $PlanetsSettings.PlanetCount + $actualCount = $PlanetsSettings.PlanetNames.Count + $actualCount | Should -Be $expectedCount + } + } + + Context 'Planet Names' { + It 'Should return the expected list of planet names' { + $expectedNames = $PlanetsSettings.PlanetNames + $actualNames = $PlanetsSettings.PlanetNames + $actualNames | Should -BeExactly $expectedNames + } + } +} diff --git a/tests/Simple/Get-Emoji.Tests.ps1 b/tests/Simple/Get-Emoji.Tests.ps1 new file mode 100644 index 00000000..fdbf208d --- /dev/null +++ b/tests/Simple/Get-Emoji.Tests.ps1 @@ -0,0 +1,49 @@ +Describe 'Get-Emoji' { + Context 'Lookup by whole name' { + It 'Returns 🌵 (cactus)' { + Get-Emoji -Name cactus | Should -Be '🌵' + } + + It 'Returns 🦒 (giraffe)' { + Get-Emoji -Name giraffe | Should -Be '🦒' + } + } + + Context 'Lookup by wildcard' { + Context 'by prefix' { + BeforeAll { + $emojis = Get-Emoji -Name pen* + } + + It 'Returns ✏️ (pencil)' { + $emojis | Should -Contain '✏️' + } + + It 'Returns 🐧 (penguin)' { + $emojis | Should -Contain '🐧' + } + + It 'Returns 😔 (pensive)' { + $emojis | Should -Contain '😔' + } + } + + Context 'by contains' { + BeforeAll { + $emojis = Get-Emoji -Name *smiling* + } + + It 'Returns 🙂 (slightly smiling face)' { + $emojis | Should -Contain '🙂' + } + + It 'Returns 😁 (beaming face with smiling eyes)' { + $emojis | Should -Contain '😁' + } + + It 'Returns 😊 (smiling face with smiling eyes)' { + $emojis | Should -Contain '😊' + } + } + } +} From 0ec58d02b3844f4aee5dfadd30341951774b18fa Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 10 Feb 2025 21:07:02 +0100 Subject: [PATCH 003/176] Refactor main script to streamline test execution and remove obsolete test functions --- scripts/{test.ps1 => Helpers.psm1} | 20 +-- scripts/main.ps1 | 213 +++++++++-------------------- 2 files changed, 66 insertions(+), 167 deletions(-) rename scripts/{test.ps1 => Helpers.psm1} (60%) diff --git a/scripts/test.ps1 b/scripts/Helpers.psm1 similarity index 60% rename from scripts/test.ps1 rename to scripts/Helpers.psm1 index 38f3e239..317664f0 100644 --- a/scripts/test.ps1 +++ b/scripts/Helpers.psm1 @@ -1,6 +1,4 @@ -# Run all files with the name like *.Containers.ps1 in the current directory recursively. - -function Get-PesterContainer { +function Get-PesterContainer { param( [string] $Path ) @@ -37,19 +35,3 @@ function Get-PesterConfiguration { } New-PesterConfiguration -Hashtable $config } - - -$Path = 'C:\Repos\GitHub\PSModule\Action\Invoke-Pester\tests\Advanced' -$containers = Get-PesterContainer -Path $Path - - -$Configuration = Get-PesterConfiguration -Path $Path -$Configuration.Run.Container = $containers - -$Configuration.Run.Container.Value - - -$Configuration | Convertto-Json -Depth 100 | Clip -$Configuration.Container | ConvertTo-Json -Depth 100 | Clip - -Invoke-Pester -Configuration $Configuration diff --git a/scripts/main.ps1 b/scripts/main.ps1 index df2155d3..06271931 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -1,30 +1,7 @@ [CmdletBinding()] param() -LogGroup 'Loading inputs' { - $codeToTest = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath $env:GITHUB_ACTION_INPUT_Path - if (-not (Test-Path -Path $codeToTest)) { - throw "Path [$codeToTest] does not exist." - } - - if (-not (Test-Path -Path $env:GITHUB_ACTION_INPUT_TestsPath)) { - throw "Path [$env:GITHUB_ACTION_INPUT_TestsPath] does not exist." - } - - [pscustomobject]@{ - CodeToTest = $codeToTest - TestsPath = $env:GITHUB_ACTION_INPUT_TestsPath - StackTraceVerbosity = $env:GITHUB_ACTION_INPUT_StackTraceVerbosity - Verbosity = $env:GITHUB_ACTION_INPUT_Verbosity - } | Format-List -} - -############################################################################################ - -$moduleName = Split-Path -Path $Path -Leaf -$testSourceCode = $TestType -eq 'SourceCode' -$testModule = $TestType -eq 'Module' -$moduleTestsPath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath $TestsPath +Import-Module "$PSScriptRoot/Helpers.psm1" LogGroup 'Get test kit versions' { $PSSAModule = Get-PSResource -Name PSScriptAnalyzer -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 @@ -37,127 +14,67 @@ LogGroup 'Get test kit versions' { } | Format-List } -LogGroup 'Add test - Common - PSScriptAnalyzer' { - $containers = @() - $PSSATestsPath = Join-Path -Path $PSScriptRoot -ChildPath '..\tests\PSScriptAnalyzer' - $settingsFileName = if ($testModule) { 'Settings.Module.psd1' } else { 'Settings.SourceCode.psd1' } - $settingsFilePath = Join-Path -Path $PSSATestsPath -ChildPath $settingsFileName - $containerParams = @{ - Path = Join-Path $PSSATestsPath 'PSScriptAnalyzer.Tests.ps1' - Data = @{ - Path = $Path - SettingsFilePath = $settingsFilePath - Debug = $false - Verbose = $false - } - } - Write-Host ($containerParams | ConvertTo-Json) - $containers += New-PesterContainer @containerParams -} - -LogGroup 'Add test - Common - PSModule' { - $containerParams = @{ - Path = Join-Path -Path $PSScriptRoot -ChildPath '..\tests\PSModule\Common.Tests.ps1' - Data = @{ - Path = $Path - Debug = $false - Verbose = $false - } - } - Write-Host ($containerParams | ConvertTo-Json) - $containers += New-PesterContainer @containerParams -} - -if ($testModule) { - LogGroup 'Add test - Module - PSModule' { - $containerParams = @{ - Path = Join-Path -Path $PSScriptRoot -ChildPath '..\tests\PSModule\Module.Tests.ps1' - Data = @{ - Path = $Path - Debug = $false - Verbose = $false - } - } - Write-Host ($containerParams | ConvertTo-Json) - $containers += New-PesterContainer @containerParams - } -} - -if ($testSourceCode) { - LogGroup 'Add test - SourceCode - PSModule' { - $containerParams = @{ - Path = Join-Path -Path $PSScriptRoot -ChildPath '..\tests\PSModule\SourceCode.Tests.ps1' - Data = @{ - Path = $Path - TestsPath = $moduleTestsPath - Debug = $false - Verbose = $false - } - } - Write-Host ($containerParams | ConvertTo-Json) - $containers += New-PesterContainer @containerParams - } -} - -if ($testModule) { - if (Test-Path -Path $moduleTestsPath) { - LogGroup "Add test - Module - $moduleName" { - $containerParams = @{ - Path = $moduleTestsPath - } - Write-Host ($containerParams | ConvertTo-Json) - $containers += New-PesterContainer @containerParams - } - } else { - Write-GitHubWarning "⚠️ No tests found - [$moduleTestsPath]" - } -} - -LogGroup 'Pester config' { - $pesterParams = @{ - Configuration = @{ - Run = @{ - Path = $Path - Container = $containers - PassThru = $true - } - TestResult = @{ - Enabled = $testModule - OutputFormat = 'NUnitXml' - OutputPath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'outputs\Test-Report.xml' - TestSuiteName = 'Unit tests' - } - CodeCoverage = @{ - Enabled = $testModule - OutputPath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'outputs\CodeCoverage-Report.xml' - OutputFormat = 'JaCoCo' - OutputEncoding = 'UTF8' - CoveragePercentTarget = 75 - } - Output = @{ - CIFormat = 'Auto' - StackTraceVerbosity = $StackTraceVerbosity - Verbosity = $Verbosity - } - } - } - Write-Host ($pesterParams | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) -} - -$testResults = Invoke-Pester @pesterParams - -LogGroup 'Test results' { - $testResults | Format-List - $failedTests = [int]$testResults.FailedCount - - if (($failedTests -gt 0) -or ($testResults.Result -ne 'Passed')) { - Write-GitHubError "❌ Some [$failedTests] tests failed." - } - if ($failedTests -eq 0) { - Write-GitHubNotice '✅ All tests passed.' - } - - Set-GitHubOutput -Name 'results' -Value $testResults -} - -exit $failedTests +$Path = '\tests\Advanced' +$containers = Get-PesterContainer -Path $Path + +$Configuration = Get-PesterConfiguration -Path $Path +$Configuration.Run.Container = $containers + +$Configuration.Run.Container.Value + + +$Configuration | ConvertTo-Json -Depth 100 | Clip +$Configuration.Container | ConvertTo-Json -Depth 100 | Clip + +Invoke-Pester -Configuration $Configuration + + + +# LogGroup 'Pester config' { +# $pesterParams = @{ +# Configuration = @{ +# Run = @{ +# Path = $Path +# Container = $containers +# PassThru = $true +# } +# TestResult = @{ +# Enabled = $testModule +# OutputFormat = 'NUnitXml' +# OutputPath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'outputs\Test-Report.xml' +# TestSuiteName = 'Unit tests' +# } +# CodeCoverage = @{ +# Enabled = $testModule +# OutputPath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'outputs\CodeCoverage-Report.xml' +# OutputFormat = 'JaCoCo' +# OutputEncoding = 'UTF8' +# CoveragePercentTarget = 75 +# } +# Output = @{ +# CIFormat = 'Auto' +# StackTraceVerbosity = $StackTraceVerbosity +# Verbosity = $Verbosity +# } +# } +# } +# Write-Host ($pesterParams | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) +# } + +# $testResults = Invoke-Pester @pesterParams + +# LogGroup 'Test results' { +# $testResults | Format-List +# $failedTests = [int]$testResults.FailedCount + +# if (($failedTests -gt 0) -or ($testResults.Result -ne 'Passed')) { +# Write-GitHubError "❌ Some [$failedTests] tests failed." +# } +# if ($failedTests -eq 0) { +# Write-GitHubNotice '✅ All tests passed.' +# } + +# Set-GitHubOutput -Name 'results' -Value $testResults +# } + +# exit $failedTests From 5ceb0e6cdb906a95747c19a4bc6eb6029e83a833 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 10 Feb 2025 21:09:16 +0100 Subject: [PATCH 004/176] Add installation of Pester module in main script for testing framework setup --- scripts/main.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 06271931..dc5d2bf6 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -3,6 +3,8 @@ param() Import-Module "$PSScriptRoot/Helpers.psm1" +Install-PSResource -Name Pester -Force -Verbose:$false + LogGroup 'Get test kit versions' { $PSSAModule = Get-PSResource -Name PSScriptAnalyzer -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 $pesterModule = Get-PSResource -Name Pester -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 From 70179836ad508f43d8db1b76398f7a3f4867ad78 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 10 Feb 2025 21:09:40 +0100 Subject: [PATCH 005/176] Add installation of PSScriptAnalyzer module alongside Pester in main script --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index dc5d2bf6..306a26f9 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -3,7 +3,7 @@ param() Import-Module "$PSScriptRoot/Helpers.psm1" -Install-PSResource -Name Pester -Force -Verbose:$false +Install-PSResource -Name Pester, PSScriptAnalyzer -Force -Verbose:$false LogGroup 'Get test kit versions' { $PSSAModule = Get-PSResource -Name PSScriptAnalyzer -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 From b1146aa9d02be8e233b788445613de9e6524fede Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 10 Feb 2025 21:20:17 +0100 Subject: [PATCH 006/176] Remove force option from PSScriptAnalyzer installation in main script --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 306a26f9..f95107cd 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -3,7 +3,7 @@ param() Import-Module "$PSScriptRoot/Helpers.psm1" -Install-PSResource -Name Pester, PSScriptAnalyzer -Force -Verbose:$false +Install-PSResource -Name Pester, PSScriptAnalyzer -Verbose:$false LogGroup 'Get test kit versions' { $PSSAModule = Get-PSResource -Name PSScriptAnalyzer -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 From 2917ff50b545ae0b1da7ae543700c136862f4c1d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 12:51:22 +0100 Subject: [PATCH 007/176] Enhance Pester configuration and streamline main script for improved test execution --- action.yml | 230 ++++++++++++++++++++++++++++++- scripts/Pester.Configuration.ps1 | 66 +++++++-- scripts/main.ps1 | 89 ++++++++++-- 3 files changed, 363 insertions(+), 22 deletions(-) diff --git a/action.yml b/action.yml index 673a6858..a7728ca0 100644 --- a/action.yml +++ b/action.yml @@ -1,10 +1,193 @@ name: Invoke-Pester -description: Runs test based on PowerShell. +description: Runs test, using Pester and PowerShell. author: PSModule branding: icon: check-square color: gray-dark +inputs: + Run_Path: + description: | + Directories to be searched for tests, paths directly to test files, or combination of both. + required: false + Run_ExcludePath: + description: | + Directories or files to be excluded from the run. + required: false + Run_ScriptBlock: + description: | + ScriptBlocks containing tests to be executed. + required: false + Run_Container: + description: | + ContainerInfo objects containing tests to be executed. + required: false + Run_TestExtension: + description: | + Filter used to identify test files. + required: false + Run_Exit: + description: | + Exit with non-zero exit code when the test run fails. Exit code is always set to `$LASTEXITCODE` even when this option is `$false`. + When used together with Throw, throwing an exception is preferred. + required: false + Run_Throw: + description: | + Throw an exception when test run fails. When used together with Exit, throwing an exception is preferred. + required: false + Run_PassThru: + description: | + Return result object to the pipeline after finishing the test run. + required: false + Run_SkipRun: + description: | + Runs the discovery phase but skips run. Use it with PassThru to get object populated with all tests. + required: false + Run_SkipRemainingOnFailure: + description: | + Skips remaining tests after failure for selected scope, options are None, Run, Container and Block. + required: false + Filter_Tag: + description: | + Tags of Describe, Context or It to be run. + required: false + Filter_ExcludeTag: + description: | + Tags of Describe, Context or It to be excluded from the run. + required: false + Filter_Line: + description: | + Filter by file and scriptblock start line, useful to run parsed tests programmatically to avoid problems with expanded names. + Example: 'C:\tests\file1.Tests.ps1:37' + required: false + Filter_ExcludeLine: + description: | + Exclude by file and scriptblock start line, takes precedence over Line. + required: false + Filter_FullName: + description: | + Full name of test with -like wildcards, joined by dot. Example: '*.describe Get-Item.test1' + required: false + CodeCoverage_Enabled: + description: | + Enable CodeCoverage. + required: false + CodeCoverage_OutputFormat: + description: | + Format to use for code coverage report. Possible values: JaCoCo, CoverageGutters, Cobertura + required: false + CodeCoverage_OutputPath: + description: | + Path relative to the current directory where code coverage report is saved. + required: false + CodeCoverage_OutputEncoding: + description: | + Encoding of the output file. + required: false + CodeCoverage_Path: + description: | + Directories or files to be used for code coverage, by default the Path(s) from general settings are used, unless overridden here. + required: false + CodeCoverage_ExcludeTests: + description: | + Exclude tests from code coverage. This uses the TestFilter from general configuration. + required: false + CodeCoverage_RecursePaths: + description: | + Will recurse through directories in the Path option. + required: false + CodeCoverage_CoveragePercentTarget: + description: | + Target percent of code coverage that you want to achieve. + required: false + CodeCoverage_UseBreakpoints: + description: | + EXPERIMENTAL: When false, use Profiler based tracer to do CodeCoverage instead of using breakpoints. + required: false + CodeCoverage_SingleHitBreakpoints: + description: | + Remove breakpoint when it is hit. + required: false + TestResult_Enabled: + description: | + Enable TestResult. + required: false + TestResult_OutputFormat: + description: | + Format to use for test result report. Possible values: NUnitXml, NUnit2.5, NUnit3 or JUnitXml + required: false + TestResult_OutputPath: + description: | + Path relative to the current directory where test result report is saved. + required: false + TestResult_OutputEncoding: + description: | + Encoding of the output file. + required: false + TestResult_TestSuiteName: + description: | + Set the name assigned to the root 'test-suite' element. + required: false + Should_ErrorAction: + description: | + Controls if Should throws on error. Use 'Stop' to throw on error, or 'Continue' to fail at the end of the test. + required: false + Debug_ShowFullErrors: + description: | + Show full errors including Pester internal stack. This property is deprecated, and if set to true it will override Output.StackTraceVerbosity to 'Full'. + required: false + Debug_WriteDebugMessages: + description: | + Write Debug messages to screen. + required: false + Debug_WriteDebugMessagesFrom: + description: | + Write Debug messages from a given source, WriteDebugMessages must be set to true for this to work. + You can use like wildcards to get messages from multiple sources, as well as * to get everything. + required: false + Debug_ShowNavigationMarkers: + description: | + Write paths after every block and test, for easy navigation in VSCode. + required: false + Debug_ReturnRawResultObject: + description: | + Returns unfiltered result object, this is for development only. Do not rely on this object for additional properties, + non-public properties will be renamed without previous notice. + required: false + Output_Verbosity: + description: | + The verbosity of output, options are None, Normal, Detailed and Diagnostic. + required: false + Output_StackTraceVerbosity: + description: | + The verbosity of stacktrace output, options are None, FirstLine, Filtered and Full. + required: false + Output_CIFormat: + description: | + The CI format of error output in build logs, options are None, Auto, AzureDevops and GithubActions. + required: false + Output_CILogLevel: + description: | + The CI log level in build logs, options are Error and Warning. + required: false + Output_RenderMode: + description: | + The mode used to render console output, options are Auto, Ansi, ConsoleColor and Plaintext. + required: false + TestDrive_Enabled: + description: | + Enable TestDrive. + required: false + TestRegistry_Enabled: + description: | + Enable TestRegistry. + required: false + ConfigurationFilePath: + description: | + Path to the configuration file. + required: false + default: '${{ github.workspace }}/.github/pester.settings.ps1' + outputs: result: description: If the tests passed. @@ -16,6 +199,51 @@ runs: - name: Invoke-Pester uses: PSModule/GitHub-Script@v1 id: test + env: + GITHUB_ACTION_INPUT_Run_Path: ${{ inputs.Run_Path }} + GITHUB_ACTION_INPUT_Run_ExcludePath: ${{ inputs.Run_ExcludePath }} + GITHUB_ACTION_INPUT_Run_ScriptBlock: ${{ inputs.Run_ScriptBlock }} + GITHUB_ACTION_INPUT_Run_Container: ${{ inputs.Run_Container }} + GITHUB_ACTION_INPUT_Run_TestExtension: ${{ inputs.Run_TestExtension }} + GITHUB_ACTION_INPUT_Run_Exit: ${{ inputs.Run_Exit }} + GITHUB_ACTION_INPUT_Run_Throw: ${{ inputs.Run_Throw }} + GITHUB_ACTION_INPUT_Run_PassThru: ${{ inputs.Run_PassThru }} + GITHUB_ACTION_INPUT_Run_SkipRun: ${{ inputs.Run_SkipRun }} + GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure: ${{ inputs.Run_SkipRemainingOnFailure }} + GITHUB_ACTION_INPUT_Filter_Tag: ${{ inputs.Filter_Tag }} + GITHUB_ACTION_INPUT_Filter_ExcludeTag: ${{ inputs.Filter_ExcludeTag }} + GITHUB_ACTION_INPUT_Filter_Line: ${{ inputs.Filter_Line }} + GITHUB_ACTION_INPUT_Filter_ExcludeLine: ${{ inputs.Filter_ExcludeLine }} + GITHUB_ACTION_INPUT_Filter_FullName: ${{ inputs.Filter_FullName }} + GITHUB_ACTION_INPUT_CodeCoverage_Enabled: ${{ inputs.CodeCoverage_Enabled }} + GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat: ${{ inputs.CodeCoverage_OutputFormat }} + GITHUB_ACTION_INPUT_CodeCoverage_OutputPath: ${{ inputs.CodeCoverage_OutputPath }} + GITHUB_ACTION_INPUT_CodeCoverage_OutputEncoding: ${{ inputs.CodeCoverage_OutputEncoding }} + GITHUB_ACTION_INPUT_CodeCoverage_Path: ${{ inputs.CodeCoverage_Path }} + GITHUB_ACTION_INPUT_CodeCoverage_ExcludeTests: ${{ inputs.CodeCoverage_ExcludeTests }} + GITHUB_ACTION_INPUT_CodeCoverage_RecursePaths: ${{ inputs.CodeCoverage_RecursePaths }} + GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget: ${{ inputs.CodeCoverage_CoveragePercentTarget }} + GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints: ${{ inputs.CodeCoverage_UseBreakpoints }} + GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints: ${{ inputs.CodeCoverage_SingleHitBreakpoints }} + GITHUB_ACTION_INPUT_TestResult_Enabled: ${{ inputs.TestResult_Enabled }} + GITHUB_ACTION_INPUT_TestResult_OutputFormat: ${{ inputs.TestResult_OutputFormat }} + GITHUB_ACTION_INPUT_TestResult_OutputPath: ${{ inputs.TestResult_OutputPath }} + GITHUB_ACTION_INPUT_TestResult_OutputEncoding: ${{ inputs.TestResult_OutputEncoding }} + GITHUB_ACTION_INPUT_TestResult_TestSuiteName: ${{ inputs.TestResult_TestSuiteName }} + GITHUB_ACTION_INPUT_Should_ErrorAction: ${{ inputs.Should_ErrorAction }} + GITHUB_ACTION_INPUT_Debug_ShowFullErrors: ${{ inputs.Debug_ShowFullErrors }} + GITHUB_ACTION_INPUT_Debug_WriteDebugMessages: ${{ inputs.Debug_WriteDebugMessages }} + GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom: ${{ inputs.Debug_WriteDebugMessagesFrom }} + GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers: ${{ inputs.Debug_ShowNavigationMarkers }} + GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject: ${{ inputs.Debug_ReturnRawResultObject }} + GITHUB_ACTION_INPUT_Output_Verbosity: ${{ inputs.Output_Verbosity }} + GITHUB_ACTION_INPUT_Output_StackTraceVerbosity: ${{ inputs.Output_StackTraceVerbosity }} + GITHUB_ACTION_INPUT_Output_CIFormat: ${{ inputs.Output_CIFormat }} + GITHUB_ACTION_INPUT_Output_CILogLevel: ${{ inputs.Output_CILogLevel }} + GITHUB_ACTION_INPUT_Output_RenderMode: ${{ inputs.Output_RenderMode }} + GITHUB_ACTION_INPUT_TestDrive_Enabled: ${{ inputs.TestDrive_Enabled }} + GITHUB_ACTION_INPUT_TestRegistry_Enabled: ${{ inputs.TestRegistry_Enabled }} + GITHUB_ACTION_INPUT_ConfigurationFilePath: ${{ inputs.ConfigurationFilePath }} with: ShowOutput: true Script: | diff --git a/scripts/Pester.Configuration.ps1 b/scripts/Pester.Configuration.ps1 index da8c8a85..e751b494 100644 --- a/scripts/Pester.Configuration.ps1 +++ b/scripts/Pester.Configuration.ps1 @@ -1,24 +1,70 @@ @{ Run = @{ - Path = $Path - PassThru = $true + Path = $Path + ExcludePath = @() + ScriptBlock = @() + Container = @() + TestExtension = @( + '.Tests.ps1' + ) + Exit = $false + Throw = $false + PassThru = $true + SkipRun = $false + SkipRemainingOnFailure = 'None' } - TestResult = @{ - Enabled = $true - OutputFormat = 'NUnitXml' - OutputPath = 'outputs\Test-Report.xml' - TestSuiteName = 'Unit tests' + Filter = @{ + Tag = @() + ExcludeTag = @() + Line = @() + ExcludeLine = @() + FullName = @() } CodeCoverage = @{ Enabled = $true - OutputPath = 'outputs\CodeCoverage-Report.xml' OutputFormat = 'JaCoCo' + OutputPath = 'CodeCoverage-Report.xml' OutputEncoding = 'UTF8' - CoveragePercentTarget = 75 + Path = @() + ExcludeTests = $true + RecursePaths = $true + CoveragePercentTarget = 75.0 + UseBreakpoints = $true + SingleHitBreakpoints = $true + } + TestResult = @{ + Enabled = $true + OutputFormat = 'NUnitXml' + OutputPath = 'outputs\Test-Report.xml' + OutputEncoding = 'UTF8' + TestSuiteName = 'Unit tests' + } + Should = @{ + ErrorAction = 'Stop' + } + Debug = @{ + ShowFullErrors = $false + WriteDebugMessages = $false + WriteDebugMessagesFrom = @( + 'Discovery', + 'Skip', + 'Mock', + 'CodeCoverage' + ) + ShowNavigationMarkers = $false + ReturnRawResultObject = $false } Output = @{ CIFormat = 'Auto' - StackTraceVerbosity = 'Normal' + StackTraceVerbosity = 'Filtered' Verbosity = 'Detailed' + CILogLevel = 'Error' + RenderMode = 'Auto' + } + TestDrive = @{ + Enabled = $true + } + TestRegistry = @{ + Enabled = $true } } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index f95107cd..6cdbe7b8 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -1,9 +1,12 @@ [CmdletBinding()] param() -Import-Module "$PSScriptRoot/Helpers.psm1" +'Pester', 'PSScriptAnalyzer' | ForEach-Object { + Install-PSResource -Name $_ -Verbose:$false -WarningAction SilentlyContinue + Import-Module -Name $_ -Verbose:$false +} -Install-PSResource -Name Pester, PSScriptAnalyzer -Verbose:$false +Import-Module "$PSScriptRoot/Helpers.psm1" LogGroup 'Get test kit versions' { $PSSAModule = Get-PSResource -Name PSScriptAnalyzer -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 @@ -16,19 +19,83 @@ LogGroup 'Get test kit versions' { } | Format-List } -$Path = '\tests\Advanced' -$containers = Get-PesterContainer -Path $Path - -$Configuration = Get-PesterConfiguration -Path $Path -$Configuration.Run.Container = $containers +LogGroup 'Load inputs' { + Get-ChildItem -Path env: | Where-Object { $_.Name -like 'GITHUB_ACTION_INPUT_*' } | ForEach-Object { + $name = $_.Name -replace '^GITHUB_ACTION_INPUT_' + $value = $_.Value + New-Variable -Name $name -Value $value -Force -Scope Script -PassThru + } | Format-Table -AutoSize +} -$Configuration.Run.Container.Value +# $Path = '\tests\Advanced' +# $containers = Get-PesterContainer -Path $Path + +# $Configuration = Get-PesterConfiguration -Path $Path +# $Configuration.Run.Container = $containers + +# $Configuration.Run.Container.Value +# @{ +# Run_Path = $Path +# Run_ExcludePath = @() +# Run_ScriptBlock = @() +# Run_Container = @() +# Run_TestExtension = @( +# '.Tests.ps1' +# ) +# Run_Exit = $false +# Run_Throw = $false +# Run_PassThru = $true +# Run_SkipRun = $false +# Run_SkipRemainingOnFailure = 'None' + +# Filter_Tag = @() +# Filter_ExcludeTag = @() +# Filter_Line = @() +# Filter_ExcludeLine = @() +# Filter_FullName = @() + +# CodeCoverage_Enabled = $true +# CodeCoverage_OutputFormat = 'JaCoCo' +# CodeCoverage_OutputPath = 'CodeCoverage-Report.xml' +# CodeCoverage_OutputEncoding = 'UTF8' +# CodeCoverage_Path = @() +# CodeCoverage_ExcludeTests = $true +# CodeCoverage_RecursePaths = $true +# CodeCoverage_CoveragePercentTarget = 75.0 +# CodeCoverage_UseBreakpoints = $true +# CodeCoverage_SingleHitBreakpoints = $true + +# TestResult_Enabled = $true +# TestResult_OutputFormat = 'NUnitXml' +# TestResult_OutputPath = 'outputs\Test-Report.xml' +# TestResult_OutputEncoding = 'UTF8' +# TestResult_TestSuiteName = 'Unit tests' +# Should_ErrorAction = 'Stop' +# Debug_ShowFullErrors = $false +# Debug_WriteDebugMessages = $false +# Debug_WriteDebugMessagesFrom = @( +# 'Discovery', +# 'Skip', +# 'Mock', +# 'CodeCoverage' +# ) +# Debug_ShowNavigationMarkers = $false +# Debug_ReturnRawResultObject = $false + +# Output_CIFormat = 'Auto' +# Output_StackTraceVerbosity = 'Filtered' +# Output_Verbosity = 'Detailed' +# Output_CILogLevel = 'Error' +# Output_RenderMode = 'Auto' +# TestDrive_Enabled = $true +# TestRegistry_Enabled = $true +# } -$Configuration | ConvertTo-Json -Depth 100 | Clip -$Configuration.Container | ConvertTo-Json -Depth 100 | Clip +# $Configuration | ConvertTo-Json -Depth 100 | Clip +# $Configuration.Container | ConvertTo-Json -Depth 100 | Clip -Invoke-Pester -Configuration $Configuration +# Invoke-Pester -Configuration $Configuration From 1c1da05b73fabb0c0e90fe2661480ae51f877585 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 12:54:55 +0100 Subject: [PATCH 008/176] Add TrustRepository option to Install-PSResource for Pester and PSScriptAnalyzer --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 6cdbe7b8..9c8979c6 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -2,7 +2,7 @@ param() 'Pester', 'PSScriptAnalyzer' | ForEach-Object { - Install-PSResource -Name $_ -Verbose:$false -WarningAction SilentlyContinue + Install-PSResource -Name $_ -Verbose:$false -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery Import-Module -Name $_ -Verbose:$false } From 67c2d29feaba12927d7ae8d18c4c02b93c7e2eae Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 12:58:37 +0100 Subject: [PATCH 009/176] Refactor GitHub Actions workflow and update main script output format; remove obsolete README for tests --- .github/workflows/Action-Test.yml | 22 +++++++++++++++++----- scripts/main.ps1 | 2 +- tests/README.md | 3 --- 3 files changed, 18 insertions(+), 9 deletions(-) delete mode 100644 tests/README.md diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index 6ff2f13e..b97e96a9 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -17,16 +17,28 @@ permissions: pull-requests: read jobs: - ActionTestBasic: - name: Action-Test - [Basic] + ActionTestSimple: + name: Action-Test - [Simple] runs-on: ubuntu-latest steps: # Need to check out as part of the test, as its a local action - name: Checkout repo uses: actions/checkout@v4 - - name: Action-Test + - name: Action-Test [Simple] uses: ./ with: - working-directory: ./tests - subject: PSModule + Run_Path: tests/Simple + + ActionTestAdvanced: + name: Action-Test - [Advanced] + runs-on: ubuntu-latest + steps: + # Need to check out as part of the test, as its a local action + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Action-Test [Advanced] + uses: ./ + with: + Run_Path: tests/Advanced diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 9c8979c6..c7ea7571 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -24,7 +24,7 @@ LogGroup 'Load inputs' { $name = $_.Name -replace '^GITHUB_ACTION_INPUT_' $value = $_.Value New-Variable -Name $name -Value $value -Force -Scope Script -PassThru - } | Format-Table -AutoSize + } | Format-List } # $Path = '\tests\Advanced' diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index a570e4d1..00000000 --- a/tests/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Placeholder for tests - -Location for tests of the action. From ef3778f3a90a817e4356a260d361465834b6e6d5 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 13:00:33 +0100 Subject: [PATCH 010/176] Update variable output format in main script to use Select-Object for improved clarity --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index c7ea7571..33a1bc2d 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -24,7 +24,7 @@ LogGroup 'Load inputs' { $name = $_.Name -replace '^GITHUB_ACTION_INPUT_' $value = $_.Value New-Variable -Name $name -Value $value -Force -Scope Script -PassThru - } | Format-List + } | Select-Object Name,Value | Format-List } # $Path = '\tests\Advanced' From 56847e116187adc9f97c4338fd359e92353101bc Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 13:04:51 +0100 Subject: [PATCH 011/176] Refactor input handling in main script to use a hashtable for improved organization and clarity --- scripts/main.ps1 | 53 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 33a1bc2d..f5a0d304 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -20,11 +20,54 @@ LogGroup 'Get test kit versions' { } LogGroup 'Load inputs' { - Get-ChildItem -Path env: | Where-Object { $_.Name -like 'GITHUB_ACTION_INPUT_*' } | ForEach-Object { - $name = $_.Name -replace '^GITHUB_ACTION_INPUT_' - $value = $_.Value - New-Variable -Name $name -Value $value -Force -Scope Script -PassThru - } | Select-Object Name,Value | Format-List + $params = @{ + Run_Path = $env:GITHUB_ACTION_INPUT_Run_Path + Run_ExcludePath = $env:GITHUB_ACTION_INPUT_Run_ExcludePath + Run_ScriptBlock = $env:GITHUB_ACTION_INPUT_Run_ScriptBlock + Run_Container = $env:GITHUB_ACTION_INPUT_Run_Container + Run_TestExtension = $env:GITHUB_ACTION_INPUT_Run_TestExtension + Run_Exit = $env:GITHUB_ACTION_INPUT_Run_Exit + Run_Throw = $env:GITHUB_ACTION_INPUT_Run_Throw + Run_PassThru = $env:GITHUB_ACTION_INPUT_Run_PassThru + Run_SkipRun = $env:GITHUB_ACTION_INPUT_Run_SkipRun + Run_SkipRemainingOnFailure = $env:GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure + Filter_Tag = $env:GITHUB_ACTION_INPUT_Filter_Tag + Filter_ExcludeTag = $env:GITHUB_ACTION_INPUT_Filter_ExcludeTag + Filter_Line = $env:GITHUB_ACTION_INPUT_Filter_Line + Filter_ExcludeLine = $env:GITHUB_ACTION_INPUT_Filter_ExcludeLine + Filter_FullName = $env:GITHUB_ACTION_INPUT_Filter_FullName + CodeCoverage_Enabled = $env:GITHUB_ACTION_INPUT_CodeCoverage_Enabled + CodeCoverage_OutputFormat = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat + CodeCoverage_OutputPath = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputPath + CodeCoverage_OutputEncoding = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputEncoding + CodeCoverage_Path = $env:GITHUB_ACTION_INPUT_CodeCoverage_Path + CodeCoverage_ExcludeTests = $env:GITHUB_ACTION_INPUT_CodeCoverage_ExcludeTests + CodeCoverage_RecursePaths = $env:GITHUB_ACTION_INPUT_CodeCoverage_RecursePaths + CodeCoverage_CoveragePercentTarget = $env:GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget + CodeCoverage_UseBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints + CodeCoverage_SingleHitBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints + TestResult_Enabled = $env:GITHUB_ACTION_INPUT_TestResult_Enabled + TestResult_OutputFormat = $env:GITHUB_ACTION_INPUT_TestResult_OutputFormat + TestResult_OutputPath = $env:GITHUB_ACTION_INPUT_TestResult_OutputPath + TestResult_OutputEncoding = $env:GITHUB_ACTION_INPUT_TestResult_OutputEncoding + TestResult_TestSuiteName = $env:GITHUB_ACTION_INPUT_TestResult_TestSuiteName + Should_ErrorAction = $env:GITHUB_ACTION_INPUT_Should_ErrorAction + Debug_ShowFullErrors = $env:GITHUB_ACTION_INPUT_Debug_ShowFullErrors + Debug_WriteDebugMessages = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessages + Debug_WriteDebugMessagesFrom = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom + Debug_ShowNavigationMarkers = $env:GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers + Debug_ReturnRawResultObject = $env:GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject + Output_Verbosity = $env:GITHUB_ACTION_INPUT_Output_Verbosity + Output_StackTraceVerbosity = $env:GITHUB_ACTION_INPUT_Output_StackTraceVerbosity + Output_CIFormat = $env:GITHUB_ACTION_INPUT_Output_CIFormat + Output_CILogLevel = $env:GITHUB_ACTION_INPUT_Output_CILogLevel + Output_RenderMode = $env:GITHUB_ACTION_INPUT_Output_RenderMode + TestDrive_Enabled = $env:GITHUB_ACTION_INPUT_TestDrive_Enabled + TestRegistry_Enabled = $env:GITHUB_ACTION_INPUT_TestRegistry_Enabled + ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath + } + + [pscustomobject]$params | Format-Table } # $Path = '\tests\Advanced' From bd042cac5f638572983705cef9701b860e26497c Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 14:07:04 +0100 Subject: [PATCH 012/176] Change output format in main script from Format-Table to Format-List for improved readability --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index f5a0d304..ab4f570e 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -67,7 +67,7 @@ LogGroup 'Load inputs' { ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath } - [pscustomobject]$params | Format-Table + [pscustomobject]$params | Format-List } # $Path = '\tests\Advanced' From df270626ca731d82d9f79c121a70f5397e2d81b9 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 14:21:41 +0100 Subject: [PATCH 013/176] Improve output formatting in main script to exclude empty parameters for better clarity --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index ab4f570e..59c7df8f 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -67,7 +67,7 @@ LogGroup 'Load inputs' { ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath } - [pscustomobject]$params | Format-List + [pscustomobject]($params.GetEnumerator() | Where-Object { $_.Value }) | Format-List } # $Path = '\tests\Advanced' From c1ccc0617eeda34c842b06bd19aa25bfbad943d0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 14:32:44 +0100 Subject: [PATCH 014/176] Add Merge-Hashtable function and refactor input handling for improved organization --- scripts/Helpers.psm1 | 57 ++++++++++++++++++ scripts/main.ps1 | 136 ++++++++++++++++++++++++++++--------------- 2 files changed, 147 insertions(+), 46 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 317664f0..b39c8bd3 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -35,3 +35,60 @@ function Get-PesterConfiguration { } New-PesterConfiguration -Hashtable $config } + +function Merge-Hashtable { + <# + .SYNOPSIS + Merge two hashtables, with the second hashtable overriding the first + + .DESCRIPTION + Merge two hashtables, with the second hashtable overriding the first + + .EXAMPLE + $Main = [ordered]@{ + Action = '' + Location = 'Main' + Name = 'Main' + Mode = 'Main' + } + $Override1 = [ordered]@{ + Action = '' + Location = '' + Name = 'Override1' + Mode = 'Override1' + } + $Override2 = [ordered]@{ + Action = '' + Location = '' + Name = 'Override1' + Mode = 'Override2' + } + Merge-Hashtables -Main $Main -Overrides $Override1, $Override2 + #> + [OutputType([Hashtable])] + [Alias('Merge-Hashtables')] + [CmdletBinding()] + param ( + # Main hashtable + [Parameter(Mandatory)] + [object] $Main, + + # Hashtable with overrides. + # Providing a list of overrides will apply them in order. + # Last write wins. + [Parameter(Mandatory)] + [object[]] $Overrides + ) + $Output = $Main.Clone() + foreach ($Override in $Overrides) { + foreach ($Key in $Override.Keys) { + if (($Output.Keys) -notcontains $Key) { + $Output.$Key = $Override.$Key + } + if ($Override.item($Key) | IsNotNullOrEmpty) { + $Output.$Key = $Override.$Key + } + } + } + return $Output +} diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 59c7df8f..8e3c590a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -20,56 +20,100 @@ LogGroup 'Get test kit versions' { } LogGroup 'Load inputs' { - $params = @{ - Run_Path = $env:GITHUB_ACTION_INPUT_Run_Path - Run_ExcludePath = $env:GITHUB_ACTION_INPUT_Run_ExcludePath - Run_ScriptBlock = $env:GITHUB_ACTION_INPUT_Run_ScriptBlock - Run_Container = $env:GITHUB_ACTION_INPUT_Run_Container - Run_TestExtension = $env:GITHUB_ACTION_INPUT_Run_TestExtension - Run_Exit = $env:GITHUB_ACTION_INPUT_Run_Exit - Run_Throw = $env:GITHUB_ACTION_INPUT_Run_Throw - Run_PassThru = $env:GITHUB_ACTION_INPUT_Run_PassThru - Run_SkipRun = $env:GITHUB_ACTION_INPUT_Run_SkipRun - Run_SkipRemainingOnFailure = $env:GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure - Filter_Tag = $env:GITHUB_ACTION_INPUT_Filter_Tag - Filter_ExcludeTag = $env:GITHUB_ACTION_INPUT_Filter_ExcludeTag - Filter_Line = $env:GITHUB_ACTION_INPUT_Filter_Line - Filter_ExcludeLine = $env:GITHUB_ACTION_INPUT_Filter_ExcludeLine - Filter_FullName = $env:GITHUB_ACTION_INPUT_Filter_FullName - CodeCoverage_Enabled = $env:GITHUB_ACTION_INPUT_CodeCoverage_Enabled - CodeCoverage_OutputFormat = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat - CodeCoverage_OutputPath = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputPath - CodeCoverage_OutputEncoding = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputEncoding - CodeCoverage_Path = $env:GITHUB_ACTION_INPUT_CodeCoverage_Path - CodeCoverage_ExcludeTests = $env:GITHUB_ACTION_INPUT_CodeCoverage_ExcludeTests - CodeCoverage_RecursePaths = $env:GITHUB_ACTION_INPUT_CodeCoverage_RecursePaths - CodeCoverage_CoveragePercentTarget = $env:GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget - CodeCoverage_UseBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints - CodeCoverage_SingleHitBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints - TestResult_Enabled = $env:GITHUB_ACTION_INPUT_TestResult_Enabled - TestResult_OutputFormat = $env:GITHUB_ACTION_INPUT_TestResult_OutputFormat - TestResult_OutputPath = $env:GITHUB_ACTION_INPUT_TestResult_OutputPath - TestResult_OutputEncoding = $env:GITHUB_ACTION_INPUT_TestResult_OutputEncoding - TestResult_TestSuiteName = $env:GITHUB_ACTION_INPUT_TestResult_TestSuiteName - Should_ErrorAction = $env:GITHUB_ACTION_INPUT_Should_ErrorAction - Debug_ShowFullErrors = $env:GITHUB_ACTION_INPUT_Debug_ShowFullErrors - Debug_WriteDebugMessages = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessages - Debug_WriteDebugMessagesFrom = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom - Debug_ShowNavigationMarkers = $env:GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers - Debug_ReturnRawResultObject = $env:GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject - Output_Verbosity = $env:GITHUB_ACTION_INPUT_Output_Verbosity - Output_StackTraceVerbosity = $env:GITHUB_ACTION_INPUT_Output_StackTraceVerbosity - Output_CIFormat = $env:GITHUB_ACTION_INPUT_Output_CIFormat - Output_CILogLevel = $env:GITHUB_ACTION_INPUT_Output_CILogLevel - Output_RenderMode = $env:GITHUB_ACTION_INPUT_Output_RenderMode - TestDrive_Enabled = $env:GITHUB_ACTION_INPUT_TestDrive_Enabled - TestRegistry_Enabled = $env:GITHUB_ACTION_INPUT_TestRegistry_Enabled - ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath + $configInputs = @{ + Run = @{ + Path = $env:GITHUB_ACTION_INPUT_Run_Path + ExcludePath = $env:GITHUB_ACTION_INPUT_Run_ExcludePath + ScriptBlock = $env:GITHUB_ACTION_INPUT_Run_ScriptBlock + Container = $env:GITHUB_ACTION_INPUT_Run_Container + TestExtension = $env:GITHUB_ACTION_INPUT_Run_TestExtension + Exit = $env:GITHUB_ACTION_INPUT_Run_Exit + Throw = $env:GITHUB_ACTION_INPUT_Run_Throw + PassThru = $env:GITHUB_ACTION_INPUT_Run_PassThru + SkipRun = $env:GITHUB_ACTION_INPUT_Run_SkipRun + SkipRemainingOnFailure = $env:GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure + } + Filter = @{ + Tag = $env:GITHUB_ACTION_INPUT_Filter_Tag + ExcludeTag = $env:GITHUB_ACTION_INPUT_Filter_ExcludeTag + Line = $env:GITHUB_ACTION_INPUT_Filter_Line + ExcludeLine = $env:GITHUB_ACTION_INPUT_Filter_ExcludeLine + FullName = $env:GITHUB_ACTION_INPUT_Filter_FullName + } + CodeCoverage = @{ + Enabled = $env:GITHUB_ACTION_INPUT_CodeCoverage_Enabled + OutputFormat = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat + OutputPath = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputPath + OutputEncoding = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputEncoding + Path = $env:GITHUB_ACTION_INPUT_CodeCoverage_Path + ExcludeTests = $env:GITHUB_ACTION_INPUT_CodeCoverage_ExcludeTests + RecursePaths = $env:GITHUB_ACTION_INPUT_CodeCoverage_RecursePaths + CoveragePercentTarget = $env:GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget + UseBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints + SingleHitBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints + } + TestResult = @{ + Enabled = $env:GITHUB_ACTION_INPUT_TestResult_Enabled + OutputFormat = $env:GITHUB_ACTION_INPUT_TestResult_OutputFormat + OutputPath = $env:GITHUB_ACTION_INPUT_TestResult_OutputPath + OutputEncoding = $env:GITHUB_ACTION_INPUT_TestResult_OutputEncoding + TestSuiteName = $env:GITHUB_ACTION_INPUT_TestResult_TestSuiteName + } + Should = @{ + ErrorAction = $env:GITHUB_ACTION_INPUT_Should_ErrorAction + } + Debug = @{ + ShowFullErrors = $env:GITHUB_ACTION_INPUT_Debug_ShowFullErrors + WriteDebugMessages = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessages + WriteDebugMessagesFrom = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom + ShowNavigationMarkers = $env:GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers + ReturnRawResultObject = $env:GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject + } + Output = @{ + Verbosity = $env:GITHUB_ACTION_INPUT_Output_Verbosity + StackTraceVerbosity = $env:GITHUB_ACTION_INPUT_Output_StackTraceVerbosity + CIFormat = $env:GITHUB_ACTION_INPUT_Output_CIFormat + CILogLevel = $env:GITHUB_ACTION_INPUT_Output_CILogLevel + RenderMode = $env:GITHUB_ACTION_INPUT_Output_RenderMode + } + TestDrive = @{ + Enabled = $env:GITHUB_ACTION_INPUT_TestDrive_Enabled + } + TestRegistry = @{ + Enabled = $env:GITHUB_ACTION_INPUT_TestRegistry_Enabled + } } + $otherInputs = @{ + ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath + } + + $inputs = $configInputs + $otherInputs + + [pscustomobject]($inputs.GetEnumerator() | Where-Object { $_.Value }) | Format-List +} + +LogGroup 'Load configuration - Defaults' { + $defaultConfiguration = . (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') + [pscustomobject]$defaultConfiguration | Format-List +} - [pscustomobject]($params.GetEnumerator() | Where-Object { $_.Value }) | Format-List +LogGroup 'Load configuration - Custom settings file' { + $customConfiguration = . (Join-Path $PSScriptRoot -ChildPath $env:GITHUB_ACTION_INPUT_ConfigurationFilePath) + [pscustomobject]$customConfiguration | Format-List } +LogGroup 'Load configuration - Action overrides' { + [pscustomobject]$configInputs | Format-List +} + +LogGroup 'Load configuration - Result' { + $configuration = Merge-Hashtable -Main $defaultConfiguration -Overrides $customConfiguration, $configInputs + [pscustomobject]$Configuration | Format-List +} +$defaultConfiguration = . (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') + + + # $Path = '\tests\Advanced' # $containers = Get-PesterContainer -Path $Path From 94ab3ae7f090ce6e5f203643372812a4ce0f2770 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 14:39:10 +0100 Subject: [PATCH 015/176] Refactor configuration loading to improve path handling and ensure valid file checks --- scripts/main.ps1 | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 8e3c590a..d39668c6 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -93,26 +93,30 @@ LogGroup 'Load inputs' { } LogGroup 'Load configuration - Defaults' { - $defaultConfiguration = . (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') - [pscustomobject]$defaultConfiguration | Format-List + $defaultConfigurationPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') + if (Test-Path -Path $defaultConfigurationPath) { + $defaultConfiguration = . $defaultConfigurationPath + [pscustomobject]$defaultConfiguration | Format-List + } } LogGroup 'Load configuration - Custom settings file' { - $customConfiguration = . (Join-Path $PSScriptRoot -ChildPath $env:GITHUB_ACTION_INPUT_ConfigurationFilePath) - [pscustomobject]$customConfiguration | Format-List + $customConfigurationFilePath = $otherInputs.ConfigurationFilePath + if ($customConfigurationFilePath -and (Test-Path -Path $customConfigurationFilePath)) { + $customConfiguration = . $customConfigurationFilePath + [pscustomobject]$customConfiguration | Format-List + } } LogGroup 'Load configuration - Action overrides' { - [pscustomobject]$configInputs | Format-List + $customConfigurationInputs = ($configInputs.GetEnumerator() | Where-Object { $_.Value }) + [pscustomobject]$customConfigurationInputs | Format-List } LogGroup 'Load configuration - Result' { - $configuration = Merge-Hashtable -Main $defaultConfiguration -Overrides $customConfiguration, $configInputs - [pscustomobject]$Configuration | Format-List + $configuration = Merge-Hashtable -Main $defaultConfiguration -Overrides $customConfiguration, $customConfigurationInputs + [pscustomobject]$configuration | Format-List } -$defaultConfiguration = . (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') - - # $Path = '\tests\Advanced' # $containers = Get-PesterContainer -Path $Path From 96eb9fe7bdfb53107ca1136bb2383feb3ca75d3a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 14:51:50 +0100 Subject: [PATCH 016/176] Enhance custom configuration loading by adding file existence check and logging for better debugging --- scripts/main.ps1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index d39668c6..af50a4be 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -102,7 +102,10 @@ LogGroup 'Load configuration - Defaults' { LogGroup 'Load configuration - Custom settings file' { $customConfigurationFilePath = $otherInputs.ConfigurationFilePath - if ($customConfigurationFilePath -and (Test-Path -Path $customConfigurationFilePath)) { + $fileExists = Test-Path -Path $customConfigurationFilePath + Write-Host "Custom configuration file path: $customConfigurationFilePath" + Write-Host "File exists: $fileExists" + if ($customConfigurationFilePath -and $fileExists) { $customConfiguration = . $customConfigurationFilePath [pscustomobject]$customConfiguration | Format-List } From da8fe36e6e6114df1a9abb7c127edcce8199c8ff Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 14:55:12 +0100 Subject: [PATCH 017/176] Initialize default and custom configuration hashtables for improved configuration management --- scripts/main.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index af50a4be..a42751de 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -92,6 +92,9 @@ LogGroup 'Load inputs' { [pscustomobject]($inputs.GetEnumerator() | Where-Object { $_.Value }) | Format-List } +$defaultConfiguration = @{} +$customConfiguration = @{} + LogGroup 'Load configuration - Defaults' { $defaultConfigurationPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') if (Test-Path -Path $defaultConfigurationPath) { From 7f94eed7de7f7cce1be19d1531c618d6af53cc50 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 15:00:19 +0100 Subject: [PATCH 018/176] Refactor output handling in main script to use JSON formatting for better readability and debugging --- scripts/main.ps1 | 113 +++++------------------------------------------ 1 file changed, 12 insertions(+), 101 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index a42751de..73e136c4 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -99,7 +99,7 @@ LogGroup 'Load configuration - Defaults' { $defaultConfigurationPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') if (Test-Path -Path $defaultConfigurationPath) { $defaultConfiguration = . $defaultConfigurationPath - [pscustomobject]$defaultConfiguration | Format-List + Write-Host ($defaultConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } } @@ -110,123 +110,34 @@ LogGroup 'Load configuration - Custom settings file' { Write-Host "File exists: $fileExists" if ($customConfigurationFilePath -and $fileExists) { $customConfiguration = . $customConfigurationFilePath - [pscustomobject]$customConfiguration | Format-List + Write-Host ($customConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } } LogGroup 'Load configuration - Action overrides' { $customConfigurationInputs = ($configInputs.GetEnumerator() | Where-Object { $_.Value }) - [pscustomobject]$customConfigurationInputs | Format-List + Write-Host ($customConfigurationInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } LogGroup 'Load configuration - Result' { $configuration = Merge-Hashtable -Main $defaultConfiguration -Overrides $customConfiguration, $customConfigurationInputs - [pscustomobject]$configuration | Format-List + Write-Host ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } -# $Path = '\tests\Advanced' -# $containers = Get-PesterContainer -Path $Path - -# $Configuration = Get-PesterConfiguration -Path $Path -# $Configuration.Run.Container = $containers - -# $Configuration.Run.Container.Value -# @{ -# Run_Path = $Path -# Run_ExcludePath = @() -# Run_ScriptBlock = @() -# Run_Container = @() -# Run_TestExtension = @( -# '.Tests.ps1' -# ) -# Run_Exit = $false -# Run_Throw = $false -# Run_PassThru = $true -# Run_SkipRun = $false -# Run_SkipRemainingOnFailure = 'None' - -# Filter_Tag = @() -# Filter_ExcludeTag = @() -# Filter_Line = @() -# Filter_ExcludeLine = @() -# Filter_FullName = @() - -# CodeCoverage_Enabled = $true -# CodeCoverage_OutputFormat = 'JaCoCo' -# CodeCoverage_OutputPath = 'CodeCoverage-Report.xml' -# CodeCoverage_OutputEncoding = 'UTF8' -# CodeCoverage_Path = @() -# CodeCoverage_ExcludeTests = $true -# CodeCoverage_RecursePaths = $true -# CodeCoverage_CoveragePercentTarget = 75.0 -# CodeCoverage_UseBreakpoints = $true -# CodeCoverage_SingleHitBreakpoints = $true - -# TestResult_Enabled = $true -# TestResult_OutputFormat = 'NUnitXml' -# TestResult_OutputPath = 'outputs\Test-Report.xml' -# TestResult_OutputEncoding = 'UTF8' -# TestResult_TestSuiteName = 'Unit tests' -# Should_ErrorAction = 'Stop' -# Debug_ShowFullErrors = $false -# Debug_WriteDebugMessages = $false -# Debug_WriteDebugMessagesFrom = @( -# 'Discovery', -# 'Skip', -# 'Mock', -# 'CodeCoverage' -# ) -# Debug_ShowNavigationMarkers = $false -# Debug_ReturnRawResultObject = $false - -# Output_CIFormat = 'Auto' -# Output_StackTraceVerbosity = 'Filtered' -# Output_Verbosity = 'Detailed' -# Output_CILogLevel = 'Error' -# Output_RenderMode = 'Auto' -# TestDrive_Enabled = $true -# TestRegistry_Enabled = $true -# } +LogGroup 'Load containers' { + $containers = Get-PesterContainer -Path $configuration.Run.Path + Write-Host ($containers | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) +} +$configuration.Run.Container = $containers -# $Configuration | ConvertTo-Json -Depth 100 | Clip -# $Configuration.Container | ConvertTo-Json -Depth 100 | Clip +LogGroup 'Run tests' { + $testResults = Invoke-Pester -Configuration $configuration +} # Invoke-Pester -Configuration $Configuration - -# LogGroup 'Pester config' { -# $pesterParams = @{ -# Configuration = @{ -# Run = @{ -# Path = $Path -# Container = $containers -# PassThru = $true -# } -# TestResult = @{ -# Enabled = $testModule -# OutputFormat = 'NUnitXml' -# OutputPath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'outputs\Test-Report.xml' -# TestSuiteName = 'Unit tests' -# } -# CodeCoverage = @{ -# Enabled = $testModule -# OutputPath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'outputs\CodeCoverage-Report.xml' -# OutputFormat = 'JaCoCo' -# OutputEncoding = 'UTF8' -# CoveragePercentTarget = 75 -# } -# Output = @{ -# CIFormat = 'Auto' -# StackTraceVerbosity = $StackTraceVerbosity -# Verbosity = $Verbosity -# } -# } -# } -# Write-Host ($pesterParams | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) -# } - # $testResults = Invoke-Pester @pesterParams # LogGroup 'Test results' { From 39c8bfc4f88610e2688c6646c0c9ee9e494f38d3 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 15:15:30 +0100 Subject: [PATCH 019/176] --- scripts/main.ps1 | 189 ++++++++++++++++++++++++++++++----------------- 1 file changed, 120 insertions(+), 69 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 73e136c4..86b42fe2 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -20,75 +20,53 @@ LogGroup 'Get test kit versions' { } LogGroup 'Load inputs' { - $configInputs = @{ - Run = @{ - Path = $env:GITHUB_ACTION_INPUT_Run_Path - ExcludePath = $env:GITHUB_ACTION_INPUT_Run_ExcludePath - ScriptBlock = $env:GITHUB_ACTION_INPUT_Run_ScriptBlock - Container = $env:GITHUB_ACTION_INPUT_Run_Container - TestExtension = $env:GITHUB_ACTION_INPUT_Run_TestExtension - Exit = $env:GITHUB_ACTION_INPUT_Run_Exit - Throw = $env:GITHUB_ACTION_INPUT_Run_Throw - PassThru = $env:GITHUB_ACTION_INPUT_Run_PassThru - SkipRun = $env:GITHUB_ACTION_INPUT_Run_SkipRun - SkipRemainingOnFailure = $env:GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure - } - Filter = @{ - Tag = $env:GITHUB_ACTION_INPUT_Filter_Tag - ExcludeTag = $env:GITHUB_ACTION_INPUT_Filter_ExcludeTag - Line = $env:GITHUB_ACTION_INPUT_Filter_Line - ExcludeLine = $env:GITHUB_ACTION_INPUT_Filter_ExcludeLine - FullName = $env:GITHUB_ACTION_INPUT_Filter_FullName - } - CodeCoverage = @{ - Enabled = $env:GITHUB_ACTION_INPUT_CodeCoverage_Enabled - OutputFormat = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat - OutputPath = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputPath - OutputEncoding = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputEncoding - Path = $env:GITHUB_ACTION_INPUT_CodeCoverage_Path - ExcludeTests = $env:GITHUB_ACTION_INPUT_CodeCoverage_ExcludeTests - RecursePaths = $env:GITHUB_ACTION_INPUT_CodeCoverage_RecursePaths - CoveragePercentTarget = $env:GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget - UseBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints - SingleHitBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints - } - TestResult = @{ - Enabled = $env:GITHUB_ACTION_INPUT_TestResult_Enabled - OutputFormat = $env:GITHUB_ACTION_INPUT_TestResult_OutputFormat - OutputPath = $env:GITHUB_ACTION_INPUT_TestResult_OutputPath - OutputEncoding = $env:GITHUB_ACTION_INPUT_TestResult_OutputEncoding - TestSuiteName = $env:GITHUB_ACTION_INPUT_TestResult_TestSuiteName - } - Should = @{ - ErrorAction = $env:GITHUB_ACTION_INPUT_Should_ErrorAction - } - Debug = @{ - ShowFullErrors = $env:GITHUB_ACTION_INPUT_Debug_ShowFullErrors - WriteDebugMessages = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessages - WriteDebugMessagesFrom = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom - ShowNavigationMarkers = $env:GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers - ReturnRawResultObject = $env:GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject - } - Output = @{ - Verbosity = $env:GITHUB_ACTION_INPUT_Output_Verbosity - StackTraceVerbosity = $env:GITHUB_ACTION_INPUT_Output_StackTraceVerbosity - CIFormat = $env:GITHUB_ACTION_INPUT_Output_CIFormat - CILogLevel = $env:GITHUB_ACTION_INPUT_Output_CILogLevel - RenderMode = $env:GITHUB_ACTION_INPUT_Output_RenderMode - } - TestDrive = @{ - Enabled = $env:GITHUB_ACTION_INPUT_TestDrive_Enabled - } - TestRegistry = @{ - Enabled = $env:GITHUB_ACTION_INPUT_TestRegistry_Enabled - } - } - $otherInputs = @{ - ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath + $inputs = @{ + Run_Path = $env:GITHUB_ACTION_INPUT_Run_Path + Run_ExcludePath = $env:GITHUB_ACTION_INPUT_Run_ExcludePath + Run_ScriptBlock = $env:GITHUB_ACTION_INPUT_Run_ScriptBlock + Run_Container = $env:GITHUB_ACTION_INPUT_Run_Container + Run_TestExtension = $env:GITHUB_ACTION_INPUT_Run_TestExtension + Run_Exit = $env:GITHUB_ACTION_INPUT_Run_Exit + Run_Throw = $env:GITHUB_ACTION_INPUT_Run_Throw + Run_PassThru = $env:GITHUB_ACTION_INPUT_Run_PassThru + Run_SkipRun = $env:GITHUB_ACTION_INPUT_Run_SkipRun + Run_SkipRemainingOnFailure = $env:GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure + Filter_Tag = $env:GITHUB_ACTION_INPUT_Filter_Tag + Filter_ExcludeTag = $env:GITHUB_ACTION_INPUT_Filter_ExcludeTag + Filter_Line = $env:GITHUB_ACTION_INPUT_Filter_Line + Filter_ExcludeLine = $env:GITHUB_ACTION_INPUT_Filter_ExcludeLine + Filter_FullName = $env:GITHUB_ACTION_INPUT_Filter_FullName + CodeCoverage_Enabled = $env:GITHUB_ACTION_INPUT_CodeCoverage_Enabled + CodeCoverage_OutputFormat = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat + CodeCoverage_OutputPath = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputPath + CodeCoverage_OutputEncoding = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputEncoding + CodeCoverage_Path = $env:GITHUB_ACTION_INPUT_CodeCoverage_Path + CodeCoverage_ExcludeTests = $env:GITHUB_ACTION_INPUT_CodeCoverage_ExcludeTests + CodeCoverage_RecursePaths = $env:GITHUB_ACTION_INPUT_CodeCoverage_RecursePaths + CodeCoverage_CoveragePercentTarget = $env:GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget + CodeCoverage_UseBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints + CodeCoverage_SingleHitBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints + TestResult_Enabled = $env:GITHUB_ACTION_INPUT_TestResult_Enabled + TestResult_OutputFormat = $env:GITHUB_ACTION_INPUT_TestResult_OutputFormat + TestResult_OutputPath = $env:GITHUB_ACTION_INPUT_TestResult_OutputPath + TestResult_OutputEncoding = $env:GITHUB_ACTION_INPUT_TestResult_OutputEncoding + TestResult_TestSuiteName = $env:GITHUB_ACTION_INPUT_TestResult_TestSuiteName + Should_ErrorAction = $env:GITHUB_ACTION_INPUT_Should_ErrorAction + Debug_ShowFullErrors = $env:GITHUB_ACTION_INPUT_Debug_ShowFullErrors + Debug_WriteDebugMessages = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessages + Debug_WriteDebugMessagesFrom = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom + Debug_ShowNavigationMarkers = $env:GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers + Debug_ReturnRawResultObject = $env:GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject + Output_Verbosity = $env:GITHUB_ACTION_INPUT_Output_Verbosity + Output_StackTraceVerbosity = $env:GITHUB_ACTION_INPUT_Output_StackTraceVerbosity + Output_CIFormat = $env:GITHUB_ACTION_INPUT_Output_CIFormat + Output_CILogLevel = $env:GITHUB_ACTION_INPUT_Output_CILogLevel + Output_RenderMode = $env:GITHUB_ACTION_INPUT_Output_RenderMode + TestDrive_Enabled = $env:GITHUB_ACTION_INPUT_TestDrive_Enabled + TestRegistry_Enabled = $env:GITHUB_ACTION_INPUT_TestRegistry_Enabled + ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath } - $inputs = $configInputs + $otherInputs - [pscustomobject]($inputs.GetEnumerator() | Where-Object { $_.Value }) | Format-List } @@ -115,12 +93,85 @@ LogGroup 'Load configuration - Custom settings file' { } LogGroup 'Load configuration - Action overrides' { - $customConfigurationInputs = ($configInputs.GetEnumerator() | Where-Object { $_.Value }) + $customConfigurationInputs = @{ + Run = @{ + Path = $inputs.Run_Path + ExcludePath = $inputs.Run_ExcludePath + ScriptBlock = $inputs.Run_ScriptBlock + Container = $inputs.Run_Container + TestExtension = $inputs.Run_TestExtension + Exit = $inputs.Run_Exit + Throw = $inputs.Run_Throw + PassThru = $inputs.Run_PassThru + SkipRun = $inputs.Run_SkipRun + SkipRemainingOnFailure = $inputs.Run_SkipRemainingOnFailure + } + Filter = @{ + Tag = $inputs.Filter_Tag + ExcludeTag = $inputs.Filter_ExcludeTag + Line = $inputs.Filter_Line + ExcludeLine = $inputs.Filter_ExcludeLine + FullName = $inputs.Filter_FullName + } + CodeCoverage = @{ + Enabled = $inputs.CodeCoverage_Enabled + OutputFormat = $inputs.CodeCoverage_OutputFormat + OutputPath = $inputs.CodeCoverage_OutputPath + OutputEncoding = $inputs.CodeCoverage_OutputEncoding + Path = $inputs.CodeCoverage_Path + ExcludeTests = $inputs.CodeCoverage_ExcludeTests + RecursePaths = $inputs.CodeCoverage_RecursePaths + CoveragePercentTarget = $inputs.CodeCoverage_CoveragePercentTarget + UseBreakpoints = $inputs.CodeCoverage_UseBreakpoints + SingleHitBreakpoints = $inputs.CodeCoverage_SingleHitBreakpoints + } + TestResult = @{ + Enabled = $inputs.TestResult_Enabled + OutputFormat = $inputs.TestResult_OutputFormat + OutputPath = $inputs.TestResult_OutputPath + OutputEncoding = $inputs.TestResult_OutputEncoding + TestSuiteName = $inputs.TestResult_TestSuiteName + } + Should = @{ + ErrorAction = $inputs.Should_ErrorAction + } + Debug = @{ + ShowFullErrors = $inputs.Debug_ShowFullErrors + WriteDebugMessages = $inputs.Debug_WriteDebugMessages + WriteDebugMessagesFrom = $inputs.Debug_WriteDebugMessagesFrom + ShowNavigationMarkers = $inputs.Debug_ShowNavigationMarkers + ReturnRawResultObject = $inputs.Debug_ReturnRawResultObject + } + Output = @{ + CIFormat = $inputs.Output_CIFormat + StackTraceVerbosity = $inputs.Output_StackTraceVerbosity + Verbosity = $inputs.Output_Verbosity + CILogLevel = $inputs.Output_CILogLevel + RenderMode = $inputs.Output_RenderMode + } + TestDrive = @{ + Enabled = $inputs.TestDrive_Enabled + } + TestRegistry = @{ + Enabled = $inputs.TestRegistry_Enabled + } + } Write-Host ($customConfigurationInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } LogGroup 'Load configuration - Result' { - $configuration = Merge-Hashtable -Main $defaultConfiguration -Overrides $customConfiguration, $customConfigurationInputs + $configuration = @{ + Run = Merge-Hashtable -Main $defaultConfiguration.Run -Overrides $customConfiguration.Run, $customConfigurationInputs.Run + Filter = Merge-Hashtable -Main $defaultConfiguration.Filter -Overrides $customConfiguration.Filter, $customConfigurationInputs.Filter + CodeCoverage = Merge-Hashtable -Main $defaultConfiguration.CodeCoverage -Overrides $customConfiguration.CodeCoverage, $customConfigurationInputs.CodeCoverage + TestResult = Merge-Hashtable -Main $defaultConfiguration.TestResult -Overrides $customConfiguration.TestResult, $customConfigurationInputs.TestResult + Should = Merge-Hashtable -Main $defaultConfiguration.Should -Overrides $customConfiguration.Should, $customConfigurationInputs.Should + Debug = Merge-Hashtable -Main $defaultConfiguration.Debug -Overrides $customConfiguration.Debug, $customConfigurationInputs.Debug + Output = Merge-Hashtable -Main $defaultConfiguration.Output -Overrides $customConfiguration.Output, $customConfigurationInputs.Output + TestDrive = Merge-Hashtable -Main $defaultConfiguration.TestDrive -Overrides $customConfiguration.TestDrive, $customConfigurationInputs.TestDrive + TestRegistry = Merge-Hashtable -Main $defaultConfiguration.TestRegistry -Overrides $customConfiguration.TestRegistry, $customConfigurationInputs.TestRegistry + } + Write-Host ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } From 1a3d959c5c33e756eb0a0abfe0a0483092a0759b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 16:01:30 +0100 Subject: [PATCH 020/176] Improve custom configuration loading by enhancing file existence check and updating output formatting for clarity --- scripts/main.ps1 | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 86b42fe2..74afbc73 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -83,12 +83,14 @@ LogGroup 'Load configuration - Defaults' { LogGroup 'Load configuration - Custom settings file' { $customConfigurationFilePath = $otherInputs.ConfigurationFilePath - $fileExists = Test-Path -Path $customConfigurationFilePath - Write-Host "Custom configuration file path: $customConfigurationFilePath" - Write-Host "File exists: $fileExists" - if ($customConfigurationFilePath -and $fileExists) { - $customConfiguration = . $customConfigurationFilePath - Write-Host ($customConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + Write-Host "Custom configuration file path: [$customConfigurationFilePath]" + if ($customConfigurationFilePath) { + $fileExists = Test-Path -Path $customConfigurationFilePath + Write-Host "File exists: [$fileExists]" + if ($fileExists) { + $customConfiguration = . $customConfigurationFilePath + Write-Host ($customConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + } } } From 16eea34d1ede94cdb37286e28a012ebf630d57b7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 16:04:03 +0100 Subject: [PATCH 021/176] Remove commented-out code for cleaner script and improved readability --- scripts/main.ps1 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 74afbc73..bae724cd 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -188,11 +188,6 @@ LogGroup 'Run tests' { $testResults = Invoke-Pester -Configuration $configuration } -# Invoke-Pester -Configuration $Configuration - - -# $testResults = Invoke-Pester @pesterParams - # LogGroup 'Test results' { # $testResults | Format-List # $failedTests = [int]$testResults.FailedCount From c4b07ec77eb5767337ce21744747a1b9a9d50ea7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 16:05:29 +0100 Subject: [PATCH 022/176] Refactor configuration loading to eliminate redundancy and enhance clarity --- scripts/main.ps1 | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index bae724cd..f01e678a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -161,19 +161,18 @@ LogGroup 'Load configuration - Action overrides' { Write-Host ($customConfigurationInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } +$configuration = @{ + Run = Merge-Hashtable -Main $defaultConfiguration.Run -Overrides $customConfiguration.Run, $customConfigurationInputs.Run + Filter = Merge-Hashtable -Main $defaultConfiguration.Filter -Overrides $customConfiguration.Filter, $customConfigurationInputs.Filter + CodeCoverage = Merge-Hashtable -Main $defaultConfiguration.CodeCoverage -Overrides $customConfiguration.CodeCoverage, $customConfigurationInputs.CodeCoverage + TestResult = Merge-Hashtable -Main $defaultConfiguration.TestResult -Overrides $customConfiguration.TestResult, $customConfigurationInputs.TestResult + Should = Merge-Hashtable -Main $defaultConfiguration.Should -Overrides $customConfiguration.Should, $customConfigurationInputs.Should + Debug = Merge-Hashtable -Main $defaultConfiguration.Debug -Overrides $customConfiguration.Debug, $customConfigurationInputs.Debug + Output = Merge-Hashtable -Main $defaultConfiguration.Output -Overrides $customConfiguration.Output, $customConfigurationInputs.Output + TestDrive = Merge-Hashtable -Main $defaultConfiguration.TestDrive -Overrides $customConfiguration.TestDrive, $customConfigurationInputs.TestDrive + TestRegistry = Merge-Hashtable -Main $defaultConfiguration.TestRegistry -Overrides $customConfiguration.TestRegistry, $customConfigurationInputs.TestRegistry +} LogGroup 'Load configuration - Result' { - $configuration = @{ - Run = Merge-Hashtable -Main $defaultConfiguration.Run -Overrides $customConfiguration.Run, $customConfigurationInputs.Run - Filter = Merge-Hashtable -Main $defaultConfiguration.Filter -Overrides $customConfiguration.Filter, $customConfigurationInputs.Filter - CodeCoverage = Merge-Hashtable -Main $defaultConfiguration.CodeCoverage -Overrides $customConfiguration.CodeCoverage, $customConfigurationInputs.CodeCoverage - TestResult = Merge-Hashtable -Main $defaultConfiguration.TestResult -Overrides $customConfiguration.TestResult, $customConfigurationInputs.TestResult - Should = Merge-Hashtable -Main $defaultConfiguration.Should -Overrides $customConfiguration.Should, $customConfigurationInputs.Should - Debug = Merge-Hashtable -Main $defaultConfiguration.Debug -Overrides $customConfiguration.Debug, $customConfigurationInputs.Debug - Output = Merge-Hashtable -Main $defaultConfiguration.Output -Overrides $customConfiguration.Output, $customConfigurationInputs.Output - TestDrive = Merge-Hashtable -Main $defaultConfiguration.TestDrive -Overrides $customConfiguration.TestDrive, $customConfigurationInputs.TestDrive - TestRegistry = Merge-Hashtable -Main $defaultConfiguration.TestRegistry -Overrides $customConfiguration.TestRegistry, $customConfigurationInputs.TestRegistry - } - Write-Host ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } From 23524f6ca4812ba1882b40bd3a47e8775f10b9d5 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 16:15:49 +0100 Subject: [PATCH 023/176] Refactor custom configuration loading to improve structure and enhance output formatting --- scripts/main.ps1 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index f01e678a..ba638612 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -88,7 +88,18 @@ LogGroup 'Load configuration - Custom settings file' { $fileExists = Test-Path -Path $customConfigurationFilePath Write-Host "File exists: [$fileExists]" if ($fileExists) { - $customConfiguration = . $customConfigurationFilePath + $tmp = . $customConfigurationFilePath + $customConfiguration = @{ + Run = $tmp.Run + Filter = $tmp.Filter + CodeCoverage = $tmp.CodeCoverage + TestResult = $tmp.TestResult + Should = $tmp.Should + Debug = $tmp.Debug + Output = $tmp.Output + TestDrive = $tmp.TestDrive + TestRegistry = $tmp.TestRegistry + } Write-Host ($customConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } } From 1fdb49048d401001affba890bc13562456f71fdc Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 16:18:55 +0100 Subject: [PATCH 024/176] Refactor configuration loading to streamline variable assignments and enhance readability --- scripts/main.ps1 | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index ba638612..51c0a762 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -172,16 +172,26 @@ LogGroup 'Load configuration - Action overrides' { Write-Host ($customConfigurationInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } +$run = Merge-Hashtable -Main $defaultConfiguration.Run -Overrides $customConfiguration.Run, $customConfigurationInputs.Run +$filter = Merge-Hashtable -Main $defaultConfiguration.Filter -Overrides $customConfiguration.Filter, $customConfigurationInputs.Filter +$codeCoverage = Merge-Hashtable -Main $defaultConfiguration.CodeCoverage -Overrides $customConfiguration.CodeCoverage, $customConfigurationInputs.CodeCoverage +$testResult = Merge-Hashtable -Main $defaultConfiguration.TestResult -Overrides $customConfiguration.TestResult, $customConfigurationInputs.TestResult +$should = Merge-Hashtable -Main $defaultConfiguration.Should -Overrides $customConfiguration.Should, $customConfigurationInputs.Should +$debug = Merge-Hashtable -Main $defaultConfiguration.Debug -Overrides $customConfiguration.Debug, $customConfigurationInputs.Debug +$output = Merge-Hashtable -Main $defaultConfiguration.Output -Overrides $customConfiguration.Output, $customConfigurationInputs.Output +$testDrive = Merge-Hashtable -Main $defaultConfiguration.TestDrive -Overrides $customConfiguration.TestDrive, $customConfigurationInputs.TestDrive +$testRegistry = Merge-Hashtable -Main $defaultConfiguration.TestRegistry -Overrides $customConfiguration.TestRegistry, $customConfigurationInputs.TestRegistry + $configuration = @{ - Run = Merge-Hashtable -Main $defaultConfiguration.Run -Overrides $customConfiguration.Run, $customConfigurationInputs.Run - Filter = Merge-Hashtable -Main $defaultConfiguration.Filter -Overrides $customConfiguration.Filter, $customConfigurationInputs.Filter - CodeCoverage = Merge-Hashtable -Main $defaultConfiguration.CodeCoverage -Overrides $customConfiguration.CodeCoverage, $customConfigurationInputs.CodeCoverage - TestResult = Merge-Hashtable -Main $defaultConfiguration.TestResult -Overrides $customConfiguration.TestResult, $customConfigurationInputs.TestResult - Should = Merge-Hashtable -Main $defaultConfiguration.Should -Overrides $customConfiguration.Should, $customConfigurationInputs.Should - Debug = Merge-Hashtable -Main $defaultConfiguration.Debug -Overrides $customConfiguration.Debug, $customConfigurationInputs.Debug - Output = Merge-Hashtable -Main $defaultConfiguration.Output -Overrides $customConfiguration.Output, $customConfigurationInputs.Output - TestDrive = Merge-Hashtable -Main $defaultConfiguration.TestDrive -Overrides $customConfiguration.TestDrive, $customConfigurationInputs.TestDrive - TestRegistry = Merge-Hashtable -Main $defaultConfiguration.TestRegistry -Overrides $customConfiguration.TestRegistry, $customConfigurationInputs.TestRegistry + Run = $run + Filter = $filter + CodeCoverage = $codeCoverage + TestResult = $testResult + Should = $should + Debug = $debug + Output = $output + TestDrive = $testDrive + TestRegistry = $testRegistry } LogGroup 'Load configuration - Result' { Write-Host ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) From 28ffb3b31136af0cfa08247670d04ae6d8cddf33 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 16:28:08 +0100 Subject: [PATCH 025/176] Refactor configuration loading to improve variable initialization and enhance clarity --- scripts/main.ps1 | 137 +++++++++++++++++++++++++++-------------------- 1 file changed, 80 insertions(+), 57 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 51c0a762..6b27c25c 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -76,9 +76,20 @@ $customConfiguration = @{} LogGroup 'Load configuration - Defaults' { $defaultConfigurationPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') if (Test-Path -Path $defaultConfigurationPath) { - $defaultConfiguration = . $defaultConfigurationPath + $tmpDefault = . $defaultConfigurationPath Write-Host ($defaultConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } + $defaultConfiguration = @{ + Run = $tmpDefault.Run ?? @{} + Filter = $tmpDefault.Filter ?? @{} + CodeCoverage = $tmpDefault.CodeCoverage ?? @{} + TestResult = $tmpDefault.TestResult ?? @{} + Should = $tmpDefault.Should ?? @{} + Debug = $tmpDefault.Debug ?? @{} + Output = $tmpDefault.Output ?? @{} + TestDrive = $tmpDefault.TestDrive ?? @{} + TestRegistry = $tmpDefault.TestRegistry ?? @{} + } } LogGroup 'Load configuration - Custom settings file' { @@ -88,85 +99,97 @@ LogGroup 'Load configuration - Custom settings file' { $fileExists = Test-Path -Path $customConfigurationFilePath Write-Host "File exists: [$fileExists]" if ($fileExists) { - $tmp = . $customConfigurationFilePath - $customConfiguration = @{ - Run = $tmp.Run - Filter = $tmp.Filter - CodeCoverage = $tmp.CodeCoverage - TestResult = $tmp.TestResult - Should = $tmp.Should - Debug = $tmp.Debug - Output = $tmp.Output - TestDrive = $tmp.TestDrive - TestRegistry = $tmp.TestRegistry - } - Write-Host ($customConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + $tmpCustom = . $customConfigurationFilePath + Write-Host ($tmpCustom | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } } + $customConfiguration = @{ + Run = $tmpCustom.Run ?? @{} + Filter = $tmpCustom.Filter ?? @{} + CodeCoverage = $tmpCustom.CodeCoverage ?? @{} + TestResult = $tmpCustom.TestResult ?? @{} + Should = $tmpCustom.Should ?? @{} + Debug = $tmpCustom.Debug ?? @{} + Output = $tmpCustom.Output ?? @{} + TestDrive = $tmpCustom.TestDrive ?? @{} + TestRegistry = $tmpCustom.TestRegistry ?? @{} + } } LogGroup 'Load configuration - Action overrides' { + $customConfigurationInputs = @{ + Run = @{} + Filter = @{} + CodeCoverage = @{} + TestResult = @{} + Should = @{} + Debug = @{} + Output = @{} + TestDrive = @{} + TestRegistry = @{} + } + $customConfigurationInputs = @{ Run = @{ - Path = $inputs.Run_Path - ExcludePath = $inputs.Run_ExcludePath - ScriptBlock = $inputs.Run_ScriptBlock - Container = $inputs.Run_Container - TestExtension = $inputs.Run_TestExtension - Exit = $inputs.Run_Exit - Throw = $inputs.Run_Throw - PassThru = $inputs.Run_PassThru - SkipRun = $inputs.Run_SkipRun - SkipRemainingOnFailure = $inputs.Run_SkipRemainingOnFailure + Path = $inputs.Run_Path ?? $null + ExcludePath = $inputs.Run_ExcludePath ?? $null + ScriptBlock = $inputs.Run_ScriptBlock ?? $null + Container = $inputs.Run_Container ?? $null + TestExtension = $inputs.Run_TestExtension ?? $null + Exit = $inputs.Run_Exit ?? $null + Throw = $inputs.Run_Throw ?? $null + PassThru = $inputs.Run_PassThru ?? $null + SkipRun = $inputs.Run_SkipRun ?? $null + SkipRemainingOnFailure = $inputs.Run_SkipRemainingOnFailure ?? $null } Filter = @{ - Tag = $inputs.Filter_Tag - ExcludeTag = $inputs.Filter_ExcludeTag - Line = $inputs.Filter_Line - ExcludeLine = $inputs.Filter_ExcludeLine - FullName = $inputs.Filter_FullName + Tag = $inputs.Filter_Tag ?? $null + ExcludeTag = $inputs.Filter_ExcludeTag ?? $null + Line = $inputs.Filter_Line ?? $null + ExcludeLine = $inputs.Filter_ExcludeLine ?? $null + FullName = $inputs.Filter_FullName ?? $null } CodeCoverage = @{ - Enabled = $inputs.CodeCoverage_Enabled - OutputFormat = $inputs.CodeCoverage_OutputFormat - OutputPath = $inputs.CodeCoverage_OutputPath - OutputEncoding = $inputs.CodeCoverage_OutputEncoding - Path = $inputs.CodeCoverage_Path - ExcludeTests = $inputs.CodeCoverage_ExcludeTests - RecursePaths = $inputs.CodeCoverage_RecursePaths - CoveragePercentTarget = $inputs.CodeCoverage_CoveragePercentTarget - UseBreakpoints = $inputs.CodeCoverage_UseBreakpoints - SingleHitBreakpoints = $inputs.CodeCoverage_SingleHitBreakpoints + Enabled = $inputs.CodeCoverage_Enabled ?? $null + OutputFormat = $inputs.CodeCoverage_OutputFormat ?? $null + OutputPath = $inputs.CodeCoverage_OutputPath ?? $null + OutputEncoding = $inputs.CodeCoverage_OutputEncoding ?? $null + Path = $inputs.CodeCoverage_Path ?? $null + ExcludeTests = $inputs.CodeCoverage_ExcludeTests ?? $null + RecursePaths = $inputs.CodeCoverage_RecursePaths ?? $null + CoveragePercentTarget = $inputs.CodeCoverage_CoveragePercentTarget ?? $null + UseBreakpoints = $inputs.CodeCoverage_UseBreakpoints ?? $null + SingleHitBreakpoints = $inputs.CodeCoverage_SingleHitBreakpoints ?? $null } TestResult = @{ - Enabled = $inputs.TestResult_Enabled - OutputFormat = $inputs.TestResult_OutputFormat - OutputPath = $inputs.TestResult_OutputPath - OutputEncoding = $inputs.TestResult_OutputEncoding - TestSuiteName = $inputs.TestResult_TestSuiteName + Enabled = $inputs.TestResult_Enabled ?? $null + OutputFormat = $inputs.TestResult_OutputFormat ?? $null + OutputPath = $inputs.TestResult_OutputPath ?? $null + OutputEncoding = $inputs.TestResult_OutputEncoding ?? $null + TestSuiteName = $inputs.TestResult_TestSuiteName ?? $null } Should = @{ - ErrorAction = $inputs.Should_ErrorAction + ErrorAction = $inputs.Should_ErrorAction ?? $null } Debug = @{ - ShowFullErrors = $inputs.Debug_ShowFullErrors - WriteDebugMessages = $inputs.Debug_WriteDebugMessages - WriteDebugMessagesFrom = $inputs.Debug_WriteDebugMessagesFrom - ShowNavigationMarkers = $inputs.Debug_ShowNavigationMarkers - ReturnRawResultObject = $inputs.Debug_ReturnRawResultObject + ShowFullErrors = $inputs.Debug_ShowFullErrors ?? $null + WriteDebugMessages = $inputs.Debug_WriteDebugMessages ?? $null + WriteDebugMessagesFrom = $inputs.Debug_WriteDebugMessagesFrom ?? $null + ShowNavigationMarkers = $inputs.Debug_ShowNavigationMarkers ?? $null + ReturnRawResultObject = $inputs.Debug_ReturnRawResultObject ?? $null } Output = @{ - CIFormat = $inputs.Output_CIFormat - StackTraceVerbosity = $inputs.Output_StackTraceVerbosity - Verbosity = $inputs.Output_Verbosity - CILogLevel = $inputs.Output_CILogLevel - RenderMode = $inputs.Output_RenderMode + CIFormat = $inputs.Output_CIFormat ?? $null + StackTraceVerbosity = $inputs.Output_StackTraceVerbosity ?? $null + Verbosity = $inputs.Output_Verbosity ?? $null + CILogLevel = $inputs.Output_CILogLevel ?? $null + RenderMode = $inputs.Output_RenderMode ?? $null } TestDrive = @{ - Enabled = $inputs.TestDrive_Enabled + Enabled = $inputs.TestDrive_Enabled ?? $null } TestRegistry = @{ - Enabled = $inputs.TestRegistry_Enabled + Enabled = $inputs.TestRegistry_Enabled ?? $null } } Write-Host ($customConfigurationInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) From fa5bc1f53978755ee93cf99a7925170f41f85a73 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 16:34:56 +0100 Subject: [PATCH 026/176] Refactor configuration loading to simplify variable assignments and enhance clarity --- scripts/main.ps1 | 129 +++++++++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 55 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 6b27c25c..36520769 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -114,84 +114,103 @@ LogGroup 'Load configuration - Custom settings file' { TestDrive = $tmpCustom.TestDrive ?? @{} TestRegistry = $tmpCustom.TestRegistry ?? @{} } -} -LogGroup 'Load configuration - Action overrides' { - $customConfigurationInputs = @{ - Run = @{} - Filter = @{} - CodeCoverage = @{} - TestResult = @{} - Should = @{} - Debug = @{} - Output = @{} - TestDrive = @{} - TestRegistry = @{} + foreach ($section in $customConfiguration.Keys) { + $filteredProperties = @{} + + foreach ($property in $customConfiguration[$section].Keys) { + $value = $customConfiguration[$section][$property] + if ($Value) { + $filteredProperties[$property] = $Value + } + } + + if ($filteredProperties.Count -gt 0) { + $customConfigurationInputs[$section] = $filteredProperties + } } +} +LogGroup 'Load configuration - Action overrides' { $customConfigurationInputs = @{ Run = @{ - Path = $inputs.Run_Path ?? $null - ExcludePath = $inputs.Run_ExcludePath ?? $null - ScriptBlock = $inputs.Run_ScriptBlock ?? $null - Container = $inputs.Run_Container ?? $null - TestExtension = $inputs.Run_TestExtension ?? $null - Exit = $inputs.Run_Exit ?? $null - Throw = $inputs.Run_Throw ?? $null - PassThru = $inputs.Run_PassThru ?? $null - SkipRun = $inputs.Run_SkipRun ?? $null - SkipRemainingOnFailure = $inputs.Run_SkipRemainingOnFailure ?? $null + Path = $inputs.Run_Path + ExcludePath = $inputs.Run_ExcludePath + ScriptBlock = $inputs.Run_ScriptBlock + Container = $inputs.Run_Container + TestExtension = $inputs.Run_TestExtension + Exit = $inputs.Run_Exit + Throw = $inputs.Run_Throw + PassThru = $inputs.Run_PassThru + SkipRun = $inputs.Run_SkipRun + SkipRemainingOnFailure = $inputs.Run_SkipRemainingOnFailure } Filter = @{ - Tag = $inputs.Filter_Tag ?? $null - ExcludeTag = $inputs.Filter_ExcludeTag ?? $null - Line = $inputs.Filter_Line ?? $null - ExcludeLine = $inputs.Filter_ExcludeLine ?? $null - FullName = $inputs.Filter_FullName ?? $null + Tag = $inputs.Filter_Tag + ExcludeTag = $inputs.Filter_ExcludeTag + Line = $inputs.Filter_Line + ExcludeLine = $inputs.Filter_ExcludeLine + FullName = $inputs.Filter_FullName } CodeCoverage = @{ - Enabled = $inputs.CodeCoverage_Enabled ?? $null - OutputFormat = $inputs.CodeCoverage_OutputFormat ?? $null - OutputPath = $inputs.CodeCoverage_OutputPath ?? $null - OutputEncoding = $inputs.CodeCoverage_OutputEncoding ?? $null - Path = $inputs.CodeCoverage_Path ?? $null - ExcludeTests = $inputs.CodeCoverage_ExcludeTests ?? $null - RecursePaths = $inputs.CodeCoverage_RecursePaths ?? $null - CoveragePercentTarget = $inputs.CodeCoverage_CoveragePercentTarget ?? $null - UseBreakpoints = $inputs.CodeCoverage_UseBreakpoints ?? $null - SingleHitBreakpoints = $inputs.CodeCoverage_SingleHitBreakpoints ?? $null + Enabled = $inputs.CodeCoverage_Enabled + OutputFormat = $inputs.CodeCoverage_OutputFormat + OutputPath = $inputs.CodeCoverage_OutputPath + OutputEncoding = $inputs.CodeCoverage_OutputEncoding + Path = $inputs.CodeCoverage_Path + ExcludeTests = $inputs.CodeCoverage_ExcludeTests + RecursePaths = $inputs.CodeCoverage_RecursePaths + CoveragePercentTarget = $inputs.CodeCoverage_CoveragePercentTarget + UseBreakpoints = $inputs.CodeCoverage_UseBreakpoints + SingleHitBreakpoints = $inputs.CodeCoverage_SingleHitBreakpoints } TestResult = @{ - Enabled = $inputs.TestResult_Enabled ?? $null - OutputFormat = $inputs.TestResult_OutputFormat ?? $null - OutputPath = $inputs.TestResult_OutputPath ?? $null - OutputEncoding = $inputs.TestResult_OutputEncoding ?? $null - TestSuiteName = $inputs.TestResult_TestSuiteName ?? $null + Enabled = $inputs.TestResult_Enabled + OutputFormat = $inputs.TestResult_OutputFormat + OutputPath = $inputs.TestResult_OutputPath + OutputEncoding = $inputs.TestResult_OutputEncoding + TestSuiteName = $inputs.TestResult_TestSuiteName } Should = @{ - ErrorAction = $inputs.Should_ErrorAction ?? $null + ErrorAction = $inputs.Should_ErrorAction } Debug = @{ - ShowFullErrors = $inputs.Debug_ShowFullErrors ?? $null - WriteDebugMessages = $inputs.Debug_WriteDebugMessages ?? $null - WriteDebugMessagesFrom = $inputs.Debug_WriteDebugMessagesFrom ?? $null - ShowNavigationMarkers = $inputs.Debug_ShowNavigationMarkers ?? $null - ReturnRawResultObject = $inputs.Debug_ReturnRawResultObject ?? $null + ShowFullErrors = $inputs.Debug_ShowFullErrors + WriteDebugMessages = $inputs.Debug_WriteDebugMessages + WriteDebugMessagesFrom = $inputs.Debug_WriteDebugMessagesFrom + ShowNavigationMarkers = $inputs.Debug_ShowNavigationMarkers + ReturnRawResultObject = $inputs.Debug_ReturnRawResultObject } Output = @{ - CIFormat = $inputs.Output_CIFormat ?? $null - StackTraceVerbosity = $inputs.Output_StackTraceVerbosity ?? $null - Verbosity = $inputs.Output_Verbosity ?? $null - CILogLevel = $inputs.Output_CILogLevel ?? $null - RenderMode = $inputs.Output_RenderMode ?? $null + CIFormat = $inputs.Output_CIFormat + StackTraceVerbosity = $inputs.Output_StackTraceVerbosity + Verbosity = $inputs.Output_Verbosity + CILogLevel = $inputs.Output_CILogLevel + RenderMode = $inputs.Output_RenderMode } TestDrive = @{ - Enabled = $inputs.TestDrive_Enabled ?? $null + Enabled = $inputs.TestDrive_Enabled } TestRegistry = @{ - Enabled = $inputs.TestRegistry_Enabled ?? $null + Enabled = $inputs.TestRegistry_Enabled + } + } + + foreach ($section in $customConfigurationInputs.Keys) { + $filteredProperties = @{} + + foreach ($property in $customConfigurationInputs[$section].Keys) { + $value = $customConfigurationInputs[$section][$property] + if ($Value) { + $filteredProperties[$property] = $Value + } + } + + if ($filteredProperties.Count -gt 0) { + $customConfigurationInputs[$section] = $filteredProperties } } + Write-Host ($customConfigurationInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } From 77be6219589cf98e9764b2224987cdd9c9195053 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 16:40:24 +0100 Subject: [PATCH 027/176] Refactor Merge-Hashtable function to simplify null or empty check for override items --- scripts/Helpers.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index b39c8bd3..f3b193e7 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -85,7 +85,7 @@ function Merge-Hashtable { if (($Output.Keys) -notcontains $Key) { $Output.$Key = $Override.$Key } - if ($Override.item($Key) | IsNotNullOrEmpty) { + if ($Override.item($Key)) { $Output.$Key = $Override.$Key } } From 0686bae408261004bde2b1ac1e021ff63e5daba9 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 16:47:53 +0100 Subject: [PATCH 028/176] Fix variable reference in configuration loading to ensure correct output --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 36520769..7d6fbb48 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -77,7 +77,7 @@ LogGroup 'Load configuration - Defaults' { $defaultConfigurationPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') if (Test-Path -Path $defaultConfigurationPath) { $tmpDefault = . $defaultConfigurationPath - Write-Host ($defaultConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + Write-Host ($tmpDefault | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } $defaultConfiguration = @{ Run = $tmpDefault.Run ?? @{} From acb56d4f8485218b21207d12878dd4ab3ec44b00 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 17:06:10 +0100 Subject: [PATCH 029/176] Refactor configuration loading to improve clarity and streamline custom action inputs handling --- scripts/main.ps1 | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 7d6fbb48..44eb6e0f 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -70,14 +70,13 @@ LogGroup 'Load inputs' { [pscustomobject]($inputs.GetEnumerator() | Where-Object { $_.Value }) | Format-List } -$defaultConfiguration = @{} $customConfiguration = @{} +$customActionInputs = @{} LogGroup 'Load configuration - Defaults' { $defaultConfigurationPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') if (Test-Path -Path $defaultConfigurationPath) { $tmpDefault = . $defaultConfigurationPath - Write-Host ($tmpDefault | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } $defaultConfiguration = @{ Run = $tmpDefault.Run ?? @{} @@ -90,6 +89,7 @@ LogGroup 'Load configuration - Defaults' { TestDrive = $tmpDefault.TestDrive ?? @{} TestRegistry = $tmpDefault.TestRegistry ?? @{} } + Write-Host ($defaultConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } LogGroup 'Load configuration - Custom settings file' { @@ -100,10 +100,9 @@ LogGroup 'Load configuration - Custom settings file' { Write-Host "File exists: [$fileExists]" if ($fileExists) { $tmpCustom = . $customConfigurationFilePath - Write-Host ($tmpCustom | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } } - $customConfiguration = @{ + $tmpCustomConfiguration = @{ Run = $tmpCustom.Run ?? @{} Filter = $tmpCustom.Filter ?? @{} CodeCoverage = $tmpCustom.CodeCoverage ?? @{} @@ -115,24 +114,25 @@ LogGroup 'Load configuration - Custom settings file' { TestRegistry = $tmpCustom.TestRegistry ?? @{} } - foreach ($section in $customConfiguration.Keys) { + foreach ($section in $tmpCustomConfiguration.Keys) { $filteredProperties = @{} - foreach ($property in $customConfiguration[$section].Keys) { - $value = $customConfiguration[$section][$property] + foreach ($property in $tmpCustomConfiguration[$section].Keys) { + $value = $tmpCustomConfiguration[$section][$property] if ($Value) { $filteredProperties[$property] = $Value } } if ($filteredProperties.Count -gt 0) { - $customConfigurationInputs[$section] = $filteredProperties + $customConfiguration[$section] = $filteredProperties } } + Write-Host ($customConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } LogGroup 'Load configuration - Action overrides' { - $customConfigurationInputs = @{ + $customConfigurationInputMap = @{ Run = @{ Path = $inputs.Run_Path ExcludePath = $inputs.Run_ExcludePath @@ -196,33 +196,33 @@ LogGroup 'Load configuration - Action overrides' { } } - foreach ($section in $customConfigurationInputs.Keys) { + foreach ($section in $customConfigurationInputMap.Keys) { $filteredProperties = @{} - foreach ($property in $customConfigurationInputs[$section].Keys) { - $value = $customConfigurationInputs[$section][$property] + foreach ($property in $customConfigurationInputMap[$section].Keys) { + $value = $customConfigurationInputMap[$section][$property] if ($Value) { $filteredProperties[$property] = $Value } } if ($filteredProperties.Count -gt 0) { - $customConfigurationInputs[$section] = $filteredProperties + $customActionInputs[$section] = $filteredProperties } } - Write-Host ($customConfigurationInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + Write-Host ($customActionInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } -$run = Merge-Hashtable -Main $defaultConfiguration.Run -Overrides $customConfiguration.Run, $customConfigurationInputs.Run -$filter = Merge-Hashtable -Main $defaultConfiguration.Filter -Overrides $customConfiguration.Filter, $customConfigurationInputs.Filter -$codeCoverage = Merge-Hashtable -Main $defaultConfiguration.CodeCoverage -Overrides $customConfiguration.CodeCoverage, $customConfigurationInputs.CodeCoverage -$testResult = Merge-Hashtable -Main $defaultConfiguration.TestResult -Overrides $customConfiguration.TestResult, $customConfigurationInputs.TestResult -$should = Merge-Hashtable -Main $defaultConfiguration.Should -Overrides $customConfiguration.Should, $customConfigurationInputs.Should -$debug = Merge-Hashtable -Main $defaultConfiguration.Debug -Overrides $customConfiguration.Debug, $customConfigurationInputs.Debug -$output = Merge-Hashtable -Main $defaultConfiguration.Output -Overrides $customConfiguration.Output, $customConfigurationInputs.Output -$testDrive = Merge-Hashtable -Main $defaultConfiguration.TestDrive -Overrides $customConfiguration.TestDrive, $customConfigurationInputs.TestDrive -$testRegistry = Merge-Hashtable -Main $defaultConfiguration.TestRegistry -Overrides $customConfiguration.TestRegistry, $customConfigurationInputs.TestRegistry +$run = Merge-Hashtable -Main $defaultConfiguration.Run -Overrides $customConfiguration.Run, $customActionInputs.Run +$filter = Merge-Hashtable -Main $defaultConfiguration.Filter -Overrides $customConfiguration.Filter, $customActionInputs.Filter +$codeCoverage = Merge-Hashtable -Main $defaultConfiguration.CodeCoverage -Overrides $customConfiguration.CodeCoverage, $customActionInputs.CodeCoverage +$testResult = Merge-Hashtable -Main $defaultConfiguration.TestResult -Overrides $customConfiguration.TestResult, $customActionInputs.TestResult +$should = Merge-Hashtable -Main $defaultConfiguration.Should -Overrides $customConfiguration.Should, $customActionInputs.Should +$debug = Merge-Hashtable -Main $defaultConfiguration.Debug -Overrides $customConfiguration.Debug, $customActionInputs.Debug +$output = Merge-Hashtable -Main $defaultConfiguration.Output -Overrides $customConfiguration.Output, $customActionInputs.Output +$testDrive = Merge-Hashtable -Main $defaultConfiguration.TestDrive -Overrides $customConfiguration.TestDrive, $customActionInputs.TestDrive +$testRegistry = Merge-Hashtable -Main $defaultConfiguration.TestRegistry -Overrides $customConfiguration.TestRegistry, $customActionInputs.TestRegistry $configuration = @{ Run = $run From b0ba6661030bdaa5a3ecc6d50e59e429de923843 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 17:08:45 +0100 Subject: [PATCH 030/176] Refactor configuration loading to simplify assignment of custom configuration and action inputs --- scripts/main.ps1 | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 44eb6e0f..e8ba2370 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -124,9 +124,7 @@ LogGroup 'Load configuration - Custom settings file' { } } - if ($filteredProperties.Count -gt 0) { - $customConfiguration[$section] = $filteredProperties - } + $customConfiguration[$section] = $filteredProperties } Write-Host ($customConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } @@ -206,9 +204,7 @@ LogGroup 'Load configuration - Action overrides' { } } - if ($filteredProperties.Count -gt 0) { - $customActionInputs[$section] = $filteredProperties - } + $customActionInputs[$section] = $filteredProperties } Write-Host ($customActionInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) From 22741b91827eddb81863e1096f9105381cfa8649 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 17:18:42 +0100 Subject: [PATCH 031/176] Reduce JSON depth in container logging for improved readability --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index e8ba2370..a50bde5a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -237,7 +237,7 @@ LogGroup 'Load configuration - Result' { LogGroup 'Load containers' { $containers = Get-PesterContainer -Path $configuration.Run.Path - Write-Host ($containers | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + Write-Host ($containers | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) } $configuration.Run.Container = $containers From 47454d570dacce182f976496896ce3e558e7df50 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 17:20:42 +0100 Subject: [PATCH 032/176] Reduce JSON depth in container logging for improved readability --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index a50bde5a..86282a15 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -237,7 +237,7 @@ LogGroup 'Load configuration - Result' { LogGroup 'Load containers' { $containers = Get-PesterContainer -Path $configuration.Run.Path - Write-Host ($containers | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) + Write-Host ($containers | ConvertTo-Json -Depth 1 -WarningAction SilentlyContinue) } $configuration.Run.Container = $containers From 8fb23c91da1ee645bbde975513261fdcd095ce32 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 17:28:33 +0100 Subject: [PATCH 033/176] Update configuration paths and streamline container scripts for improved clarity --- .github/workflows/Action-Test.yml | 2 +- tests/Advanced/Animals/Animals.Container.ps1 | 4 +- tests/Advanced/Cars/Cars.Container.ps1 | 4 +- tests/Advanced/Pester.Configuration.ps1 | 59 ++++---------------- tests/Advanced/Planets/Planets.Container.ps1 | 4 +- 5 files changed, 18 insertions(+), 55 deletions(-) diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index b97e96a9..754a8211 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -41,4 +41,4 @@ jobs: - name: Action-Test [Advanced] uses: ./ with: - Run_Path: tests/Advanced + ConfigurationFilePath: tests/Advanced/Pester.Configuration.ps1 diff --git a/tests/Advanced/Animals/Animals.Container.ps1 b/tests/Advanced/Animals/Animals.Container.ps1 index 5bdeb19d..dce74d95 100644 --- a/tests/Advanced/Animals/Animals.Container.ps1 +++ b/tests/Advanced/Animals/Animals.Container.ps1 @@ -1,7 +1,7 @@ @{ - Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 | Select-Object -ExpandProperty FullName Data = @{ - Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 | Select-Object -ExpandProperty FullName Debug = $false Verbose = $false } diff --git a/tests/Advanced/Cars/Cars.Container.ps1 b/tests/Advanced/Cars/Cars.Container.ps1 index 5bdeb19d..dce74d95 100644 --- a/tests/Advanced/Cars/Cars.Container.ps1 +++ b/tests/Advanced/Cars/Cars.Container.ps1 @@ -1,7 +1,7 @@ @{ - Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 | Select-Object -ExpandProperty FullName Data = @{ - Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 | Select-Object -ExpandProperty FullName Debug = $false Verbose = $false } diff --git a/tests/Advanced/Pester.Configuration.ps1 b/tests/Advanced/Pester.Configuration.ps1 index 96ef58a1..ae42025e 100644 --- a/tests/Advanced/Pester.Configuration.ps1 +++ b/tests/Advanced/Pester.Configuration.ps1 @@ -1,55 +1,18 @@ @{ - # Define run settings for Pester Run = @{ - # Include specific test tags. For example, you might tag tests with "Planets", "Animals", or "Cars" - Include = @('Planets', 'Animals', 'Cars') - - # Exclude tests with certain tags (e.g., integration tests that are not run on every build) - Exclude = @('Integration') - - # Configure parallel test execution to speed up test runs. - Parallel = @{ - Enabled = $true - MaxRunspaceCount = 4 # Adjust based on your system's capabilities. - } + Path = $PSScriptRoot } - - # Output configuration: adjust verbosity, colors, and format. - Output = @{ - # Toggle verbose output for more details during test runs. - Verbose = $true - - # Define color output for test results (if your terminal supports color). - Color = @{ - Success = 'Green' - Failure = 'Red' - Error = 'Yellow' - } - - # Choose an output format; "Detailed" shows more information than "Short". - Format = 'Detailed' + CodeCoverage = @{ + Enabled = $false } - - # Test-specific settings. - Test = @{ - # Timeout for individual tests, in milliseconds. - Timeout = 60000 + TestResult = @{ + Enabled = $true + OutputPath = 'outputs\AnotherPath.xml' + TestSuiteName = 'Pester' } - - # Code coverage settings. - CodeCoverage = @{ - Enabled = $true - - # Specify what files to include in code coverage calculations. - Include = @('*.ps1', '*.psm1') - - # Exclude test files to prevent them from skewing coverage results. - Exclude = @('*.Tests.ps1', '*Tests.ps1') - - # Output format can be "Cobertura", "Html", etc. - OutputFormat = 'Cobertura' - - # Define where the code coverage report should be saved. - OutputPath = "$PSScriptRoot\coverage.xml" + Output = @{ + CIFormat = 'Auto' + StackTraceVerbosity = 'Filtered' + Verbosity = 'Detailed' } } diff --git a/tests/Advanced/Planets/Planets.Container.ps1 b/tests/Advanced/Planets/Planets.Container.ps1 index 5bdeb19d..dce74d95 100644 --- a/tests/Advanced/Planets/Planets.Container.ps1 +++ b/tests/Advanced/Planets/Planets.Container.ps1 @@ -1,7 +1,7 @@ @{ - Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 | Select-Object -ExpandProperty FullName Data = @{ - Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 | Select-Object -ExpandProperty FullName Debug = $false Verbose = $false } From 68317460276b89244d804a36bd1f6aba1f324440 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 17:32:24 +0100 Subject: [PATCH 034/176] Fix custom configuration file path assignment in main.ps1 script --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 86282a15..8c8b44cf 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -93,7 +93,7 @@ LogGroup 'Load configuration - Defaults' { } LogGroup 'Load configuration - Custom settings file' { - $customConfigurationFilePath = $otherInputs.ConfigurationFilePath + $customConfigurationFilePath = $inputs.ConfigurationFilePath Write-Host "Custom configuration file path: [$customConfigurationFilePath]" if ($customConfigurationFilePath) { $fileExists = Test-Path -Path $customConfigurationFilePath From 12af6a494e7a446b0017e701cb625462ce1f8f48 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 17:34:53 +0100 Subject: [PATCH 035/176] Improve null or empty value checks in custom configuration loading --- scripts/main.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 8c8b44cf..5bc99e71 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -119,7 +119,7 @@ LogGroup 'Load configuration - Custom settings file' { foreach ($property in $tmpCustomConfiguration[$section].Keys) { $value = $tmpCustomConfiguration[$section][$property] - if ($Value) { + if (-not [string]::IsNullOrEmpty($Value)) { $filteredProperties[$property] = $Value } } @@ -199,7 +199,7 @@ LogGroup 'Load configuration - Action overrides' { foreach ($property in $customConfigurationInputMap[$section].Keys) { $value = $customConfigurationInputMap[$section][$property] - if ($Value) { + if (-not [string]::IsNullOrEmpty($Value)) { $filteredProperties[$property] = $Value } } From 5c9d6397a8599bf557c8d9209e8b0c4b928b6d12 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 17:52:24 +0100 Subject: [PATCH 036/176] Improve null or empty value checks in Merge-Hashtable function --- scripts/Helpers.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index f3b193e7..cdad4b34 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -85,7 +85,7 @@ function Merge-Hashtable { if (($Output.Keys) -notcontains $Key) { $Output.$Key = $Override.$Key } - if ($Override.item($Key)) { + if (-not [string]::IsNullOrEmpty($Override.item($Key))) { $Output.$Key = $Override.$Key } } From 64a7eee32a85a5ba115b6616be3607b6976c571f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 17:55:24 +0100 Subject: [PATCH 037/176] Refactor configuration loading to append containers and improve logging output --- scripts/main.ps1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 5bc99e71..093cea9e 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -231,21 +231,21 @@ $configuration = @{ TestDrive = $testDrive TestRegistry = $testRegistry } -LogGroup 'Load configuration - Result' { - Write-Host ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) -} LogGroup 'Load containers' { $containers = Get-PesterContainer -Path $configuration.Run.Path Write-Host ($containers | ConvertTo-Json -Depth 1 -WarningAction SilentlyContinue) } -$configuration.Run.Container = $containers - -LogGroup 'Run tests' { - $testResults = Invoke-Pester -Configuration $configuration +LogGroup 'Load configuration - Result' { + $configuration.Run.Container += $containers + Write-Host ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } + +$testResults = Invoke-Pester -Configuration $configuration + + # LogGroup 'Test results' { # $testResults | Format-List # $failedTests = [int]$testResults.FailedCount From cb15d97e0186497e30adf398db571a6fa8719dec Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 18:21:43 +0100 Subject: [PATCH 038/176] Enhance logging for container loading and test results in main.ps1 script --- scripts/main.ps1 | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 093cea9e..d13c6230 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -232,7 +232,7 @@ $configuration = @{ TestRegistry = $testRegistry } -LogGroup 'Load containers' { +LogGroup 'Load configuration - Add containers' { $containers = Get-PesterContainer -Path $configuration.Run.Path Write-Host ($containers | ConvertTo-Json -Depth 1 -WarningAction SilentlyContinue) } @@ -246,18 +246,18 @@ LogGroup 'Load configuration - Result' { $testResults = Invoke-Pester -Configuration $configuration -# LogGroup 'Test results' { -# $testResults | Format-List -# $failedTests = [int]$testResults.FailedCount +LogGroup 'Test results' { + $testResults | Format-List + $failedTests = [int]$testResults.FailedCount -# if (($failedTests -gt 0) -or ($testResults.Result -ne 'Passed')) { -# Write-GitHubError "❌ Some [$failedTests] tests failed." -# } -# if ($failedTests -eq 0) { -# Write-GitHubNotice '✅ All tests passed.' -# } + if (($failedTests -gt 0) -or ($testResults.Result -ne 'Passed')) { + Write-GitHubError "❌ Some [$failedTests] tests failed." + } + if ($failedTests -eq 0) { + Write-GitHubNotice '✅ All tests passed.' + } -# Set-GitHubOutput -Name 'results' -Value $testResults -# } + Set-GitHubOutput -Name 'results' -Value $testResults +} -# exit $failedTests +exit $failedTests From b917369dba9022c61e3e61ffa93c1ab8c240fc8d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 18:32:23 +0100 Subject: [PATCH 039/176] Refactor Helpers.psm1 to remove unnecessary calls to New-PesterContainer and New-PesterConfiguration --- scripts/Helpers.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index cdad4b34..a6ad2f76 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -13,7 +13,7 @@ Import-PowerShellDataFile -Path $file } } - New-PesterContainer @param + $param } } @@ -33,7 +33,7 @@ function Get-PesterConfiguration { } } } - New-PesterConfiguration -Hashtable $config + $config } function Merge-Hashtable { From cc9fc5dbd01bcec40937e37a40f3a970ff165b2b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 18:37:07 +0100 Subject: [PATCH 040/176] Increase JSON depth for container logging in main.ps1 --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index d13c6230..28e34a48 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -234,7 +234,7 @@ $configuration = @{ LogGroup 'Load configuration - Add containers' { $containers = Get-PesterContainer -Path $configuration.Run.Path - Write-Host ($containers | ConvertTo-Json -Depth 1 -WarningAction SilentlyContinue) + Write-Host ($containers | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) } LogGroup 'Load configuration - Result' { From 19430f07898b33f5645945486f9b9e5f69d5263f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 18:47:57 +0100 Subject: [PATCH 041/176] Refactor container loading to utilize New-PesterContainer for improved configuration handling --- scripts/main.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 28e34a48..114f140c 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -238,14 +238,12 @@ LogGroup 'Load configuration - Add containers' { } LogGroup 'Load configuration - Result' { - $configuration.Run.Container += $containers + $configuration.Run.Container += $containers | ForEach-Object { New-PesterContainer @_ } Write-Host ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } - $testResults = Invoke-Pester -Configuration $configuration - LogGroup 'Test results' { $testResults | Format-List $failedTests = [int]$testResults.FailedCount From 3271534f4f1e292246c2de5a005cc316aadd8814 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 18:48:19 +0100 Subject: [PATCH 042/176] Refactor Get-PesterConfiguration to streamline file processing and return configuration directly --- scripts/Helpers.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index a6ad2f76..22baedde 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -22,7 +22,7 @@ function Get-PesterConfiguration { [string] $Path ) - $config = Get-ChildItem -Path $Path -Filter *.Configuration.ps* | ForEach-Object { + Get-ChildItem -Path $Path -Filter *.Configuration.ps* | ForEach-Object { $file = $_ switch ($file.Extension) { '.ps1' { @@ -32,8 +32,8 @@ function Get-PesterConfiguration { Import-PowerShellDataFile -Path $file } } + $config } - $config } function Merge-Hashtable { From d1f4c1830d7602df75679a6330b7e77566e2cf04 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 19:23:09 +0100 Subject: [PATCH 043/176] Refactor Helpers.psm1 to eliminate unnecessary variable assignments in file processing --- scripts/Helpers.psm1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 22baedde..12c7d5a5 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -5,7 +5,7 @@ Get-ChildItem -Path $Path -Recurse -Filter *.Container.ps* | ForEach-Object { $file = $_ - $param = switch ($file.Extension) { + switch ($file.Extension) { '.ps1' { . $file } @@ -13,7 +13,6 @@ Import-PowerShellDataFile -Path $file } } - $param } } @@ -32,7 +31,6 @@ function Get-PesterConfiguration { Import-PowerShellDataFile -Path $file } } - $config } } From bb9fbd0cb790d88567d807f8057ae906de37a4d3 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 19:37:12 +0100 Subject: [PATCH 044/176] Refactor test scripts to use parameterized path for settings file loading --- tests/Advanced/Cars/Cars.Tests.ps1 | 11 +++++++++-- tests/Advanced/Planets/Planets.Tests.ps1 | 18 ++++++++---------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/tests/Advanced/Cars/Cars.Tests.ps1 b/tests/Advanced/Cars/Cars.Tests.ps1 index b6a1efaa..3dc253d3 100644 --- a/tests/Advanced/Cars/Cars.Tests.ps1 +++ b/tests/Advanced/Cars/Cars.Tests.ps1 @@ -1,5 +1,12 @@ - -. "$PSScriptRoot\Cars.Settings.ps1" +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string] $Path +) + +BeforeAll { + . $Path +} Describe 'Cars Module Tests' { diff --git a/tests/Advanced/Planets/Planets.Tests.ps1 b/tests/Advanced/Planets/Planets.Tests.ps1 index 488a186e..9c8a8d0f 100644 --- a/tests/Advanced/Planets/Planets.Tests.ps1 +++ b/tests/Advanced/Planets/Planets.Tests.ps1 @@ -1,14 +1,12 @@ -<# -.SYNOPSIS - Pester tests for planet-related functions. -.DESCRIPTION - This script loads settings from Planets.Settings.ps1 and validates functions that return planet data. -.NOTES - Ensure that functions like Get-PlanetCount and Get-PlanetNames are available (e.g. from your module). -#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string] $Path +) -# Dot-source the settings file to import $PlanetsSettings -. "$PSScriptRoot\Planets.Settings.ps1" +BeforeAll { + . $Path +} Describe 'Planets Module Tests' { From 4038037fd20ce26abf56cf467c90c2be30ce2787 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 19:41:59 +0100 Subject: [PATCH 045/176] Remove redundant tests for animal count and names in Animals.Tests.ps1 --- tests/Advanced/Animals/Animals.Tests.ps1 | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tests/Advanced/Animals/Animals.Tests.ps1 b/tests/Advanced/Animals/Animals.Tests.ps1 index e33a1fae..07484f69 100644 --- a/tests/Advanced/Animals/Animals.Tests.ps1 +++ b/tests/Advanced/Animals/Animals.Tests.ps1 @@ -24,20 +24,3 @@ Describe 'Animals Module Tests' { } } } - -Describe 'Animals Module Tests' { - Context 'Animal Count' { - It 'Should return the expected number of animals' { - $expectedCount = $AnimalsSettings.AnimalCount - $actualCount = $AnimalsSettings.AnimalNames.Count - $actualCount | Should -Be $expectedCount - } - } - Context 'Animal Names' { - It 'Should return the expected list of animal names' { - $expectedNames = $AnimalsSettings.AnimalNames - $actualNames = $AnimalsSettings.AnimalNames - $actualNames | Should -BeExactly $expectedNames - } - } -} From 21d2a107918634be4178aea518bc12dcc5add20d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 19:56:01 +0100 Subject: [PATCH 046/176] Convert test results to JSON format before setting GitHub output --- scripts/main.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 114f140c..0c427134 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -255,7 +255,9 @@ LogGroup 'Test results' { Write-GitHubNotice '✅ All tests passed.' } - Set-GitHubOutput -Name 'results' -Value $testResults + $testResults | ConvertTo-Json -Depth 5 + + Set-GitHubOutput -Name 'results' -Value $($testResults | ConvertTo-Json -Depth 5) } exit $failedTests From a58ccdf3114f2d5d7ee5d3ee8fac16c003104ba6 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 20:12:31 +0100 Subject: [PATCH 047/176] Reduce JSON conversion depth for test results in GitHub output --- scripts/main.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 0c427134..23a6cabc 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -255,9 +255,9 @@ LogGroup 'Test results' { Write-GitHubNotice '✅ All tests passed.' } - $testResults | ConvertTo-Json -Depth 5 + $testResults | ConvertTo-Json -Depth 2 - Set-GitHubOutput -Name 'results' -Value $($testResults | ConvertTo-Json -Depth 5) + Set-GitHubOutput -Name 'results' -Value $($testResults | ConvertTo-Json -Depth 2) } exit $failedTests From daddab3a72ee436543bd435a5648a19edda825db Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 20:14:22 +0100 Subject: [PATCH 048/176] Reduce JSON conversion depth for GitHub output in main.ps1 --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 23a6cabc..6dab7928 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -257,7 +257,7 @@ LogGroup 'Test results' { $testResults | ConvertTo-Json -Depth 2 - Set-GitHubOutput -Name 'results' -Value $($testResults | ConvertTo-Json -Depth 2) + Set-GitHubOutput -Name 'results' -Value $($testResults | ConvertTo-Json -Depth 1) } exit $failedTests From d0cb9c8e8d103e85ef24db1a214099dda31e051d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 20:20:10 +0100 Subject: [PATCH 049/176] Increase JSON conversion depth for GitHub output in main.ps1 --- scripts/main.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 6dab7928..61756616 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -255,9 +255,7 @@ LogGroup 'Test results' { Write-GitHubNotice '✅ All tests passed.' } - $testResults | ConvertTo-Json -Depth 2 - - Set-GitHubOutput -Name 'results' -Value $($testResults | ConvertTo-Json -Depth 1) + Set-GitHubOutput -Name 'results' -Value $($testResults | ConvertTo-Json -Depth 2) } exit $failedTests From af0d260e1d7d870c39c9fde103699d9d33d739fa Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 20:24:16 +0100 Subject: [PATCH 050/176] Increase JSON conversion depth for test results in GitHub output --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 61756616..23e6980d 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -255,7 +255,7 @@ LogGroup 'Test results' { Write-GitHubNotice '✅ All tests passed.' } - Set-GitHubOutput -Name 'results' -Value $($testResults | ConvertTo-Json -Depth 2) + Set-GitHubOutput -Name 'results' -Value $($testResults | ConvertTo-Json -Depth 3) } exit $failedTests From 513bfb26daa03e5b33ed95f4e490c58d63bea7c4 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 20:28:04 +0100 Subject: [PATCH 051/176] No code changes made --- scripts/main.ps1 | 133 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 118 insertions(+), 15 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 23e6980d..ccafae49 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -1,6 +1,9 @@ [CmdletBinding()] param() +# ------------------------------------------------------------------------- +# Step 1: Install/Import Pester & ScriptAnalyzer +# ------------------------------------------------------------------------- 'Pester', 'PSScriptAnalyzer' | ForEach-Object { Install-PSResource -Name $_ -Verbose:$false -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery Import-Module -Name $_ -Verbose:$false @@ -8,17 +11,23 @@ param() Import-Module "$PSScriptRoot/Helpers.psm1" +# ------------------------------------------------------------------------- +# Step 2: Log tool versions +# ------------------------------------------------------------------------- LogGroup 'Get test kit versions' { $PSSAModule = Get-PSResource -Name PSScriptAnalyzer -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 $pesterModule = Get-PSResource -Name Pester -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 [PSCustomObject]@{ PowerShell = $PSVersionTable.PSVersion.ToString() - Pester = $pesterModule.version - PSScriptAnalyzer = $PSSAModule.version + Pester = $pesterModule.Version + PSScriptAnalyzer = $PSSAModule.Version } | Format-List } +# ------------------------------------------------------------------------- +# Step 3: Load all action inputs (from environment vars) +# ------------------------------------------------------------------------- LogGroup 'Load inputs' { $inputs = @{ Run_Path = $env:GITHUB_ACTION_INPUT_Run_Path @@ -31,11 +40,13 @@ LogGroup 'Load inputs' { Run_PassThru = $env:GITHUB_ACTION_INPUT_Run_PassThru Run_SkipRun = $env:GITHUB_ACTION_INPUT_Run_SkipRun Run_SkipRemainingOnFailure = $env:GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure + Filter_Tag = $env:GITHUB_ACTION_INPUT_Filter_Tag Filter_ExcludeTag = $env:GITHUB_ACTION_INPUT_Filter_ExcludeTag Filter_Line = $env:GITHUB_ACTION_INPUT_Filter_Line Filter_ExcludeLine = $env:GITHUB_ACTION_INPUT_Filter_ExcludeLine Filter_FullName = $env:GITHUB_ACTION_INPUT_Filter_FullName + CodeCoverage_Enabled = $env:GITHUB_ACTION_INPUT_CodeCoverage_Enabled CodeCoverage_OutputFormat = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat CodeCoverage_OutputPath = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputPath @@ -46,33 +57,41 @@ LogGroup 'Load inputs' { CodeCoverage_CoveragePercentTarget = $env:GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget CodeCoverage_UseBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints CodeCoverage_SingleHitBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints + TestResult_Enabled = $env:GITHUB_ACTION_INPUT_TestResult_Enabled TestResult_OutputFormat = $env:GITHUB_ACTION_INPUT_TestResult_OutputFormat TestResult_OutputPath = $env:GITHUB_ACTION_INPUT_TestResult_OutputPath TestResult_OutputEncoding = $env:GITHUB_ACTION_INPUT_TestResult_OutputEncoding TestResult_TestSuiteName = $env:GITHUB_ACTION_INPUT_TestResult_TestSuiteName + Should_ErrorAction = $env:GITHUB_ACTION_INPUT_Should_ErrorAction + Debug_ShowFullErrors = $env:GITHUB_ACTION_INPUT_Debug_ShowFullErrors Debug_WriteDebugMessages = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessages Debug_WriteDebugMessagesFrom = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom Debug_ShowNavigationMarkers = $env:GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers Debug_ReturnRawResultObject = $env:GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject + Output_Verbosity = $env:GITHUB_ACTION_INPUT_Output_Verbosity Output_StackTraceVerbosity = $env:GITHUB_ACTION_INPUT_Output_StackTraceVerbosity Output_CIFormat = $env:GITHUB_ACTION_INPUT_Output_CIFormat Output_CILogLevel = $env:GITHUB_ACTION_INPUT_Output_CILogLevel Output_RenderMode = $env:GITHUB_ACTION_INPUT_Output_RenderMode + TestDrive_Enabled = $env:GITHUB_ACTION_INPUT_TestDrive_Enabled TestRegistry_Enabled = $env:GITHUB_ACTION_INPUT_TestRegistry_Enabled ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath } - [pscustomobject]($inputs.GetEnumerator() | Where-Object { $_.Value }) | Format-List + [pscustomobject]($inputs.GetEnumerator() | Where-Object { -not [string]::IsNullOrEmpty($_.Value) }) | Format-List } $customConfiguration = @{} $customActionInputs = @{} +# ------------------------------------------------------------------------- +# Step 4: Load default configuration (from Pester.Configuration.ps1) +# ------------------------------------------------------------------------- LogGroup 'Load configuration - Defaults' { $defaultConfigurationPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') if (Test-Path -Path $defaultConfigurationPath) { @@ -89,15 +108,18 @@ LogGroup 'Load configuration - Defaults' { TestDrive = $tmpDefault.TestDrive ?? @{} TestRegistry = $tmpDefault.TestRegistry ?? @{} } - Write-Host ($defaultConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + Write-Output ($defaultConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } +# ------------------------------------------------------------------------- +# Step 5: Load custom config file (if provided) +# ------------------------------------------------------------------------- LogGroup 'Load configuration - Custom settings file' { $customConfigurationFilePath = $inputs.ConfigurationFilePath - Write-Host "Custom configuration file path: [$customConfigurationFilePath]" + Write-Output "Custom configuration file path: [$customConfigurationFilePath]" if ($customConfigurationFilePath) { $fileExists = Test-Path -Path $customConfigurationFilePath - Write-Host "File exists: [$fileExists]" + Write-Output "File exists: [$fileExists]" if ($fileExists) { $tmpCustom = . $customConfigurationFilePath } @@ -116,19 +138,21 @@ LogGroup 'Load configuration - Custom settings file' { foreach ($section in $tmpCustomConfiguration.Keys) { $filteredProperties = @{} - foreach ($property in $tmpCustomConfiguration[$section].Keys) { $value = $tmpCustomConfiguration[$section][$property] if (-not [string]::IsNullOrEmpty($Value)) { $filteredProperties[$property] = $Value } } - $customConfiguration[$section] = $filteredProperties } - Write-Host ($customConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + + Write-Output ($customConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } +# ------------------------------------------------------------------------- +# Step 6: Load direct Action input overrides +# ------------------------------------------------------------------------- LogGroup 'Load configuration - Action overrides' { $customConfigurationInputMap = @{ Run = @{ @@ -196,20 +220,21 @@ LogGroup 'Load configuration - Action overrides' { foreach ($section in $customConfigurationInputMap.Keys) { $filteredProperties = @{} - foreach ($property in $customConfigurationInputMap[$section].Keys) { $value = $customConfigurationInputMap[$section][$property] if (-not [string]::IsNullOrEmpty($Value)) { $filteredProperties[$property] = $Value } } - $customActionInputs[$section] = $filteredProperties } - Write-Host ($customActionInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + Write-Output ($customActionInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } +# ------------------------------------------------------------------------- +# Step 7: Merge all configuration layers +# ------------------------------------------------------------------------- $run = Merge-Hashtable -Main $defaultConfiguration.Run -Overrides $customConfiguration.Run, $customActionInputs.Run $filter = Merge-Hashtable -Main $defaultConfiguration.Filter -Overrides $customConfiguration.Filter, $customActionInputs.Filter $codeCoverage = Merge-Hashtable -Main $defaultConfiguration.CodeCoverage -Overrides $customConfiguration.CodeCoverage, $customActionInputs.CodeCoverage @@ -232,20 +257,30 @@ $configuration = @{ TestRegistry = $testRegistry } +# ------------------------------------------------------------------------- +# Step 8: Find and add containers (if any) +# ------------------------------------------------------------------------- LogGroup 'Load configuration - Add containers' { $containers = Get-PesterContainer -Path $configuration.Run.Path - Write-Host ($containers | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) + Write-Output ($containers | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) } LogGroup 'Load configuration - Result' { $configuration.Run.Container += $containers | ForEach-Object { New-PesterContainer @_ } - Write-Host ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + Write-Output ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } +# ------------------------------------------------------------------------- +# Step 9: Invoke Pester tests +# ------------------------------------------------------------------------- $testResults = Invoke-Pester -Configuration $configuration +# ------------------------------------------------------------------------- +# Step 10: Log test results (pass/fail) and return the number of failures +# ------------------------------------------------------------------------- LogGroup 'Test results' { $testResults | Format-List + $failedTests = [int]$testResults.FailedCount if (($failedTests -gt 0) -or ($testResults.Result -ne 'Passed')) { @@ -255,7 +290,75 @@ LogGroup 'Test results' { Write-GitHubNotice '✅ All tests passed.' } - Set-GitHubOutput -Name 'results' -Value $($testResults | ConvertTo-Json -Depth 3) + $testResults | ConvertTo-Json -Depth 2 + + # Provide structured JSON as an output for potential downstream steps + Set-GitHubOutput -Name 'results' -Value ($testResults | ConvertTo-Json -Depth 1) +} + +# ------------------------------------------------------------------------- +# Step 11: Coverage summary (optional) +# Display coverage info if CodeCoverage.Enabled = 'true' and +# testResults.CodeCoverage is present. +# ------------------------------------------------------------------------- +if ($configuration.CodeCoverage.Enabled -eq 'true') { + LogGroup 'Coverage summary' { + if ($testResults.CodeCoverage) { + $coveredLines = $testResults.CodeCoverage.CoveredLines + $totalLines = $testResults.CodeCoverage.TotalLines + + if ($totalLines -gt 0) { + $coveragePercent = [math]::Round(($coveredLines / $totalLines) * 100, 2) + Write-GitHubNotice "Coverage: $coveragePercent% ($coveredLines/$totalLines lines covered)." + } else { + Write-GitHubNotice 'Coverage: 0% (0/0 lines).' + } + } else { + Write-GitHubNotice 'No coverage info in the test results (Pester CodeCoverage object not found).' + } + } +} + +# ------------------------------------------------------------------------- +# Step 12: Generate a Step Summary (Markdown in GITHUB_STEP_SUMMARY) +# so results appear nicely in GitHub Actions UI. +# ------------------------------------------------------------------------- +LogGroup 'Generate step summary' { + $totalTests = $testResults.TestCount + $passedTests = $testResults.PassedCount + $failedTests = $testResults.FailedCount + $skippedTests = $testResults.SkippedCount + + # Default coverage text is 'N/A' if coverage is disabled + $coverageStr = 'N/A' + if (($configuration.CodeCoverage.Enabled -eq 'true') -and $testResults.CodeCoverage) { + $c = $testResults.CodeCoverage + if ($c.TotalLines -gt 0) { + $pct = [math]::Round(($c.CoveredLines / $c.TotalLines) * 100, 2) + $coverageStr = "$pct%" + } else { + $coverageStr = '0%' + } + } + + # Build a concise markdown summary + $summaryMarkdown = @" +### Pester Test Results + +| Total | Passed | Failed | Skipped | Coverage | +| ----: | -----: | -----: | ------: | -------: | +| $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $coverageStr | + +$(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅ All tests passed!' }) + +"@ + + # Write the summary to the special environment file + Set-GitHubStepSummary -Summary $summaryMarkdown } +# ------------------------------------------------------------------------- +# Step 13: Exit with the number of failed tests as the error code +# (non-zero means the step fails if tests failed). +# ------------------------------------------------------------------------- exit $failedTests From d56a9a1a3dce44c6a90177492c277e4e558be81e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 20:30:42 +0100 Subject: [PATCH 052/176] Update Pester configuration to enable test results and specify output path --- tests/Advanced/Pester.Configuration.ps1 | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/Advanced/Pester.Configuration.ps1 b/tests/Advanced/Pester.Configuration.ps1 index ae42025e..3d74517c 100644 --- a/tests/Advanced/Pester.Configuration.ps1 +++ b/tests/Advanced/Pester.Configuration.ps1 @@ -1,16 +1,13 @@ @{ - Run = @{ + Run = @{ Path = $PSScriptRoot } - CodeCoverage = @{ - Enabled = $false - } - TestResult = @{ + TestResult = @{ Enabled = $true OutputPath = 'outputs\AnotherPath.xml' TestSuiteName = 'Pester' } - Output = @{ + Output = @{ CIFormat = 'Auto' StackTraceVerbosity = 'Filtered' Verbosity = 'Detailed' From ddf60b21a47f077389f3080716e02b12c0fd2fc0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 20:35:04 +0100 Subject: [PATCH 053/176] Fix test results summary to use TotalCount and improve code coverage check --- scripts/main.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index ccafae49..fdfbc87a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -324,14 +324,14 @@ if ($configuration.CodeCoverage.Enabled -eq 'true') { # so results appear nicely in GitHub Actions UI. # ------------------------------------------------------------------------- LogGroup 'Generate step summary' { - $totalTests = $testResults.TestCount + $totalTests = $testResults.TotalCount $passedTests = $testResults.PassedCount $failedTests = $testResults.FailedCount $skippedTests = $testResults.SkippedCount # Default coverage text is 'N/A' if coverage is disabled $coverageStr = 'N/A' - if (($configuration.CodeCoverage.Enabled -eq 'true') -and $testResults.CodeCoverage) { + if (($configuration.CodeCoverage.Enabled -eq 'true') -and -not [string]::IsNullOrEmpty($testResults.CodeCoverage)) { $c = $testResults.CodeCoverage if ($c.TotalLines -gt 0) { $pct = [math]::Round(($c.CoveredLines / $c.TotalLines) * 100, 2) From f390f4c563f6b238865f58db22006bc6b9f3e4a0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 20:37:14 +0100 Subject: [PATCH 054/176] Add inconclusive and not run test counts to summary output --- scripts/main.ps1 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index fdfbc87a..1f6f9642 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -328,6 +328,8 @@ LogGroup 'Generate step summary' { $passedTests = $testResults.PassedCount $failedTests = $testResults.FailedCount $skippedTests = $testResults.SkippedCount + $inconclusiveTests = $testResults.InconclusiveCount + $notRunTests = $testResults.NotRunCount # Default coverage text is 'N/A' if coverage is disabled $coverageStr = 'N/A' @@ -345,9 +347,9 @@ LogGroup 'Generate step summary' { $summaryMarkdown = @" ### Pester Test Results -| Total | Passed | Failed | Skipped | Coverage | -| ----: | -----: | -----: | ------: | -------: | -| $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $coverageStr | +| Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | +| ----- | ------ | ------ | ------- | ------------ | ------ | -------- | +| $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageStr | $(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅ All tests passed!' }) From a22f7a2d9a27fac3186dbb052f07f0d689040749 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 20:58:21 +0100 Subject: [PATCH 055/176] Refactor test results output to use structured JSON and improve coverage summary display --- scripts/main.ps1 | 57 ++++++++++++++---------------------------------- 1 file changed, 16 insertions(+), 41 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 1f6f9642..badb2c60 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -290,39 +290,12 @@ LogGroup 'Test results' { Write-GitHubNotice '✅ All tests passed.' } - $testResults | ConvertTo-Json -Depth 2 + $results = $testResults | ConvertTo-Json -Depth 2 # Provide structured JSON as an output for potential downstream steps - Set-GitHubOutput -Name 'results' -Value ($testResults | ConvertTo-Json -Depth 1) + Set-GitHubOutput -Name 'results' -Value $results } -# ------------------------------------------------------------------------- -# Step 11: Coverage summary (optional) -# Display coverage info if CodeCoverage.Enabled = 'true' and -# testResults.CodeCoverage is present. -# ------------------------------------------------------------------------- -if ($configuration.CodeCoverage.Enabled -eq 'true') { - LogGroup 'Coverage summary' { - if ($testResults.CodeCoverage) { - $coveredLines = $testResults.CodeCoverage.CoveredLines - $totalLines = $testResults.CodeCoverage.TotalLines - - if ($totalLines -gt 0) { - $coveragePercent = [math]::Round(($coveredLines / $totalLines) * 100, 2) - Write-GitHubNotice "Coverage: $coveragePercent% ($coveredLines/$totalLines lines covered)." - } else { - Write-GitHubNotice 'Coverage: 0% (0/0 lines).' - } - } else { - Write-GitHubNotice 'No coverage info in the test results (Pester CodeCoverage object not found).' - } - } -} - -# ------------------------------------------------------------------------- -# Step 12: Generate a Step Summary (Markdown in GITHUB_STEP_SUMMARY) -# so results appear nicely in GitHub Actions UI. -# ------------------------------------------------------------------------- LogGroup 'Generate step summary' { $totalTests = $testResults.TotalCount $passedTests = $testResults.PassedCount @@ -332,26 +305,28 @@ LogGroup 'Generate step summary' { $notRunTests = $testResults.NotRunCount # Default coverage text is 'N/A' if coverage is disabled - $coverageStr = 'N/A' - if (($configuration.CodeCoverage.Enabled -eq 'true') -and -not [string]::IsNullOrEmpty($testResults.CodeCoverage)) { - $c = $testResults.CodeCoverage - if ($c.TotalLines -gt 0) { - $pct = [math]::Round(($c.CoveredLines / $c.TotalLines) * 100, 2) - $coverageStr = "$pct%" - } else { - $coverageStr = '0%' + + if ($configuration.CodeCoverage.Enabled -eq 'true') { + LogGroup 'Coverage summary' { + $coveragePercent = ($testResults.CodeCoverage).ToString() + Write-GitHubNotice "Coverage: $coveragePercent% ($coveredLines/$totalLines lines covered)." } } - # Build a concise markdown summary + $coverageString = 'N/A' + if ($configuration.CodeCoverage.Enabled) { + $coverage = [System.Math]::Round(($testResults.CodeCoverage.CoveragePercent), 2) + $coverageString = "$coverage%" + } + $summaryMarkdown = @" ### Pester Test Results +$(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅ All tests passed!' }) + | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | -| $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageStr | - -$(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅ All tests passed!' }) +| $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | "@ From 933301f090fc065b026c0406334deac99bae5a58 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:18:16 +0100 Subject: [PATCH 056/176] Refactor test summary generation for improved readability and structure --- scripts/main.ps1 | 53 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index badb2c60..16d92bba 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -296,30 +296,22 @@ LogGroup 'Test results' { Set-GitHubOutput -Name 'results' -Value $results } -LogGroup 'Generate step summary' { - $totalTests = $testResults.TotalCount - $passedTests = $testResults.PassedCount - $failedTests = $testResults.FailedCount - $skippedTests = $testResults.SkippedCount - $inconclusiveTests = $testResults.InconclusiveCount - $notRunTests = $testResults.NotRunCount - - # Default coverage text is 'N/A' if coverage is disabled - - if ($configuration.CodeCoverage.Enabled -eq 'true') { - LogGroup 'Coverage summary' { - $coveragePercent = ($testResults.CodeCoverage).ToString() - Write-GitHubNotice "Coverage: $coveragePercent% ($coveredLines/$totalLines lines covered)." - } - } - - $coverageString = 'N/A' - if ($configuration.CodeCoverage.Enabled) { - $coverage = [System.Math]::Round(($testResults.CodeCoverage.CoveragePercent), 2) - $coverageString = "$coverage%" - } +$totalTests = $testResults.TotalCount +$passedTests = $testResults.PassedCount +$failedTests = $testResults.FailedCount +$skippedTests = $testResults.SkippedCount +$inconclusiveTests = $testResults.InconclusiveCount +$notRunTests = $testResults.NotRunCount + +# Default coverage text is 'N/A' if coverage is disabled + +$coverageString = 'N/A' +if ($configuration.CodeCoverage.Enabled) { + $coverage = [System.Math]::Round(($testResults.CodeCoverage.CoveragePercent), 2) + $coverageString = "$coverage%" +} - $summaryMarkdown = @" +$summaryMarkdown = @" ### Pester Test Results $(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅ All tests passed!' }) @@ -328,11 +320,20 @@ $(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅ | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | + +
Details +

+ +<- Add detailed test results here -> + +

+
+ "@ - # Write the summary to the special environment file - Set-GitHubStepSummary -Summary $summaryMarkdown -} +# Write the summary to the special environment file +Set-GitHubStepSummary -Summary $summaryMarkdown + # ------------------------------------------------------------------------- # Step 13: Exit with the number of failed tests as the error code From d19bf222eaa829f082f2e6b603e7925c7dfb00c0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:27:13 +0100 Subject: [PATCH 057/176] Enhance test results summary to include detailed test outcomes and duration --- scripts/main.ps1 | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 16d92bba..58076059 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -324,11 +324,21 @@ $(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅
Details

-<- Add detailed test results here -> +"@ + +foreach ($test in $testResults.Tests) { + $statusIcon = if ($test.Result -eq 'Passed') { '✅' } else { '❌' } + if ($test.Result -eq 'Failed') { + $test.ErrorRecord + } + $summaryMarkdown += @" +- $statusIcon **$($test.Name)** $($test.Duration.ToString()) +"@ +} +$summaryMarkdown += @"

- "@ # Write the summary to the special environment file From 9eb734eff1af2252257a9ed0bdcd4090887fc2a4 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:28:51 +0100 Subject: [PATCH 058/176] Update test summary output to include duration in seconds and improve formatting --- scripts/main.ps1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 58076059..9c16a3c7 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -324,6 +324,7 @@ $(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅
Details

+``` "@ foreach ($test in $testResults.Tests) { @@ -332,11 +333,14 @@ foreach ($test in $testResults.Tests) { $test.ErrorRecord } $summaryMarkdown += @" -- $statusIcon **$($test.Name)** $($test.Duration.ToString()) +- $statusIcon **$($test.Name)** $($test.Duration.Seconds)s + "@ } $summaryMarkdown += @" +``` +

"@ From 6fcd8fa7a0b6afffba3add9ad2c392aaba38f885 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:30:18 +0100 Subject: [PATCH 059/176] Update test summary output to use italic formatting for duration --- scripts/main.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 9c16a3c7..e1388621 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -324,7 +324,7 @@ $(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅
Details

-``` +`````` "@ foreach ($test in $testResults.Tests) { @@ -333,13 +333,13 @@ foreach ($test in $testResults.Tests) { $test.ErrorRecord } $summaryMarkdown += @" -- $statusIcon **$($test.Name)** $($test.Duration.Seconds)s +- $statusIcon **$($test.Name)** _$($test.Duration.Seconds)s_ "@ } $summaryMarkdown += @" -``` +``````

From d8fe03422e16bbbf67dc8044a525a90b8799fb31 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:32:29 +0100 Subject: [PATCH 060/176] Improve test summary output by including duration in parentheses and displaying error messages for failed tests --- scripts/main.ps1 | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index e1388621..b005c158 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -333,8 +333,12 @@ foreach ($test in $testResults.Tests) { $test.ErrorRecord } $summaryMarkdown += @" -- $statusIcon **$($test.Name)** _$($test.Duration.Seconds)s_ +- $statusIcon $($test.Name) ($($test.Duration.Seconds)s) +"@ + if ($test.Result -eq 'Failed') { + $summaryMarkdown += @" + $($test.ErrorRecord.Exception.Message) "@ } @@ -345,12 +349,12 @@ $summaryMarkdown += @" "@ -# Write the summary to the special environment file -Set-GitHubStepSummary -Summary $summaryMarkdown + # Write the summary to the special environment file + Set-GitHubStepSummary -Summary $summaryMarkdown -# ------------------------------------------------------------------------- -# Step 13: Exit with the number of failed tests as the error code -# (non-zero means the step fails if tests failed). -# ------------------------------------------------------------------------- -exit $failedTests + # ------------------------------------------------------------------------- + # Step 13: Exit with the number of failed tests as the error code + # (non-zero means the step fails if tests failed). + # ------------------------------------------------------------------------- + exit $failedTests From ef5e9aee19f1fddf7a279661f324c6229012c3ef Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:33:59 +0100 Subject: [PATCH 061/176] Refactor summary generation for improved clarity and consistency --- scripts/main.ps1 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index b005c158..a669e0b9 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -340,8 +340,8 @@ foreach ($test in $testResults.Tests) { $summaryMarkdown += @" $($test.ErrorRecord.Exception.Message) "@ + } } - $summaryMarkdown += @" `````` @@ -349,12 +349,12 @@ $summaryMarkdown += @" "@ - # Write the summary to the special environment file - Set-GitHubStepSummary -Summary $summaryMarkdown +# Write the summary to the special environment file +Set-GitHubStepSummary -Summary $summaryMarkdown - # ------------------------------------------------------------------------- - # Step 13: Exit with the number of failed tests as the error code - # (non-zero means the step fails if tests failed). - # ------------------------------------------------------------------------- - exit $failedTests +# ------------------------------------------------------------------------- +# Step 13: Exit with the number of failed tests as the error code +# (non-zero means the step fails if tests failed). +# ------------------------------------------------------------------------- +exit $failedTests From 97266a293caa679c8267e7b9a3a58aeb7a62fb90 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:37:03 +0100 Subject: [PATCH 062/176] Refactor test summary output to improve error message formatting for failed tests --- scripts/main.ps1 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index a669e0b9..39190836 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -329,17 +329,16 @@ $(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅ foreach ($test in $testResults.Tests) { $statusIcon = if ($test.Result -eq 'Passed') { '✅' } else { '❌' } - if ($test.Result -eq 'Failed') { - $test.ErrorRecord - } $summaryMarkdown += @" - $statusIcon $($test.Name) ($($test.Duration.Seconds)s) "@ if ($test.Result -eq 'Failed') { - $summaryMarkdown += @" - $($test.ErrorRecord.Exception.Message) + $test.ErrorRecord | Out-String -Stream | ForEach-Object { + $summaryMarkdown += @" + $_ "@ + } } } $summaryMarkdown += @" From c249e9b3fa38946dca3d64566133ee6e776afdc7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:39:43 +0100 Subject: [PATCH 063/176] Update test summary output to include status icon for better visual indication of test results --- scripts/main.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 39190836..92ac4c9a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -311,10 +311,10 @@ if ($configuration.CodeCoverage.Enabled) { $coverageString = "$coverage%" } -$summaryMarkdown = @" -### Pester Test Results +$statusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } -$(if ($failedTests -gt 0) { "❌ **$failedTests test(s) failed**" } else { '✅ All tests passed!' }) +$summaryMarkdown = @" +### $statusIcon - Test Results | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | From 0f450f70446052d0ad06b61100624065afc5b4c5 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:43:39 +0100 Subject: [PATCH 064/176] Refactor error message handling in test summary output for improved formatting --- scripts/main.ps1 | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 92ac4c9a..50376c4d 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -334,11 +334,9 @@ foreach ($test in $testResults.Tests) { "@ if ($test.Result -eq 'Failed') { - $test.ErrorRecord | Out-String -Stream | ForEach-Object { - $summaryMarkdown += @" - $_ + $summaryMarkdown += @" + $(($test.ErrorRecord | Out-String) -Split '\n') "@ - } } } $summaryMarkdown += @" From 62f164a8432f0daa1a83ee0b0f4a9e20799e4080 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:49:03 +0100 Subject: [PATCH 065/176] Refactor error message handling in test summary output to display exception messages directly --- scripts/main.ps1 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 50376c4d..4854718f 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -324,7 +324,7 @@ $summaryMarkdown = @"
Details

-`````` + "@ foreach ($test in $testResults.Tests) { @@ -335,12 +335,11 @@ foreach ($test in $testResults.Tests) { "@ if ($test.Result -eq 'Failed') { $summaryMarkdown += @" - $(($test.ErrorRecord | Out-String) -Split '\n') + $($test.ErrorRecord.Exception.Message) "@ } } $summaryMarkdown += @" -``````

From 4fb2e3cafca93e53bf9cf2d9237fd985743a7fa2 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 22:55:25 +0100 Subject: [PATCH 066/176] Add newline to error message output in test summary for better readability --- scripts/main.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 4854718f..feec899a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -336,6 +336,7 @@ foreach ($test in $testResults.Tests) { if ($test.Result -eq 'Failed') { $summaryMarkdown += @" $($test.ErrorRecord.Exception.Message) + "@ } } From 9a4c6bb875bd73cfe4c4f0d45384c37b668f2a59 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 14 Feb 2025 23:18:39 +0100 Subject: [PATCH 067/176] Add Format-TimeSpan function for improved time duration formatting in test summary --- scripts/Helpers.psm1 | 98 ++++++++++++++++++++++++++++++++++++++++++++ scripts/main.ps1 | 5 ++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 12c7d5a5..93e00919 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -90,3 +90,101 @@ function Merge-Hashtable { } return $Output } + +filter Format-TimeSpan { + [CmdletBinding()] + param( + [Parameter( + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName + )] + [TimeSpan] $TimeSpan + ) + + # If the TimeSpan is negative, handle sign and convert to a positive interval for breakdown + $isNegative = $TimeSpan.Ticks -lt 0 + if ($isNegative) { + $TimeSpan = New-TimeSpan -Ticks (-1 * $TimeSpan.Ticks) + } + + # Total ticks in the TimeSpan + [long]$ticks = $TimeSpan.Ticks + + # Define approximate conversion constants + [long]$ticksInMillisecond = 10000 # 1 ms = 10,000 ticks + [long]$ticksInSecond = 10000000 # 1 second = 10 million ticks + [long]$ticksInMinute = $ticksInSecond * 60 + [long]$ticksInHour = $ticksInMinute * 60 + [long]$ticksInDay = $ticksInHour * 24 + [long]$ticksInWeek = $ticksInDay * 7 + + # Approximate day-based constants for months/years: + # ~30.436875 days in an average month, ~365.2425 days in an average year + [double]$daysInMonth = 30.436875 + [double]$daysInYear = 365.2425 + + [long]$ticksInMonth = [long]($daysInMonth * $ticksInDay) + [long]$ticksInYear = [long]($daysInYear * $ticksInDay) + + # Extract each component (largest to smallest) + $years = [math]::Floor($ticks / $ticksInYear) + $ticks = $ticks % $ticksInYear + + $months = [math]::Floor($ticks / $ticksInMonth) + $ticks = $ticks % $ticksInMonth + + $weeks = [math]::Floor($ticks / $ticksInWeek) + $ticks = $ticks % $ticksInWeek + + $days = [math]::Floor($ticks / $ticksInDay) + $ticks = $ticks % $ticksInDay + + $hours = [math]::Floor($ticks / $ticksInHour) + $ticks = $ticks % $ticksInHour + + $minutes = [math]::Floor($ticks / $ticksInMinute) + $ticks = $ticks % $ticksInMinute + + $seconds = [math]::Floor($ticks / $ticksInSecond) + $ticks = $ticks % $ticksInSecond + + $milliseconds = [math]::Floor($ticks / $ticksInMillisecond) + $ticks = $ticks % $ticksInMillisecond + + # 1 tick = 100 nanoseconds. + # Microseconds = leftover ticks * (100 ns) / 1000 => leftover ticks / 10 + $microseconds = [math]::Floor($ticks / 10) + $ticks = $ticks % 10 + + # Remaining ticks are in increments of 100 ns + $nanoseconds = $ticks * 100 + + # Build a list of non-zero components + $parts = @() + if ($years -ne 0) { $parts += "$years" + 'y' } + if ($months -ne 0) { $parts += "$months" + 'mo' } + if ($weeks -ne 0) { $parts += "$weeks" + 'w' } + if ($days -ne 0) { $parts += "$days" + 'd' } + if ($hours -ne 0) { $parts += "$hours" + 'h' } + if ($minutes -ne 0) { $parts += "$minutes" + 'm' } + if ($seconds -ne 0) { $parts += "$seconds" + 's' } + if ($milliseconds -ne 0) { $parts += "$milliseconds" + 'ms' } + if ($microseconds -ne 0) { $parts += "$microseconds" + 'us' } + if ($nanoseconds -ne 0) { $parts += "$nanoseconds" + 'ns' } + + # If everything was 0, just show "0s" + $formatted = if ($parts.Count -eq 0) { + '0s' + } else { + # Join with spaces (or any desired separator) + $parts -join ' ' + } + + # Add negative sign if original TimeSpan was negative + if ($isNegative) { + $formatted = "-$formatted" + } + + return $formatted +} diff --git a/scripts/main.ps1 b/scripts/main.ps1 index feec899a..58cdd1e6 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -324,13 +324,13 @@ $summaryMarkdown = @"
Details

- +`````` "@ foreach ($test in $testResults.Tests) { $statusIcon = if ($test.Result -eq 'Passed') { '✅' } else { '❌' } $summaryMarkdown += @" -- $statusIcon $($test.Name) ($($test.Duration.Seconds)s) +- $statusIcon $($test.Name) ($($test.Duration | Format-TimeSpan)) "@ if ($test.Result -eq 'Failed') { @@ -341,6 +341,7 @@ foreach ($test in $testResults.Tests) { } } $summaryMarkdown += @" +``````

From 7cb9c981d1166d7f56ea6117fc289a033e6a4722 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 08:27:01 +0100 Subject: [PATCH 068/176] Enhance Format-TimeSpan function with precision and adaptive rounding options for improved time formatting in test summaries --- scripts/Helpers.psm1 | 173 ++++++++++++++++++++++++++++++++----------- scripts/main.ps1 | 2 +- 2 files changed, 131 insertions(+), 44 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 93e00919..c4c46beb 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -94,40 +94,45 @@ function Merge-Hashtable { filter Format-TimeSpan { [CmdletBinding()] param( - [Parameter( - Mandatory, + [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] - [TimeSpan] $TimeSpan + [TimeSpan] $TimeSpan, + + [ValidateSet('Years', 'Months', 'Weeks', 'Days', 'Hours', 'Minutes', 'Seconds', 'Milliseconds', 'Microseconds', 'Nanoseconds')] + [string] $Precision = 'Nanoseconds', + + # If set to $true, do a rounding pass from nanoseconds -> microseconds -> milliseconds -> seconds, etc. + # so that e.g. 999ms + leftover microseconds could become 1s, dropping microseconds/nanoseconds. + [switch] $AdaptiveRounding ) - # If the TimeSpan is negative, handle sign and convert to a positive interval for breakdown + #----- 1) Handle negative TimeSpan ----- $isNegative = $TimeSpan.Ticks -lt 0 if ($isNegative) { $TimeSpan = New-TimeSpan -Ticks (-1 * $TimeSpan.Ticks) } - # Total ticks in the TimeSpan - [long]$ticks = $TimeSpan.Ticks + #----- 2) Define constants ----- + [long] $ticks = $TimeSpan.Ticks - # Define approximate conversion constants - [long]$ticksInMillisecond = 10000 # 1 ms = 10,000 ticks - [long]$ticksInSecond = 10000000 # 1 second = 10 million ticks - [long]$ticksInMinute = $ticksInSecond * 60 - [long]$ticksInHour = $ticksInMinute * 60 - [long]$ticksInDay = $ticksInHour * 24 - [long]$ticksInWeek = $ticksInDay * 7 + # 1 tick = 100 ns + [long] $ticksInMillisecond = 10000 # 1 ms = 10,000 ticks + [long] $ticksInSecond = 10000000 # 1 s = 10,000,000 ticks + [long] $ticksInMinute = $ticksInSecond * 60 + [long] $ticksInHour = $ticksInMinute * 60 + [long] $ticksInDay = $ticksInHour * 24 + [long] $ticksInWeek = $ticksInDay * 7 - # Approximate day-based constants for months/years: - # ~30.436875 days in an average month, ~365.2425 days in an average year - [double]$daysInMonth = 30.436875 - [double]$daysInYear = 365.2425 + # Approximate day-based constants for months & years + [double] $daysInMonth = 30.436875 + [double] $daysInYear = 365.2425 - [long]$ticksInMonth = [long]($daysInMonth * $ticksInDay) - [long]$ticksInYear = [long]($daysInYear * $ticksInDay) + [long] $ticksInMonth = [long]($daysInMonth * $ticksInDay) + [long] $ticksInYear = [long]($daysInYear * $ticksInDay) - # Extract each component (largest to smallest) + #----- 3) Extract units from largest to smallest ----- $years = [math]::Floor($ticks / $ticksInYear) $ticks = $ticks % $ticksInYear @@ -152,36 +157,118 @@ filter Format-TimeSpan { $milliseconds = [math]::Floor($ticks / $ticksInMillisecond) $ticks = $ticks % $ticksInMillisecond - # 1 tick = 100 nanoseconds. - # Microseconds = leftover ticks * (100 ns) / 1000 => leftover ticks / 10 + # 1 tick = 100 ns, so microseconds = leftover ticks / 10 $microseconds = [math]::Floor($ticks / 10) $ticks = $ticks % 10 - # Remaining ticks are in increments of 100 ns + # leftover ticks * 100 ns = nanoseconds $nanoseconds = $ticks * 100 - # Build a list of non-zero components - $parts = @() - if ($years -ne 0) { $parts += "$years" + 'y' } - if ($months -ne 0) { $parts += "$months" + 'mo' } - if ($weeks -ne 0) { $parts += "$weeks" + 'w' } - if ($days -ne 0) { $parts += "$days" + 'd' } - if ($hours -ne 0) { $parts += "$hours" + 'h' } - if ($minutes -ne 0) { $parts += "$minutes" + 'm' } - if ($seconds -ne 0) { $parts += "$seconds" + 's' } - if ($milliseconds -ne 0) { $parts += "$milliseconds" + 'ms' } - if ($microseconds -ne 0) { $parts += "$microseconds" + 'us' } - if ($nanoseconds -ne 0) { $parts += "$nanoseconds" + 'ns' } - - # If everything was 0, just show "0s" - $formatted = if ($parts.Count -eq 0) { - '0s' - } else { - # Join with spaces (or any desired separator) - $parts -join ' ' + #----- 4) If requested, do an adaptive "rounding up" pass ----- + if ($AdaptiveRounding) { + # Round nanoseconds -> microseconds + # e.g. if nano >= 500, round up microseconds by 1 + if ($nanoseconds -ge 500) { + $microseconds++ + } + $nanoseconds = 0 + + # Carry microseconds -> milliseconds + if ($microseconds -ge 1000) { + $milliseconds += [math]::Floor($microseconds / 1000) + $microseconds = $microseconds % 1000 + } + + # Carry milliseconds -> seconds + if ($milliseconds -ge 1000) { + $seconds += [math]::Floor($milliseconds / 1000) + $milliseconds = $milliseconds % 1000 + } + + # Carry seconds -> minutes + if ($seconds -ge 60) { + $minutes += [math]::Floor($seconds / 60) + $seconds = $seconds % 60 + } + + # Carry minutes -> hours + if ($minutes -ge 60) { + $hours += [math]::Floor($minutes / 60) + $minutes = $minutes % 60 + } + + # Carry hours -> days + if ($hours -ge 24) { + $days += [math]::Floor($hours / 24) + $hours = $hours % 24 + } + + # Carry days -> weeks + if ($days -ge 7) { + $weeks += [math]::Floor($days / 7) + $days = $days % 7 + } + + # Approx: 4 weeks = 1 month + if ($weeks -ge 4) { + $months += [math]::Floor($weeks / 4) + $weeks = $weeks % 4 + } + + # 12 months = 1 year + if ($months -ge 12) { + $years += [math]::Floor($months / 12) + $months = $months % 12 + } + } + + #----- 5) Apply Precision Filtering ----- + # Map each unit to a numeric rank + $unitRank = @{ + 'Years' = 1 + 'Months' = 2 + 'Weeks' = 3 + 'Days' = 4 + 'Hours' = 5 + 'Minutes' = 6 + 'Seconds' = 7 + 'Milliseconds' = 8 + 'Microseconds' = 9 + 'Nanoseconds' = 10 } + [int] $lowestUnitAllowed = $unitRank[$Precision] + + # Gather all units in descending order + $components = [System.Collections.Generic.List[object]]::new() + $components.Add(@('Years', $years, 'y')) + $components.Add(@('Months', $months, 'mo')) + $components.Add(@('Weeks', $weeks, 'w')) + $components.Add(@('Days', $days, 'd')) + $components.Add(@('Hours', $hours, 'h')) + $components.Add(@('Minutes', $minutes, 'm')) + $components.Add(@('Seconds', $seconds, 's')) + $components.Add(@('Milliseconds', $milliseconds, 'ms')) + $components.Add(@('Microseconds', $microseconds, 'us')) + $components.Add(@('Nanoseconds', $nanoseconds, 'ns')) + + # Filter out units that rank below the chosen precision or have zero value + $parts = foreach ($item in $components) { + $name = $item[0] + $value = $item[1] + $abbr = $item[2] + if ($unitRank[$name] -le $lowestUnitAllowed -and $value -ne 0) { + "$value$abbr" + } + } + + # If no parts remain, it means everything was 0 => "0s" + if ($parts.Count -eq 0) { + $parts = @('0s') + } + + $formatted = $parts -join ' ' - # Add negative sign if original TimeSpan was negative + #----- 6) Reapply sign if negative ----- if ($isNegative) { $formatted = "-$formatted" } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 58cdd1e6..e45f0745 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -330,7 +330,7 @@ $summaryMarkdown = @" foreach ($test in $testResults.Tests) { $statusIcon = if ($test.Result -eq 'Passed') { '✅' } else { '❌' } $summaryMarkdown += @" -- $statusIcon $($test.Name) ($($test.Duration | Format-TimeSpan)) +- $statusIcon $($test.Name) ($($test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding)) "@ if ($test.Result -eq 'Failed') { From 621539e6e084d510b1ba8607ddc13a49dd349fe4 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 08:38:31 +0100 Subject: [PATCH 069/176] Refactor configuration handling in main script for improved clarity and consistency --- scripts/main.ps1 | 107 ++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 72 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index e45f0745..af4df2f0 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -1,19 +1,14 @@ [CmdletBinding()] param() -# ------------------------------------------------------------------------- -# Step 1: Install/Import Pester & ScriptAnalyzer -# ------------------------------------------------------------------------- -'Pester', 'PSScriptAnalyzer' | ForEach-Object { - Install-PSResource -Name $_ -Verbose:$false -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery - Import-Module -Name $_ -Verbose:$false +LogGroup 'Setup prerequisites' { + 'Pester', 'PSScriptAnalyzer' | ForEach-Object { + Install-PSResource -Name $_ -Verbose:$false -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery + Import-Module -Name $_ -Verbose:$false + } + Import-Module "$PSScriptRoot/Helpers.psm1" } -Import-Module "$PSScriptRoot/Helpers.psm1" - -# ------------------------------------------------------------------------- -# Step 2: Log tool versions -# ------------------------------------------------------------------------- LogGroup 'Get test kit versions' { $PSSAModule = Get-PSResource -Name PSScriptAnalyzer -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 $pesterModule = Get-PSResource -Name Pester -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 @@ -25,9 +20,6 @@ LogGroup 'Get test kit versions' { } | Format-List } -# ------------------------------------------------------------------------- -# Step 3: Load all action inputs (from environment vars) -# ------------------------------------------------------------------------- LogGroup 'Load inputs' { $inputs = @{ Run_Path = $env:GITHUB_ACTION_INPUT_Run_Path @@ -86,18 +78,15 @@ LogGroup 'Load inputs' { [pscustomobject]($inputs.GetEnumerator() | Where-Object { -not [string]::IsNullOrEmpty($_.Value) }) | Format-List } -$customConfiguration = @{} -$customActionInputs = @{} +$customConfig = @{} +$customInputs = @{} -# ------------------------------------------------------------------------- -# Step 4: Load default configuration (from Pester.Configuration.ps1) -# ------------------------------------------------------------------------- LogGroup 'Load configuration - Defaults' { - $defaultConfigurationPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') - if (Test-Path -Path $defaultConfigurationPath) { - $tmpDefault = . $defaultConfigurationPath + $defaultConfigPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') + if (Test-Path -Path $defaultConfigPath) { + $tmpDefault = . $defaultConfigPath } - $defaultConfiguration = @{ + $defaultConfig = @{ Run = $tmpDefault.Run ?? @{} Filter = $tmpDefault.Filter ?? @{} CodeCoverage = $tmpDefault.CodeCoverage ?? @{} @@ -108,20 +97,17 @@ LogGroup 'Load configuration - Defaults' { TestDrive = $tmpDefault.TestDrive ?? @{} TestRegistry = $tmpDefault.TestRegistry ?? @{} } - Write-Output ($defaultConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + Write-Output ($defaultConfig | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } -# ------------------------------------------------------------------------- -# Step 5: Load custom config file (if provided) -# ------------------------------------------------------------------------- LogGroup 'Load configuration - Custom settings file' { - $customConfigurationFilePath = $inputs.ConfigurationFilePath - Write-Output "Custom configuration file path: [$customConfigurationFilePath]" - if ($customConfigurationFilePath) { - $fileExists = Test-Path -Path $customConfigurationFilePath + $customConfigFilePath = $inputs.ConfigurationFilePath + Write-Output "Custom configuration file path: [$customConfigFilePath]" + if ($customConfigFilePath) { + $fileExists = Test-Path -Path $customConfigFilePath Write-Output "File exists: [$fileExists]" if ($fileExists) { - $tmpCustom = . $customConfigurationFilePath + $tmpCustom = . $customConfigFilePath } } $tmpCustomConfiguration = @{ @@ -144,17 +130,14 @@ LogGroup 'Load configuration - Custom settings file' { $filteredProperties[$property] = $Value } } - $customConfiguration[$section] = $filteredProperties + $customConfig[$section] = $filteredProperties } - Write-Output ($customConfiguration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + Write-Output ($customConfig | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } -# ------------------------------------------------------------------------- -# Step 6: Load direct Action input overrides -# ------------------------------------------------------------------------- LogGroup 'Load configuration - Action overrides' { - $customConfigurationInputMap = @{ + $customConfigInputMap = @{ Run = @{ Path = $inputs.Run_Path ExcludePath = $inputs.Run_ExcludePath @@ -218,32 +201,29 @@ LogGroup 'Load configuration - Action overrides' { } } - foreach ($section in $customConfigurationInputMap.Keys) { + foreach ($section in $customConfigInputMap.Keys) { $filteredProperties = @{} - foreach ($property in $customConfigurationInputMap[$section].Keys) { - $value = $customConfigurationInputMap[$section][$property] + foreach ($property in $customConfigInputMap[$section].Keys) { + $value = $customConfigInputMap[$section][$property] if (-not [string]::IsNullOrEmpty($Value)) { $filteredProperties[$property] = $Value } } - $customActionInputs[$section] = $filteredProperties + $customInputs[$section] = $filteredProperties } - Write-Output ($customActionInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) + Write-Output ($customInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } -# ------------------------------------------------------------------------- -# Step 7: Merge all configuration layers -# ------------------------------------------------------------------------- -$run = Merge-Hashtable -Main $defaultConfiguration.Run -Overrides $customConfiguration.Run, $customActionInputs.Run -$filter = Merge-Hashtable -Main $defaultConfiguration.Filter -Overrides $customConfiguration.Filter, $customActionInputs.Filter -$codeCoverage = Merge-Hashtable -Main $defaultConfiguration.CodeCoverage -Overrides $customConfiguration.CodeCoverage, $customActionInputs.CodeCoverage -$testResult = Merge-Hashtable -Main $defaultConfiguration.TestResult -Overrides $customConfiguration.TestResult, $customActionInputs.TestResult -$should = Merge-Hashtable -Main $defaultConfiguration.Should -Overrides $customConfiguration.Should, $customActionInputs.Should -$debug = Merge-Hashtable -Main $defaultConfiguration.Debug -Overrides $customConfiguration.Debug, $customActionInputs.Debug -$output = Merge-Hashtable -Main $defaultConfiguration.Output -Overrides $customConfiguration.Output, $customActionInputs.Output -$testDrive = Merge-Hashtable -Main $defaultConfiguration.TestDrive -Overrides $customConfiguration.TestDrive, $customActionInputs.TestDrive -$testRegistry = Merge-Hashtable -Main $defaultConfiguration.TestRegistry -Overrides $customConfiguration.TestRegistry, $customActionInputs.TestRegistry +$run = Merge-Hashtable -Main $defaultConfig.Run -Overrides $customConfig.Run, $customInputs.Run +$filter = Merge-Hashtable -Main $defaultConfig.Filter -Overrides $customConfig.Filter, $customInputs.Filter +$codeCoverage = Merge-Hashtable -Main $defaultConfig.CodeCoverage -Overrides $customConfig.CodeCoverage, $customInputs.CodeCoverage +$testResult = Merge-Hashtable -Main $defaultConfig.TestResult -Overrides $customConfig.TestResult, $customInputs.TestResult +$should = Merge-Hashtable -Main $defaultConfig.Should -Overrides $customConfig.Should, $customInputs.Should +$debug = Merge-Hashtable -Main $defaultConfig.Debug -Overrides $customConfig.Debug, $customInputs.Debug +$output = Merge-Hashtable -Main $defaultConfig.Output -Overrides $customConfig.Output, $customInputs.Output +$testDrive = Merge-Hashtable -Main $defaultConfig.TestDrive -Overrides $customConfig.TestDrive, $customInputs.TestDrive +$testRegistry = Merge-Hashtable -Main $defaultConfig.TestRegistry -Overrides $customConfig.TestRegistry, $customInputs.TestRegistry $configuration = @{ Run = $run @@ -257,9 +237,6 @@ $configuration = @{ TestRegistry = $testRegistry } -# ------------------------------------------------------------------------- -# Step 8: Find and add containers (if any) -# ------------------------------------------------------------------------- LogGroup 'Load configuration - Add containers' { $containers = Get-PesterContainer -Path $configuration.Run.Path Write-Output ($containers | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) @@ -270,14 +247,8 @@ LogGroup 'Load configuration - Result' { Write-Output ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } -# ------------------------------------------------------------------------- -# Step 9: Invoke Pester tests -# ------------------------------------------------------------------------- $testResults = Invoke-Pester -Configuration $configuration -# ------------------------------------------------------------------------- -# Step 10: Log test results (pass/fail) and return the number of failures -# ------------------------------------------------------------------------- LogGroup 'Test results' { $testResults | Format-List @@ -303,8 +274,6 @@ $skippedTests = $testResults.SkippedCount $inconclusiveTests = $testResults.InconclusiveCount $notRunTests = $testResults.NotRunCount -# Default coverage text is 'N/A' if coverage is disabled - $coverageString = 'N/A' if ($configuration.CodeCoverage.Enabled) { $coverage = [System.Math]::Round(($testResults.CodeCoverage.CoveragePercent), 2) @@ -347,12 +316,6 @@ $summaryMarkdown += @" "@ -# Write the summary to the special environment file Set-GitHubStepSummary -Summary $summaryMarkdown - -# ------------------------------------------------------------------------- -# Step 13: Exit with the number of failed tests as the error code -# (non-zero means the step fails if tests failed). -# ------------------------------------------------------------------------- exit $failedTests From ec9aadde19c8493360c80955591505efbc4b5bb8 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 08:51:38 +0100 Subject: [PATCH 070/176] Add emoji data initialization and Get-Emoji function for enhanced emoji lookup in tests --- tests/Advanced/Pester.Configuration.ps1 | 3 ++- tests/Simple/Get-Emoji.Tests.ps1 | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/Advanced/Pester.Configuration.ps1 b/tests/Advanced/Pester.Configuration.ps1 index 3d74517c..53c99aab 100644 --- a/tests/Advanced/Pester.Configuration.ps1 +++ b/tests/Advanced/Pester.Configuration.ps1 @@ -1,6 +1,7 @@ @{ Run = @{ - Path = $PSScriptRoot + Path = $PSScriptRoot + Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.ps* | ForEach-Object { . $_ } } TestResult = @{ Enabled = $true diff --git a/tests/Simple/Get-Emoji.Tests.ps1 b/tests/Simple/Get-Emoji.Tests.ps1 index fdbf208d..2db4ac47 100644 --- a/tests/Simple/Get-Emoji.Tests.ps1 +++ b/tests/Simple/Get-Emoji.Tests.ps1 @@ -1,4 +1,22 @@ -Describe 'Get-Emoji' { +BeforeAll { + $emojis = @( + @{ Name = 'apple'; Symbol = '🍎'; Kind = 'Fruit' } + @{ Name = 'beaming face with smiling eyes'; Symbol = '😁'; Kind = 'Face' } + @{ Name = 'cactus'; Symbol = '🌵'; Kind = 'Plant' } + @{ Name = 'giraffe'; Symbol = '🦒'; Kind = 'Animal' } + @{ Name = 'pencil'; Symbol = '✏️'; Kind = 'Item' } + @{ Name = 'penguin'; Symbol = '🐧'; Kind = 'Animal' } + @{ Name = 'pensive'; Symbol = '😔'; Kind = 'Face' } + @{ Name = 'slightly smiling face'; Symbol = '🙂'; Kind = 'Face' } + @{ Name = 'smiling face with smiling eyes'; Symbol = '😊'; Kind = 'Face' } + ) | ForEach-Object { [PSCustomObject]$_ } + + function Get-Emoji ([string]$Name = '*') { + $emojis | Where-Object Name -Like $Name | ForEach-Object Symbol + } +} + +Describe 'Get-Emoji' { Context 'Lookup by whole name' { It 'Returns 🌵 (cactus)' { Get-Emoji -Name cactus | Should -Be '🌵' From a347866b15e1374c02ff04a355c454b82e110d60 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 09:05:48 +0100 Subject: [PATCH 071/176] Add data and test files for Cars, Animals, and Planets modules to enhance testing coverage --- .github/workflows/Action-Test.yml | 6 +-- .../{Simple => 1-Simple}/Get-Emoji.Tests.ps1 | 0 .../Emoji.Configuration.ps1} | 2 +- .../Emoji.Container.ps1} | 0 tests/2-Standard/Emoji.Tests.ps1 | 49 +++++++++++++++++++ tests/2-Standard/Emoji.psm1 | 15 ++++++ .../Animals/Animals.Container.ps1} | 0 .../Animals/Animals.Data.ps1 | 0 .../Animals/Animals.Tests.ps1 | 0 .../Cars/Cars.Container.ps1} | 0 .../Cars/Cars.Data.ps1 | 0 .../Cars/Cars.Tests.ps1 | 0 tests/3-Advanced/Pester.Configuration.ps1 | 15 ++++++ .../3-Advanced/Planets/Planets.Container.ps1 | 8 +++ .../Planets/Planets.Data.ps1 | 0 .../Planets/Planets.Tests.ps1 | 0 16 files changed, 91 insertions(+), 4 deletions(-) rename tests/{Simple => 1-Simple}/Get-Emoji.Tests.ps1 (100%) rename tests/{Advanced/Pester.Configuration.ps1 => 2-Standard/Emoji.Configuration.ps1} (91%) rename tests/{Advanced/Animals/Animals.Container.ps1 => 2-Standard/Emoji.Container.ps1} (100%) create mode 100644 tests/2-Standard/Emoji.Tests.ps1 create mode 100644 tests/2-Standard/Emoji.psm1 rename tests/{Advanced/Cars/Cars.Container.ps1 => 3-Advanced/Animals/Animals.Container.ps1} (100%) rename tests/{Advanced => 3-Advanced}/Animals/Animals.Data.ps1 (100%) rename tests/{Advanced => 3-Advanced}/Animals/Animals.Tests.ps1 (100%) rename tests/{Advanced/Planets/Planets.Container.ps1 => 3-Advanced/Cars/Cars.Container.ps1} (100%) rename tests/{Advanced => 3-Advanced}/Cars/Cars.Data.ps1 (100%) rename tests/{Advanced => 3-Advanced}/Cars/Cars.Tests.ps1 (100%) create mode 100644 tests/3-Advanced/Pester.Configuration.ps1 create mode 100644 tests/3-Advanced/Planets/Planets.Container.ps1 rename tests/{Advanced => 3-Advanced}/Planets/Planets.Data.ps1 (100%) rename tests/{Advanced => 3-Advanced}/Planets/Planets.Tests.ps1 (100%) diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index 754a8211..a9c15339 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -31,14 +31,14 @@ jobs: Run_Path: tests/Simple ActionTestAdvanced: - name: Action-Test - [Advanced] + name: Action-Test - [3-Advanced] runs-on: ubuntu-latest steps: # Need to check out as part of the test, as its a local action - name: Checkout repo uses: actions/checkout@v4 - - name: Action-Test [Advanced] + - name: Action-Test [3-Advanced] uses: ./ with: - ConfigurationFilePath: tests/Advanced/Pester.Configuration.ps1 + ConfigurationFilePath: tests/3-Advanced/Pester.Configuration.ps1 diff --git a/tests/Simple/Get-Emoji.Tests.ps1 b/tests/1-Simple/Get-Emoji.Tests.ps1 similarity index 100% rename from tests/Simple/Get-Emoji.Tests.ps1 rename to tests/1-Simple/Get-Emoji.Tests.ps1 diff --git a/tests/Advanced/Pester.Configuration.ps1 b/tests/2-Standard/Emoji.Configuration.ps1 similarity index 91% rename from tests/Advanced/Pester.Configuration.ps1 rename to tests/2-Standard/Emoji.Configuration.ps1 index 53c99aab..200ad6a4 100644 --- a/tests/Advanced/Pester.Configuration.ps1 +++ b/tests/2-Standard/Emoji.Configuration.ps1 @@ -1,7 +1,7 @@ @{ Run = @{ Path = $PSScriptRoot - Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.ps* | ForEach-Object { . $_ } + Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* | ForEach-Object { . $_ } } TestResult = @{ Enabled = $true diff --git a/tests/Advanced/Animals/Animals.Container.ps1 b/tests/2-Standard/Emoji.Container.ps1 similarity index 100% rename from tests/Advanced/Animals/Animals.Container.ps1 rename to tests/2-Standard/Emoji.Container.ps1 diff --git a/tests/2-Standard/Emoji.Tests.ps1 b/tests/2-Standard/Emoji.Tests.ps1 new file mode 100644 index 00000000..fdbf208d --- /dev/null +++ b/tests/2-Standard/Emoji.Tests.ps1 @@ -0,0 +1,49 @@ +Describe 'Get-Emoji' { + Context 'Lookup by whole name' { + It 'Returns 🌵 (cactus)' { + Get-Emoji -Name cactus | Should -Be '🌵' + } + + It 'Returns 🦒 (giraffe)' { + Get-Emoji -Name giraffe | Should -Be '🦒' + } + } + + Context 'Lookup by wildcard' { + Context 'by prefix' { + BeforeAll { + $emojis = Get-Emoji -Name pen* + } + + It 'Returns ✏️ (pencil)' { + $emojis | Should -Contain '✏️' + } + + It 'Returns 🐧 (penguin)' { + $emojis | Should -Contain '🐧' + } + + It 'Returns 😔 (pensive)' { + $emojis | Should -Contain '😔' + } + } + + Context 'by contains' { + BeforeAll { + $emojis = Get-Emoji -Name *smiling* + } + + It 'Returns 🙂 (slightly smiling face)' { + $emojis | Should -Contain '🙂' + } + + It 'Returns 😁 (beaming face with smiling eyes)' { + $emojis | Should -Contain '😁' + } + + It 'Returns 😊 (smiling face with smiling eyes)' { + $emojis | Should -Contain '😊' + } + } + } +} diff --git a/tests/2-Standard/Emoji.psm1 b/tests/2-Standard/Emoji.psm1 new file mode 100644 index 00000000..d27e0317 --- /dev/null +++ b/tests/2-Standard/Emoji.psm1 @@ -0,0 +1,15 @@ +$script:emojis = @( + @{ Name = 'apple'; Symbol = '🍎'; Kind = 'Fruit' } + @{ Name = 'beaming face with smiling eyes'; Symbol = '😁'; Kind = 'Face' } + @{ Name = 'cactus'; Symbol = '🌵'; Kind = 'Plant' } + @{ Name = 'giraffe'; Symbol = '🦒'; Kind = 'Animal' } + @{ Name = 'pencil'; Symbol = '✏️'; Kind = 'Item' } + @{ Name = 'penguin'; Symbol = '🐧'; Kind = 'Animal' } + @{ Name = 'pensive'; Symbol = '😔'; Kind = 'Face' } + @{ Name = 'slightly smiling face'; Symbol = '🙂'; Kind = 'Face' } + @{ Name = 'smiling face with smiling eyes'; Symbol = '😊'; Kind = 'Face' } +) | ForEach-Object { [PSCustomObject]$_ } + +function Get-Emoji ([string]$Name = '*') { + $script:emojis | Where-Object Name -Like $Name | ForEach-Object Symbol +} diff --git a/tests/Advanced/Cars/Cars.Container.ps1 b/tests/3-Advanced/Animals/Animals.Container.ps1 similarity index 100% rename from tests/Advanced/Cars/Cars.Container.ps1 rename to tests/3-Advanced/Animals/Animals.Container.ps1 diff --git a/tests/Advanced/Animals/Animals.Data.ps1 b/tests/3-Advanced/Animals/Animals.Data.ps1 similarity index 100% rename from tests/Advanced/Animals/Animals.Data.ps1 rename to tests/3-Advanced/Animals/Animals.Data.ps1 diff --git a/tests/Advanced/Animals/Animals.Tests.ps1 b/tests/3-Advanced/Animals/Animals.Tests.ps1 similarity index 100% rename from tests/Advanced/Animals/Animals.Tests.ps1 rename to tests/3-Advanced/Animals/Animals.Tests.ps1 diff --git a/tests/Advanced/Planets/Planets.Container.ps1 b/tests/3-Advanced/Cars/Cars.Container.ps1 similarity index 100% rename from tests/Advanced/Planets/Planets.Container.ps1 rename to tests/3-Advanced/Cars/Cars.Container.ps1 diff --git a/tests/Advanced/Cars/Cars.Data.ps1 b/tests/3-Advanced/Cars/Cars.Data.ps1 similarity index 100% rename from tests/Advanced/Cars/Cars.Data.ps1 rename to tests/3-Advanced/Cars/Cars.Data.ps1 diff --git a/tests/Advanced/Cars/Cars.Tests.ps1 b/tests/3-Advanced/Cars/Cars.Tests.ps1 similarity index 100% rename from tests/Advanced/Cars/Cars.Tests.ps1 rename to tests/3-Advanced/Cars/Cars.Tests.ps1 diff --git a/tests/3-Advanced/Pester.Configuration.ps1 b/tests/3-Advanced/Pester.Configuration.ps1 new file mode 100644 index 00000000..3d74517c --- /dev/null +++ b/tests/3-Advanced/Pester.Configuration.ps1 @@ -0,0 +1,15 @@ +@{ + Run = @{ + Path = $PSScriptRoot + } + TestResult = @{ + Enabled = $true + OutputPath = 'outputs\AnotherPath.xml' + TestSuiteName = 'Pester' + } + Output = @{ + CIFormat = 'Auto' + StackTraceVerbosity = 'Filtered' + Verbosity = 'Detailed' + } +} diff --git a/tests/3-Advanced/Planets/Planets.Container.ps1 b/tests/3-Advanced/Planets/Planets.Container.ps1 new file mode 100644 index 00000000..dce74d95 --- /dev/null +++ b/tests/3-Advanced/Planets/Planets.Container.ps1 @@ -0,0 +1,8 @@ +@{ + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 | Select-Object -ExpandProperty FullName + Data = @{ + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 | Select-Object -ExpandProperty FullName + Debug = $false + Verbose = $false + } +} diff --git a/tests/Advanced/Planets/Planets.Data.ps1 b/tests/3-Advanced/Planets/Planets.Data.ps1 similarity index 100% rename from tests/Advanced/Planets/Planets.Data.ps1 rename to tests/3-Advanced/Planets/Planets.Data.ps1 diff --git a/tests/Advanced/Planets/Planets.Tests.ps1 b/tests/3-Advanced/Planets/Planets.Tests.ps1 similarity index 100% rename from tests/Advanced/Planets/Planets.Tests.ps1 rename to tests/3-Advanced/Planets/Planets.Tests.ps1 From 3f3efedbd8175ba699580fa7aeddb019753747ef Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 09:07:31 +0100 Subject: [PATCH 072/176] Add separate test jobs for Simple and Standard actions in GitHub workflow --- .github/workflows/Action-Test.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index a9c15339..3c90b8ff 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -17,18 +17,31 @@ permissions: pull-requests: read jobs: - ActionTestSimple: - name: Action-Test - [Simple] + ActionTest1Simple: + name: Action-Test - [1-Simple] runs-on: ubuntu-latest steps: # Need to check out as part of the test, as its a local action - name: Checkout repo uses: actions/checkout@v4 - - name: Action-Test [Simple] + - name: Action-Test [1-Simple] uses: ./ with: - Run_Path: tests/Simple + Run_Path: tests/1-Simple + + ActionTest2Standard: + name: Action-Test - [2-Standard] + runs-on: ubuntu-latest + steps: + # Need to check out as part of the test, as its a local action + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Action-Test [2-Standard] + uses: ./ + with: + Run_Path: tests/2-Standard ActionTestAdvanced: name: Action-Test - [3-Advanced] From 975daacfb54ca03aa03f2ca048226999ddac61a0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 09:11:59 +0100 Subject: [PATCH 073/176] Refactor Emoji tests to improve module importability and update data path for enhanced test reliability --- tests/2-Standard/Emoji.Container.ps1 | 2 +- tests/2-Standard/Emoji.Tests.ps1 | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/2-Standard/Emoji.Container.ps1 b/tests/2-Standard/Emoji.Container.ps1 index dce74d95..dacb12f9 100644 --- a/tests/2-Standard/Emoji.Container.ps1 +++ b/tests/2-Standard/Emoji.Container.ps1 @@ -1,7 +1,7 @@ @{ Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 | Select-Object -ExpandProperty FullName Data = @{ - Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Data.ps1 | Select-Object -ExpandProperty FullName + Path = Join-Path $PSScriptRoot -ChildPath 'Emoji.psm1' Debug = $false Verbose = $false } diff --git a/tests/2-Standard/Emoji.Tests.ps1 b/tests/2-Standard/Emoji.Tests.ps1 index fdbf208d..fe8544b9 100644 --- a/tests/2-Standard/Emoji.Tests.ps1 +++ b/tests/2-Standard/Emoji.Tests.ps1 @@ -1,4 +1,16 @@ -Describe 'Get-Emoji' { +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string] $Path +) + +Describe 'Emoji' { + It 'Module is importable' { + $null = Import-Module -Name $Path -PassThru + } +} + +Describe 'Get-Emoji' { Context 'Lookup by whole name' { It 'Returns 🌵 (cactus)' { Get-Emoji -Name cactus | Should -Be '🌵' From e102e511151b4298cc908ba2828d7f9da6a4e861 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 09:20:56 +0100 Subject: [PATCH 074/176] Refactor test result processing for improved readability and add PassThru option in configuration files --- scripts/main.ps1 | 5 +++-- tests/2-Standard/Emoji.Configuration.ps1 | 1 + tests/3-Advanced/Pester.Configuration.ps1 | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index af4df2f0..91c70af0 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -296,8 +296,9 @@ $summaryMarkdown = @" `````` "@ -foreach ($test in $testResults.Tests) { - $statusIcon = if ($test.Result -eq 'Passed') { '✅' } else { '❌' } +$testResults.Tests | ForEach-Object { + $test = $_ + $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" - $statusIcon $($test.Name) ($($test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding)) diff --git a/tests/2-Standard/Emoji.Configuration.ps1 b/tests/2-Standard/Emoji.Configuration.ps1 index 200ad6a4..8cef931a 100644 --- a/tests/2-Standard/Emoji.Configuration.ps1 +++ b/tests/2-Standard/Emoji.Configuration.ps1 @@ -2,6 +2,7 @@ Run = @{ Path = $PSScriptRoot Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* | ForEach-Object { . $_ } + PassThru = $true } TestResult = @{ Enabled = $true diff --git a/tests/3-Advanced/Pester.Configuration.ps1 b/tests/3-Advanced/Pester.Configuration.ps1 index 3d74517c..ab1fad7b 100644 --- a/tests/3-Advanced/Pester.Configuration.ps1 +++ b/tests/3-Advanced/Pester.Configuration.ps1 @@ -1,6 +1,7 @@ @{ Run = @{ - Path = $PSScriptRoot + Path = $PSScriptRoot + PassThru = $true } TestResult = @{ Enabled = $true From 06f06445835b56ecfd13053865495a36a0ddf0ad Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 09:39:15 +0100 Subject: [PATCH 075/176] Enhance test result output by adding test count display for improved visibility --- scripts/main.ps1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 91c70af0..42479b51 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -296,7 +296,10 @@ $summaryMarkdown = @" `````` "@ -$testResults.Tests | ForEach-Object { +$tests = $testResults.Tests +Write-Output "Test count: $($tests.Count)" + +$tests | ForEach-Object { $test = $_ $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" From 94f2e4b89d0d7f4c28e54489425a8bcbd39c08c6 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 09:46:01 +0100 Subject: [PATCH 076/176] Improve test output by adding processing details and enhance error handling in Emoji tests --- scripts/main.ps1 | 3 ++- tests/2-Standard/Emoji.Tests.ps1 | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 42479b51..ec259d60 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -300,13 +300,14 @@ $tests = $testResults.Tests Write-Output "Test count: $($tests.Count)" $tests | ForEach-Object { + Write-Output "Processing test: $($_.Name)" $test = $_ $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" - $statusIcon $($test.Name) ($($test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding)) "@ - if ($test.Result -eq 'Failed') { + if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { $summaryMarkdown += @" $($test.ErrorRecord.Exception.Message) diff --git a/tests/2-Standard/Emoji.Tests.ps1 b/tests/2-Standard/Emoji.Tests.ps1 index fe8544b9..82ef1e80 100644 --- a/tests/2-Standard/Emoji.Tests.ps1 +++ b/tests/2-Standard/Emoji.Tests.ps1 @@ -6,7 +6,7 @@ param( Describe 'Emoji' { It 'Module is importable' { - $null = Import-Module -Name $Path -PassThru + $null = Import-Module -Name $Path -PassThru | Should -Not -Throw } } From 004f1aa62e0e25bae5c52f2b23bb66bb148e304e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 09:48:34 +0100 Subject: [PATCH 077/176] Enhance test summary output by formatting duration for improved readability --- scripts/main.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index ec259d60..0c1d7a89 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -294,6 +294,7 @@ $summaryMarkdown = @"

`````` + "@ $tests = $testResults.Tests @@ -303,8 +304,9 @@ $tests | ForEach-Object { Write-Output "Processing test: $($_.Name)" $test = $_ $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' + $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @" -- $statusIcon $($test.Name) ($($test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding)) +- $statusIcon $($test.Name) - $formattedDuration "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { From cc2e9941b28867b571926a08d4090d920fef148b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 09:51:19 +0100 Subject: [PATCH 078/176] Add debugging step to GitHub Actions and link to run summary in test output --- .github/workflows/Action-Test.yml | 6 ++++++ scripts/main.ps1 | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index 3c90b8ff..68d98bb9 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -25,6 +25,8 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 + - uses: PSModule/Debug@v0 + - name: Action-Test [1-Simple] uses: ./ with: @@ -38,6 +40,8 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 + - uses: PSModule/Debug@v0 + - name: Action-Test [2-Standard] uses: ./ with: @@ -51,6 +55,8 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 + - uses: PSModule/Debug@v0 + - name: Action-Test [3-Advanced] uses: ./ with: diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 0c1d7a89..c3aa003b 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -323,6 +323,12 @@ $summaryMarkdown += @" "@ +# Add a link to the run summary in the GitHub Actions log +$summaryMarkdown += @" +[View the full test run details in the GitHub Actions log]($env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY/actions/runs/$env:GITHUB_RUN_ID) + +"@ + Set-GitHubStepSummary -Summary $summaryMarkdown exit $failedTests From 3b4cf68d9b69d2939e0fa610f2496f05bc519de6 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:02:25 +0100 Subject: [PATCH 079/176] Refactor test output processing to streamline test iteration and remove redundant summary link --- scripts/main.ps1 | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index c3aa003b..2a58f6ad 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -297,11 +297,7 @@ $summaryMarkdown = @" "@ -$tests = $testResults.Tests -Write-Output "Test count: $($tests.Count)" - -$tests | ForEach-Object { - Write-Output "Processing test: $($_.Name)" +$testResults.Tests | ForEach-Object { $test = $_ $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding @@ -323,12 +319,6 @@ $summaryMarkdown += @" "@ -# Add a link to the run summary in the GitHub Actions log -$summaryMarkdown += @" -[View the full test run details in the GitHub Actions log]($env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY/actions/runs/$env:GITHUB_RUN_ID) - -"@ - Set-GitHubStepSummary -Summary $summaryMarkdown exit $failedTests From c8ac62f0ab07a796054ad366f008334129aa56b4 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:13:43 +0100 Subject: [PATCH 080/176] Add output paths for artifacts upload in GitHub Actions --- scripts/main.ps1 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 2a58f6ad..c434699d 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -321,4 +321,11 @@ $summaryMarkdown += @" Set-GitHubStepSummary -Summary $summaryMarkdown +# Output paths for artifacts upload +$testResults.CodeCoverage.OutputPath +Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $testResults.CodeCoverage.OutputPath + +$testResults.TestResult.OutputPath +Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResults.TestResult.OutputPath + exit $failedTests From 233fc62c7217a031c034a3cac186f6485ffbc43a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:16:04 +0100 Subject: [PATCH 081/176] Add checks for output paths in GitHub Actions and log warnings if not found --- scripts/main.ps1 | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index c434699d..4e5da7ba 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -322,10 +322,16 @@ $summaryMarkdown += @" Set-GitHubStepSummary -Summary $summaryMarkdown # Output paths for artifacts upload -$testResults.CodeCoverage.OutputPath -Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $testResults.CodeCoverage.OutputPath +if ($testResults.CodeCoverage.OutputPath) { + Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $testResults.CodeCoverage.OutputPath +} else { + Write-GitHubWarning 'No code coverage output path found.' +} -$testResults.TestResult.OutputPath -Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResults.TestResult.OutputPath +if ($testResults.TestResult.OutputPath) { + Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResults.TestResult.OutputPath +} else { + Write-GitHubWarning 'No test result output path found.' +} exit $failedTests From df764608413a2e45232bc0fb7d948670a9332d6c Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:18:14 +0100 Subject: [PATCH 082/176] Refactor output path handling in GitHub Actions to improve clarity and maintainability --- scripts/main.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 4e5da7ba..7ff33f92 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -322,14 +322,16 @@ $summaryMarkdown += @" Set-GitHubStepSummary -Summary $summaryMarkdown # Output paths for artifacts upload -if ($testResults.CodeCoverage.OutputPath) { - Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $testResults.CodeCoverage.OutputPath +$codeCoverageOutputPath = $testResults.Configuration.CodeCoverage.OutputPath +if ($codeCoverageOutputPath) { + Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $codeCoverageOutputPath } else { Write-GitHubWarning 'No code coverage output path found.' } -if ($testResults.TestResult.OutputPath) { - Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResults.TestResult.OutputPath +$testResultOutputPath = $testResults.Configuration.TestResult.OutputPath +if ($testResultOutputPath) { + Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResultOutputPath } else { Write-GitHubWarning 'No test result output path found.' } From 7ad526905bb8f318f1aadfc2fe43178f86d60986 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:19:53 +0100 Subject: [PATCH 083/176] Fix output path retrieval for code coverage and test results in GitHub Actions --- scripts/main.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 7ff33f92..8f151ed7 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -322,14 +322,14 @@ $summaryMarkdown += @" Set-GitHubStepSummary -Summary $summaryMarkdown # Output paths for artifacts upload -$codeCoverageOutputPath = $testResults.Configuration.CodeCoverage.OutputPath +$codeCoverageOutputPath = $testResults.Configuration.CodeCoverage.OutputPath.Value if ($codeCoverageOutputPath) { Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $codeCoverageOutputPath } else { Write-GitHubWarning 'No code coverage output path found.' } -$testResultOutputPath = $testResults.Configuration.TestResult.OutputPath +$testResultOutputPath = $testResults.Configuration.TestResult.OutputPath.Value if ($testResultOutputPath) { Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResultOutputPath } else { From d690590e49c8b767c9d889f99cde24c1ecc7dc0b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:27:21 +0100 Subject: [PATCH 084/176] Update output paths for code coverage and test results in GitHub Actions --- scripts/Pester.Configuration.ps1 | 4 ++-- scripts/main.ps1 | 15 ++------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/scripts/Pester.Configuration.ps1 b/scripts/Pester.Configuration.ps1 index e751b494..e991d09a 100644 --- a/scripts/Pester.Configuration.ps1 +++ b/scripts/Pester.Configuration.ps1 @@ -23,7 +23,7 @@ CodeCoverage = @{ Enabled = $true OutputFormat = 'JaCoCo' - OutputPath = 'CodeCoverage-Report.xml' + OutputPath = 'test_reports/CodeCoverage-Report.xml' OutputEncoding = 'UTF8' Path = @() ExcludeTests = $true @@ -35,7 +35,7 @@ TestResult = @{ Enabled = $true OutputFormat = 'NUnitXml' - OutputPath = 'outputs\Test-Report.xml' + OutputPath = 'test_reports/TestResult-Report.xml' OutputEncoding = 'UTF8' TestSuiteName = 'Unit tests' } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 8f151ed7..705b90c5 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -322,18 +322,7 @@ $summaryMarkdown += @" Set-GitHubStepSummary -Summary $summaryMarkdown # Output paths for artifacts upload -$codeCoverageOutputPath = $testResults.Configuration.CodeCoverage.OutputPath.Value -if ($codeCoverageOutputPath) { - Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $codeCoverageOutputPath -} else { - Write-GitHubWarning 'No code coverage output path found.' -} - -$testResultOutputPath = $testResults.Configuration.TestResult.OutputPath.Value -if ($testResultOutputPath) { - Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResultOutputPath -} else { - Write-GitHubWarning 'No test result output path found.' -} +Set-GitHubOutput -Name 'CodeCoverageConfig' -Value $testResults.Configuration.CodeCoverage +Set-GitHubOutput -Name 'TestResultConfig' -Value $testResults.Configuration.TestResult exit $failedTests From 057c7a6d75e49e2303c6792d79bec7ce206b7b10 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:30:09 +0100 Subject: [PATCH 085/176] Convert output values to JSON format for artifacts upload in GitHub Actions --- scripts/main.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 705b90c5..822a70e1 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -322,7 +322,7 @@ $summaryMarkdown += @" Set-GitHubStepSummary -Summary $summaryMarkdown # Output paths for artifacts upload -Set-GitHubOutput -Name 'CodeCoverageConfig' -Value $testResults.Configuration.CodeCoverage -Set-GitHubOutput -Name 'TestResultConfig' -Value $testResults.Configuration.TestResult +Set-GitHubOutput -Name 'CodeCoverageConfig' -Value ($testResults.Configuration.CodeCoverage | ConvertTo-Json -Depth 5 ) +Set-GitHubOutput -Name 'TestResultConfig' -Value ($testResults.Configuration.TestResult | ConvertTo-Json -Depth 5 ) exit $failedTests From 022dab27dbd1ace5f5a964ba4d5fa3512fa9ebf8 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:34:08 +0100 Subject: [PATCH 086/176] Add additional output paths for test results and code coverage in GitHub Actions --- scripts/main.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 822a70e1..4c9240b3 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -322,7 +322,9 @@ $summaryMarkdown += @" Set-GitHubStepSummary -Summary $summaryMarkdown # Output paths for artifacts upload -Set-GitHubOutput -Name 'CodeCoverageConfig' -Value ($testResults.Configuration.CodeCoverage | ConvertTo-Json -Depth 5 ) Set-GitHubOutput -Name 'TestResultConfig' -Value ($testResults.Configuration.TestResult | ConvertTo-Json -Depth 5 ) +Set-GitHubOutput -Name 'CodeCoverageConfig' -Value ($testResults.Configuration.CodeCoverage | ConvertTo-Json -Depth 5 ) +Set-GitHubOutput -Name 'TestResults' -Value ($testResults | Select-Object -ExcludeProperty CodeCoverage | ConvertTo-Json -Depth 5 ) +Set-GitHubOutput -Name 'CodeCoverageResults' -Value ($testResults.CodeCoverage | ConvertTo-Json -Depth 5 ) exit $failedTests From b794146665b3b110deab8027764ff3b7edc4685d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:36:36 +0100 Subject: [PATCH 087/176] Reduce JSON conversion depth for test results and code coverage outputs in GitHub Actions --- scripts/main.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 4c9240b3..cc728444 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -324,7 +324,7 @@ Set-GitHubStepSummary -Summary $summaryMarkdown # Output paths for artifacts upload Set-GitHubOutput -Name 'TestResultConfig' -Value ($testResults.Configuration.TestResult | ConvertTo-Json -Depth 5 ) Set-GitHubOutput -Name 'CodeCoverageConfig' -Value ($testResults.Configuration.CodeCoverage | ConvertTo-Json -Depth 5 ) -Set-GitHubOutput -Name 'TestResults' -Value ($testResults | Select-Object -ExcludeProperty CodeCoverage | ConvertTo-Json -Depth 5 ) -Set-GitHubOutput -Name 'CodeCoverageResults' -Value ($testResults.CodeCoverage | ConvertTo-Json -Depth 5 ) +Set-GitHubOutput -Name 'TestResults' -Value ($testResults | Select-Object -ExcludeProperty CodeCoverage | ConvertTo-Json -Depth 1 ) +Set-GitHubOutput -Name 'CodeCoverageResults' -Value ($testResults.CodeCoverage | ConvertTo-Json -Depth 1 ) exit $failedTests From deb4cf0c090dba33f418e9b4227b55f89aa69157 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:41:16 +0100 Subject: [PATCH 088/176] Refactor output handling for test results in GitHub Actions and improve module import test --- scripts/main.ps1 | 9 ++++----- tests/2-Standard/Emoji.Tests.ps1 | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index cc728444..23f1319a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -321,10 +321,9 @@ $summaryMarkdown += @" Set-GitHubStepSummary -Summary $summaryMarkdown -# Output paths for artifacts upload -Set-GitHubOutput -Name 'TestResultConfig' -Value ($testResults.Configuration.TestResult | ConvertTo-Json -Depth 5 ) -Set-GitHubOutput -Name 'CodeCoverageConfig' -Value ($testResults.Configuration.CodeCoverage | ConvertTo-Json -Depth 5 ) -Set-GitHubOutput -Name 'TestResults' -Value ($testResults | Select-Object -ExcludeProperty CodeCoverage | ConvertTo-Json -Depth 1 ) -Set-GitHubOutput -Name 'CodeCoverageResults' -Value ($testResults.CodeCoverage | ConvertTo-Json -Depth 1 ) +# For each property of testresults, output the value as a JSON object +foreach ($property in $testResults.PSObject.Properties) { + Set-GitHubOutput -Name $property.Name -Value ($property.Value | ConvertTo-Json -Depth 5) +} exit $failedTests diff --git a/tests/2-Standard/Emoji.Tests.ps1 b/tests/2-Standard/Emoji.Tests.ps1 index 82ef1e80..78f88ae3 100644 --- a/tests/2-Standard/Emoji.Tests.ps1 +++ b/tests/2-Standard/Emoji.Tests.ps1 @@ -6,7 +6,7 @@ param( Describe 'Emoji' { It 'Module is importable' { - $null = Import-Module -Name $Path -PassThru | Should -Not -Throw + { Import-Module -Name $Path } | Should -Not -Throw } } From 479c2acdc6628c3d4936a292c909b73e43076362 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:47:40 +0100 Subject: [PATCH 089/176] Add debug mode option and improve output handling in GitHub Actions --- .github/workflows/Action-Test.yml | 6 -- action.yml | 9 ++- scripts/main.ps1 | 5 +- .../{Get-Emoji.Tests.ps1 => Emoji.Tests.ps1} | 0 tests/3-Advanced/Emoji/Emoji.Container.ps1 | 8 +++ tests/3-Advanced/Emoji/Emoji.Tests.ps1 | 61 +++++++++++++++++++ tests/3-Advanced/Emoji/Emoji.psm1 | 15 +++++ 7 files changed, 96 insertions(+), 8 deletions(-) rename tests/1-Simple/{Get-Emoji.Tests.ps1 => Emoji.Tests.ps1} (100%) create mode 100644 tests/3-Advanced/Emoji/Emoji.Container.ps1 create mode 100644 tests/3-Advanced/Emoji/Emoji.Tests.ps1 create mode 100644 tests/3-Advanced/Emoji/Emoji.psm1 diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index 68d98bb9..3c90b8ff 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -25,8 +25,6 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 - - uses: PSModule/Debug@v0 - - name: Action-Test [1-Simple] uses: ./ with: @@ -40,8 +38,6 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 - - uses: PSModule/Debug@v0 - - name: Action-Test [2-Standard] uses: ./ with: @@ -55,8 +51,6 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 - - uses: PSModule/Debug@v0 - - name: Action-Test [3-Advanced] uses: ./ with: diff --git a/action.yml b/action.yml index a7728ca0..a2cb371c 100644 --- a/action.yml +++ b/action.yml @@ -187,7 +187,11 @@ inputs: Path to the configuration file. required: false default: '${{ github.workspace }}/.github/pester.settings.ps1' - + Debug: + description: | + Enable debug mode. + required: false + default: 'false' outputs: result: description: If the tests passed. @@ -196,6 +200,9 @@ outputs: runs: using: composite steps: + - uses: PSModule/Debug@v0 + if: ${{ inputs.Debug == 'true' }} + - name: Invoke-Pester uses: PSModule/GitHub-Script@v1 id: test diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 23f1319a..dea8b7cd 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -323,7 +323,10 @@ Set-GitHubStepSummary -Summary $summaryMarkdown # For each property of testresults, output the value as a JSON object foreach ($property in $testResults.PSObject.Properties) { - Set-GitHubOutput -Name $property.Name -Value ($property.Value | ConvertTo-Json -Depth 5) + Write-Verbose "Setting output for [$($property.Name)]" -Verbose + $name = $property.Name + $value = $null -ne $property.Value ? ($property.Value | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) : '' + Set-GitHubOutput -Name $name -Value $value } exit $failedTests diff --git a/tests/1-Simple/Get-Emoji.Tests.ps1 b/tests/1-Simple/Emoji.Tests.ps1 similarity index 100% rename from tests/1-Simple/Get-Emoji.Tests.ps1 rename to tests/1-Simple/Emoji.Tests.ps1 diff --git a/tests/3-Advanced/Emoji/Emoji.Container.ps1 b/tests/3-Advanced/Emoji/Emoji.Container.ps1 new file mode 100644 index 00000000..dacb12f9 --- /dev/null +++ b/tests/3-Advanced/Emoji/Emoji.Container.ps1 @@ -0,0 +1,8 @@ +@{ + Path = Get-ChildItem -Path $PSScriptRoot -Filter *.Tests.ps1 | Select-Object -ExpandProperty FullName + Data = @{ + Path = Join-Path $PSScriptRoot -ChildPath 'Emoji.psm1' + Debug = $false + Verbose = $false + } +} diff --git a/tests/3-Advanced/Emoji/Emoji.Tests.ps1 b/tests/3-Advanced/Emoji/Emoji.Tests.ps1 new file mode 100644 index 00000000..78f88ae3 --- /dev/null +++ b/tests/3-Advanced/Emoji/Emoji.Tests.ps1 @@ -0,0 +1,61 @@ +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string] $Path +) + +Describe 'Emoji' { + It 'Module is importable' { + { Import-Module -Name $Path } | Should -Not -Throw + } +} + +Describe 'Get-Emoji' { + Context 'Lookup by whole name' { + It 'Returns 🌵 (cactus)' { + Get-Emoji -Name cactus | Should -Be '🌵' + } + + It 'Returns 🦒 (giraffe)' { + Get-Emoji -Name giraffe | Should -Be '🦒' + } + } + + Context 'Lookup by wildcard' { + Context 'by prefix' { + BeforeAll { + $emojis = Get-Emoji -Name pen* + } + + It 'Returns ✏️ (pencil)' { + $emojis | Should -Contain '✏️' + } + + It 'Returns 🐧 (penguin)' { + $emojis | Should -Contain '🐧' + } + + It 'Returns 😔 (pensive)' { + $emojis | Should -Contain '😔' + } + } + + Context 'by contains' { + BeforeAll { + $emojis = Get-Emoji -Name *smiling* + } + + It 'Returns 🙂 (slightly smiling face)' { + $emojis | Should -Contain '🙂' + } + + It 'Returns 😁 (beaming face with smiling eyes)' { + $emojis | Should -Contain '😁' + } + + It 'Returns 😊 (smiling face with smiling eyes)' { + $emojis | Should -Contain '😊' + } + } + } +} diff --git a/tests/3-Advanced/Emoji/Emoji.psm1 b/tests/3-Advanced/Emoji/Emoji.psm1 new file mode 100644 index 00000000..d27e0317 --- /dev/null +++ b/tests/3-Advanced/Emoji/Emoji.psm1 @@ -0,0 +1,15 @@ +$script:emojis = @( + @{ Name = 'apple'; Symbol = '🍎'; Kind = 'Fruit' } + @{ Name = 'beaming face with smiling eyes'; Symbol = '😁'; Kind = 'Face' } + @{ Name = 'cactus'; Symbol = '🌵'; Kind = 'Plant' } + @{ Name = 'giraffe'; Symbol = '🦒'; Kind = 'Animal' } + @{ Name = 'pencil'; Symbol = '✏️'; Kind = 'Item' } + @{ Name = 'penguin'; Symbol = '🐧'; Kind = 'Animal' } + @{ Name = 'pensive'; Symbol = '😔'; Kind = 'Face' } + @{ Name = 'slightly smiling face'; Symbol = '🙂'; Kind = 'Face' } + @{ Name = 'smiling face with smiling eyes'; Symbol = '😊'; Kind = 'Face' } +) | ForEach-Object { [PSCustomObject]$_ } + +function Get-Emoji ([string]$Name = '*') { + $script:emojis | Where-Object Name -Like $Name | ForEach-Object Symbol +} From cedd01cd89ab08153e1e579cd6665d19abb0c143 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:51:27 +0100 Subject: [PATCH 090/176] Update README with nested details section and improve output handling in main.ps1 --- README.md | 13 +++++++++++++ scripts/main.ps1 | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3e74c20c..49c9c0b5 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,18 @@ A template repository for GitHub Actions +

+ Outer Details + Outer details content. + +
+ Inner Details + Inner details content. +
+ + More outer details content. +
+ ## Usage ### Inputs @@ -15,3 +27,4 @@ A template repository for GitHub Actions ```yaml Example here ``` + diff --git a/scripts/main.ps1 b/scripts/main.ps1 index dea8b7cd..f1dab11d 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -325,7 +325,7 @@ Set-GitHubStepSummary -Summary $summaryMarkdown foreach ($property in $testResults.PSObject.Properties) { Write-Verbose "Setting output for [$($property.Name)]" -Verbose $name = $property.Name - $value = $null -ne $property.Value ? ($property.Value | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) : '' + $value = -not [string]::IsNullOrEmpty($property.Value) ? ($property.Value | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) : '' Set-GitHubOutput -Name $name -Value $value } From 99f958c4c952533d11aeca3d060ee032be69317b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:53:11 +0100 Subject: [PATCH 091/176] Reduce JSON conversion depth for output values in main.ps1 --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index f1dab11d..e35ffeb1 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -325,7 +325,7 @@ Set-GitHubStepSummary -Summary $summaryMarkdown foreach ($property in $testResults.PSObject.Properties) { Write-Verbose "Setting output for [$($property.Name)]" -Verbose $name = $property.Name - $value = -not [string]::IsNullOrEmpty($property.Value) ? ($property.Value | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) : '' + $value = -not [string]::IsNullOrEmpty($property.Value) ? ($property.Value | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) : '' Set-GitHubOutput -Name $name -Value $value } From d549a0c48e78f32f686d898bfbbbb40a7dabd556 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 10:57:55 +0100 Subject: [PATCH 092/176] Refactor Emoji.Configuration.ps1 to improve structure and clarify output settings --- tests/2-Standard/Emoji.Configuration.ps1 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/2-Standard/Emoji.Configuration.ps1 b/tests/2-Standard/Emoji.Configuration.ps1 index 8cef931a..43798070 100644 --- a/tests/2-Standard/Emoji.Configuration.ps1 +++ b/tests/2-Standard/Emoji.Configuration.ps1 @@ -1,15 +1,18 @@ @{ - Run = @{ + Run = @{ Path = $PSScriptRoot Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* | ForEach-Object { . $_ } PassThru = $true } - TestResult = @{ + TestResult = @{ Enabled = $true OutputPath = 'outputs\AnotherPath.xml' TestSuiteName = 'Pester' } - Output = @{ + CodeCoverage = @{ + Path = 'Emoji.psm1' + } + Output = @{ CIFormat = 'Auto' StackTraceVerbosity = 'Filtered' Verbosity = 'Detailed' From 74c41e4c4792513fbe4d83dafd0384a4bb6beed0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 11:01:18 +0100 Subject: [PATCH 093/176] Enhance test results summary header to include test suite name --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index e35ffeb1..24c89d5b 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -283,7 +283,7 @@ if ($configuration.CodeCoverage.Enabled) { $statusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } $summaryMarkdown = @" -### $statusIcon - Test Results +### $statusIcon - Test Results for '$($configuration.TestResult.TestSuiteName)' | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | From 6609b3087c631a8fe49f8fd1910197cc2d1112ac Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 11:02:46 +0100 Subject: [PATCH 094/176] Update test results summary to use a table format and include test suite name in details --- scripts/main.ps1 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 24c89d5b..dfb397ab 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -283,14 +283,12 @@ if ($configuration.CodeCoverage.Enabled) { $statusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } $summaryMarkdown = @" -### $statusIcon - Test Results for '$($configuration.TestResult.TestSuiteName)' +| Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | +| ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | +| $statusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | -| Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | -| ----- | ------ | ------ | ------- | ------------ | ------ | -------- | -| $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | - -
Details +
$($configuration.TestResult.TestSuiteName) - Details

`````` From fd8388266056ffea5143da86ead2350fccf7856f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 11:47:59 +0100 Subject: [PATCH 095/176] Refactor test results summary in main.ps1 to use a markdown format with detailed container information and improve readability --- scripts/main.ps1 | 119 +++++++++++++++++----- tests/3-Advanced/Pester.Configuration.ps1 | 6 +- 2 files changed, 97 insertions(+), 28 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index dfb397ab..f619cdf3 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -282,40 +282,107 @@ if ($configuration.CodeCoverage.Enabled) { $statusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } -$summaryMarkdown = @" -| Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | -| ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | -| $statusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | +################################################################################# + +# Initialize a markdown string builder (using backtick-n for newlines in double-quoted strings) +$summaryMarkdown = "# Pester Test Results`n`n" + +foreach ($container in $TestResults.Containers) { + # Determine container name for display (file name or a label for scriptblock) + $containerPath = $null + $containerName = 'Test Container' + if ($container.Type -eq 'File') { + $containerPath = [string]$container.Path # ensure it's a string + $containerName = [System.IO.Path]::GetFileName($containerPath) # just the file name + } elseif ($container.Type -eq 'ScriptBlock') { + # For scriptblock containers, use a generic name or the start line + $containerName = 'ScriptBlock Tests' + if ($container.Content) { + $containerName = "ScriptBlock ($($container.Content.File):$($container.Content.StartPosition.StartLine))" + } + } + # Gather summary counts + $passed = $container.PassedCount + $failed = $container.FailedCount + $skipped = $container.SkippedCount + + # Add a details section for this container + $summaryMarkdown += "

$containerName - Passed: $passed, Failed: $failed, Skipped: $skipped`n`n" + + # List each test in the container + foreach ($test in $container.Tests) { + # Determine status icon and test name + $status = '✅' # assume passed + $outcome = 'Passed' + if (-not $test.Executed -or -not $test.Passed) { + # If not executed (skipped) or failed + if (-not $test.ShouldRun) { + $status = '⚠️' # skipped test icon (could also use 🚫 or another symbol) + $outcome = 'Skipped' + } else { + $status = '❌' + $outcome = 'Failed' + } + } -
$($configuration.TestResult.TestSuiteName) - Details -

+ # Build test name or full description. + # If the test object has a Name property: + $testName = $test.Name + # If needed, include context/describe info: + # e.g. $fullName = ($test.BlockPath -join ' > ') + " > $($test.Name)" -`````` + # Include failure message for failed tests + $failureDetails = '' + if ($outcome -eq 'Failed' -and $test.FailureMessage) { + $failureDetails = " – $($test.FailureMessage)" + } -"@ + # Append the bullet list entry + $summaryMarkdown += "- $status **$testName** $failureDetails`n" + } -$testResults.Tests | ForEach-Object { - $test = $_ - $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' - $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding - $summaryMarkdown += @" -- $statusIcon $($test.Name) - $formattedDuration + # Close the details tag and add an extra newline + $summaryMarkdown += "

`n`n" +} -"@ - if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { - $summaryMarkdown += @" - $($test.ErrorRecord.Exception.Message) -"@ - } -} -$summaryMarkdown += @" -`````` +################################################################################# + +# $summaryMarkdown = @" +# | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | +# | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | +# | $statusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | + + +#
$($configuration.TestResult.TestSuiteName) - Details +#

+ +# `````` + +# "@ + +# $testResults.Tests | ForEach-Object { +# $test = $_ +# $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' +# $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding +# $summaryMarkdown += @" +# - $statusIcon $($test.Name) - $formattedDuration + +# "@ +# if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { +# $summaryMarkdown += @" +# $($test.ErrorRecord.Exception.Message) + +# "@ +# } +# } +# $summaryMarkdown += @" +# `````` -

-
-"@ +#

+#
+# "@ Set-GitHubStepSummary -Summary $summaryMarkdown diff --git a/tests/3-Advanced/Pester.Configuration.ps1 b/tests/3-Advanced/Pester.Configuration.ps1 index ab1fad7b..066f53b9 100644 --- a/tests/3-Advanced/Pester.Configuration.ps1 +++ b/tests/3-Advanced/Pester.Configuration.ps1 @@ -1,7 +1,9 @@ @{ Run = @{ - Path = $PSScriptRoot - PassThru = $true + Path = $PSScriptRoot + PassThru = $true + Container = Get-ChildItem -Path $config.Run.Path.Value -Filter *.Container.* -Recurse | + ForEach-Object { . $_ } | ForEach-Object { New-PesterContainer @_ } } TestResult = @{ Enabled = $true From 0fef68290e9e980d948b3041851b362043ed8f5c Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 11:53:04 +0100 Subject: [PATCH 096/176] Refactor Pester test results summary in main.ps1 to enhance markdown formatting and improve readability --- scripts/main.ps1 | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index f619cdf3..8e77ffc5 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -285,9 +285,13 @@ $statusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } ################################################################################# # Initialize a markdown string builder (using backtick-n for newlines in double-quoted strings) -$summaryMarkdown = "# Pester Test Results`n`n" +$summaryMarkdown = @' +## Pester Test Results + +'@ foreach ($container in $TestResults.Containers) { + Write-Verbose "Processing container: $($container.Name)-$($container.Type)-$($container.Path)" -Verbose # Determine container name for display (file name or a label for scriptblock) $containerPath = $null $containerName = 'Test Container' @@ -308,10 +312,14 @@ foreach ($container in $TestResults.Containers) { $skipped = $container.SkippedCount # Add a details section for this container - $summaryMarkdown += "
$containerName - Passed: $passed, Failed: $failed, Skipped: $skipped`n`n" + $summaryMarkdown += @" +
$containerName - Passed: $passed, Failed: $failed, Skipped: $skipped + +"@ # List each test in the container foreach ($test in $container.Tests) { + Write-Verbose "Processing test: $($test.Name)" -Verbose # Determine status icon and test name $status = '✅' # assume passed $outcome = 'Passed' @@ -339,11 +347,17 @@ foreach ($container in $TestResults.Containers) { } # Append the bullet list entry - $summaryMarkdown += "- $status **$testName** $failureDetails`n" + $summaryMarkdown += @" +- $status **$testName** $failureDetails + +"@ } # Close the details tag and add an extra newline - $summaryMarkdown += "
`n`n" + $summaryMarkdown += @' +
+ +'@ } From 426a87839c36316d530ea9f4ce473750869b6c29 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 11:56:11 +0100 Subject: [PATCH 097/176] Add verbose logging for test processing in main.ps1 --- scripts/main.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 8e77ffc5..7e1f3d38 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -318,6 +318,7 @@ foreach ($container in $TestResults.Containers) { "@ # List each test in the container + Write-Verbose "Processing [$($container.Tests.Count)]tests in container: $($container.Name)" -Verbose foreach ($test in $container.Tests) { Write-Verbose "Processing test: $($test.Name)" -Verbose # Determine status icon and test name From a270782d203688b2f6da9ee591e410721f053917 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:11:42 +0100 Subject: [PATCH 098/176] Refactor test results summary in main.ps1 to include test suite name and improve formatting with a detailed bullet list --- scripts/main.ps1 | 126 +++++++++-------------------------------------- 1 file changed, 23 insertions(+), 103 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 7e1f3d38..ae350d6f 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -282,122 +282,42 @@ if ($configuration.CodeCoverage.Enabled) { $statusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } -################################################################################# - -# Initialize a markdown string builder (using backtick-n for newlines in double-quoted strings) -$summaryMarkdown = @' -## Pester Test Results - -'@ - -foreach ($container in $TestResults.Containers) { - Write-Verbose "Processing container: $($container.Name)-$($container.Type)-$($container.Path)" -Verbose - # Determine container name for display (file name or a label for scriptblock) - $containerPath = $null - $containerName = 'Test Container' - if ($container.Type -eq 'File') { - $containerPath = [string]$container.Path # ensure it's a string - $containerName = [System.IO.Path]::GetFileName($containerPath) # just the file name - } elseif ($container.Type -eq 'ScriptBlock') { - # For scriptblock containers, use a generic name or the start line - $containerName = 'ScriptBlock Tests' - if ($container.Content) { - $containerName = "ScriptBlock ($($container.Content.File):$($container.Content.StartPosition.StartLine))" - } - } +$summaryMarkdown = @" +## '$($configuration.TestResult.TestSuiteName)' - Test Results - # Gather summary counts - $passed = $container.PassedCount - $failed = $container.FailedCount - $skipped = $container.SkippedCount +| Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | +| ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | +| $statusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | - # Add a details section for this container - $summaryMarkdown += @" -
$containerName - Passed: $passed, Failed: $failed, Skipped: $skipped -"@ +
- Details +

- # List each test in the container - Write-Verbose "Processing [$($container.Tests.Count)]tests in container: $($container.Name)" -Verbose - foreach ($test in $container.Tests) { - Write-Verbose "Processing test: $($test.Name)" -Verbose - # Determine status icon and test name - $status = '✅' # assume passed - $outcome = 'Passed' - if (-not $test.Executed -or -not $test.Passed) { - # If not executed (skipped) or failed - if (-not $test.ShouldRun) { - $status = '⚠️' # skipped test icon (could also use 🚫 or another symbol) - $outcome = 'Skipped' - } else { - $status = '❌' - $outcome = 'Failed' - } - } +`````` - # Build test name or full description. - # If the test object has a Name property: - $testName = $test.Name - # If needed, include context/describe info: - # e.g. $fullName = ($test.BlockPath -join ' > ') + " > $($test.Name)" +"@ - # Include failure message for failed tests - $failureDetails = '' - if ($outcome -eq 'Failed' -and $test.FailureMessage) { - $failureDetails = " – $($test.FailureMessage)" - } +$testResults.Tests | ForEach-Object { + $test = $_ + $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' + $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding + $summaryMarkdown += @" +- $statusIcon $($test.Name) - $formattedDuration - # Append the bullet list entry +"@ + if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { $summaryMarkdown += @" -- $status **$testName** $failureDetails + $($test.ErrorRecord.Exception.Message) "@ } - - # Close the details tag and add an extra newline - $summaryMarkdown += @' -

- -'@ } +$summaryMarkdown += @" +`````` - -################################################################################# - -# $summaryMarkdown = @" -# | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | -# | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | -# | $statusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | - - -#
$($configuration.TestResult.TestSuiteName) - Details -#

- -# `````` - -# "@ - -# $testResults.Tests | ForEach-Object { -# $test = $_ -# $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' -# $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding -# $summaryMarkdown += @" -# - $statusIcon $($test.Name) - $formattedDuration - -# "@ -# if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { -# $summaryMarkdown += @" -# $($test.ErrorRecord.Exception.Message) - -# "@ -# } -# } -# $summaryMarkdown += @" -# `````` - -#

-#
-# "@ +

+
+"@ Set-GitHubStepSummary -Summary $summaryMarkdown From 7aaf68e7a2ae510c9f5d7d85598b9cc81aaae532 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:12:16 +0100 Subject: [PATCH 099/176] Refactor test results summary in main.ps1 to include container details and improve markdown formatting --- scripts/main.ps1 | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index ae350d6f..e1864465 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -289,36 +289,44 @@ $summaryMarkdown = @" | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $statusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | +"@ -
- Details +foreach ($container in $testResult.Container) { + $containerPath = $container.Item.FullName + $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' + $summaryMarkdown += @" +
$containerName - Details

-`````` - +Path: $containerPath "@ -$testResults.Tests | ForEach-Object { - $test = $_ - $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' - $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding - $summaryMarkdown += @" + $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item -eq $containerPath } | ForEach-Object { + $test = $_ + $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' + $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding + $summaryMarkdown += @" - $statusIcon $($test.Name) - $formattedDuration "@ - if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { - $summaryMarkdown += @" + if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { + $summaryMarkdown += @" $($test.ErrorRecord.Exception.Message) "@ + } } -} -$summaryMarkdown += @" + + $summaryMarkdown += @" ``````

"@ +} + + Set-GitHubStepSummary -Summary $summaryMarkdown # For each property of testresults, output the value as a JSON object From 0a823e9101dcced5e58efcb4ad3617f030abb4b7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:14:38 +0100 Subject: [PATCH 100/176] Fix variable name for container iteration in main.ps1 --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index e1864465..096e4881 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -291,7 +291,7 @@ $summaryMarkdown = @" "@ -foreach ($container in $testResult.Container) { +foreach ($container in $testResult.Containers) { $containerPath = $container.Item.FullName $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' $summaryMarkdown += @" From 5d9841e738e62194efd7cf3f6632894a82281193 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:24:42 +0100 Subject: [PATCH 101/176] Enhance test results summary formatting and add verbose logging for container processing in main.ps1 --- scripts/main.ps1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 096e4881..9097817b 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -283,7 +283,7 @@ if ($configuration.CodeCoverage.Enabled) { $statusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } $summaryMarkdown = @" -## '$($configuration.TestResult.TestSuiteName)' - Test Results +### '$($configuration.TestResult.TestSuiteName)' - Test Results | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | @@ -291,14 +291,18 @@ $summaryMarkdown = @" "@ +Write-Verbose "Processing containers [$($testResult.Containers.Count)]" -Verbose foreach ($container in $testResult.Containers) { $containerPath = $container.Item.FullName + Write-Verbose "Processing container [$containerPath]" -Verbose $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' + Write-Verbose "Container name: [$containerName]" -Verbose $summaryMarkdown += @"
$containerName - Details

Path: $containerPath + "@ $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item -eq $containerPath } | ForEach-Object { From 9321073cfcd75014aa30042ac6b1e65c790f5bf8 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:29:46 +0100 Subject: [PATCH 102/176] Refactor test results summary in main.ps1 to improve container details and ensure structured JSON output --- scripts/main.ps1 | 51 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 9097817b..b7470508 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -260,11 +260,6 @@ LogGroup 'Test results' { if ($failedTests -eq 0) { Write-GitHubNotice '✅ All tests passed.' } - - $results = $testResults | ConvertTo-Json -Depth 2 - - # Provide structured JSON as an output for potential downstream steps - Set-GitHubOutput -Name 'results' -Value $results } $totalTests = $testResults.TotalCount @@ -280,9 +275,10 @@ if ($configuration.CodeCoverage.Enabled) { $coverageString = "$coverage%" } -$statusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } +LogGroup 'Test results summary' { -$summaryMarkdown = @" + $statusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } + $summaryMarkdown = @" ### '$($configuration.TestResult.TestSuiteName)' - Test Results | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | @@ -291,13 +287,13 @@ $summaryMarkdown = @" "@ -Write-Verbose "Processing containers [$($testResult.Containers.Count)]" -Verbose -foreach ($container in $testResult.Containers) { - $containerPath = $container.Item.FullName - Write-Verbose "Processing container [$containerPath]" -Verbose - $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' - Write-Verbose "Container name: [$containerName]" -Verbose - $summaryMarkdown += @" + Write-Verbose "Processing containers [$($testResults.Containers.Count)]" -Verbose + foreach ($container in $testResults.Containers) { + $containerPath = $container.Item.FullName + Write-Verbose "Processing container [$containerPath]" -Verbose + $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' + Write-Verbose "Container name: [$containerName]" -Verbose + $summaryMarkdown += @"

$containerName - Details

@@ -305,33 +301,38 @@ Path: $containerPath "@ - $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item -eq $containerPath } | ForEach-Object { - $test = $_ - $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' - $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding - $summaryMarkdown += @" + $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item -eq $containerPath } | ForEach-Object { + $test = $_ + $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' + $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding + $summaryMarkdown += @" - $statusIcon $($test.Name) - $formattedDuration "@ - if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { - $summaryMarkdown += @" + if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { + $summaryMarkdown += @" $($test.ErrorRecord.Exception.Message) "@ + } } - } - $summaryMarkdown += @" + $summaryMarkdown += @" ``````

"@ -} + } + + Set-GitHubStepSummary -Summary $summaryMarkdown +} -Set-GitHubStepSummary -Summary $summaryMarkdown +$results = $testResults | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue +# Provide structured JSON as an output for potential downstream steps +Set-GitHubOutput -Name 'results' -Value $results # For each property of testresults, output the value as a JSON object foreach ($property in $testResults.PSObject.Properties) { From 37f0a01e33e11cc05379e93f9cb403914500a2e0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:34:31 +0100 Subject: [PATCH 103/176] Refactor test results processing in main.ps1 to improve container test filtering and add verbose logging --- scripts/main.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index b7470508..aa80dde7 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -301,7 +301,9 @@ Path: $containerPath "@ - $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item -eq $containerPath } | ForEach-Object { + $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } + Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose + $containerTests | ForEach-Object { $test = $_ $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding @@ -318,7 +320,6 @@ Path: $containerPath } $summaryMarkdown += @" -``````

From 1fc008ce3d2e8c7e292f71858785c5143c085f4d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:37:51 +0100 Subject: [PATCH 104/176] Fix expected emoji output for giraffe test in Emoji.Tests.ps1 --- tests/3-Advanced/Emoji/Emoji.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/3-Advanced/Emoji/Emoji.Tests.ps1 b/tests/3-Advanced/Emoji/Emoji.Tests.ps1 index 78f88ae3..2615e7bb 100644 --- a/tests/3-Advanced/Emoji/Emoji.Tests.ps1 +++ b/tests/3-Advanced/Emoji/Emoji.Tests.ps1 @@ -17,7 +17,7 @@ Describe 'Get-Emoji' { } It 'Returns 🦒 (giraffe)' { - Get-Emoji -Name giraffe | Should -Be '🦒' + Get-Emoji -Name giraffe | Should -Be '🌵'#'🦒' } } From b06f321b91410b8d2c14bc33fd1e094f1c4de61a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:46:02 +0100 Subject: [PATCH 105/176] Enhance test results summary with detailed container information and improved formatting --- scripts/main.ps1 | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index aa80dde7..102156a1 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -285,6 +285,9 @@ LogGroup 'Test results summary' { | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $statusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | +
$($configuration.TestResult.TestSuiteName) - Details +

+ "@ Write-Verbose "Processing containers [$($testResults.Containers.Count)]" -Verbose @@ -293,11 +296,12 @@ LogGroup 'Test results summary' { Write-Verbose "Processing container [$containerPath]" -Verbose $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' Write-Verbose "Container name: [$containerName]" -Verbose + $statusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -

$containerName - Details +
- $statusIcon - $containerName

-Path: $containerPath +Path: ``$containerPath`` "@ @@ -313,21 +317,26 @@ Path: $containerPath "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { $summaryMarkdown += @" +`````` $($test.ErrorRecord.Exception.Message) +`````` "@ } } - $summaryMarkdown += @" + $summaryMarkdown += @'

-"@ - +'@ } + $summaryMarkdown += @' +

+
+'@ Set-GitHubStepSummary -Summary $summaryMarkdown } From 30ecacaeb5c21582bc0b801483ee0433ae7ed388 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:52:07 +0100 Subject: [PATCH 106/176] Refactor test results summary in main.ps1 to enhance container details and improve status icon representation --- scripts/main.ps1 | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 102156a1..c99d8c6f 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -277,15 +277,16 @@ if ($configuration.CodeCoverage.Enabled) { LogGroup 'Test results summary' { - $statusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } + $testSuitName = $($configuration.TestResult.TestSuiteName) + $testSuitStatusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } $summaryMarkdown = @" -### '$($configuration.TestResult.TestSuiteName)' - Test Results +### '$testSuitName' - Test Results | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | -| $statusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | +| $testSuitStatusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | -
$($configuration.TestResult.TestSuiteName) - Details +
$testSuitStatusIcon - $testSuitName - Details

"@ @@ -296,9 +297,9 @@ LogGroup 'Test results summary' { Write-Verbose "Processing container [$containerPath]" -Verbose $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' Write-Verbose "Container name: [$containerName]" -Verbose - $statusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' + $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -

- $statusIcon - $containerName +
$containerStatusIcon - $testSuitName - $containerName

Path: ``$containerPath`` @@ -308,19 +309,26 @@ Path: ``$containerPath`` $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose $containerTests | ForEach-Object { + + + $test = $_ - $statusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' + $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @" -- $statusIcon $($test.Name) - $formattedDuration +

$testStatusIcon - $($test.Name) - $formattedDuration +

"@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { $summaryMarkdown += @" `````` - $($test.ErrorRecord.Exception.Message) +$($test.ErrorRecord.Exception.Message) `````` +

+
+ "@ } } From 380de517ebc83de50246459e6bc913fde446c68a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:55:56 +0100 Subject: [PATCH 107/176] Refactor test results summary in main.ps1 to remove unnecessary HTML tags and improve markdown formatting --- scripts/main.ps1 | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index c99d8c6f..33d6dfc8 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -287,7 +287,6 @@ LogGroup 'Test results summary' { | $testSuitStatusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString |
$testSuitStatusIcon - $testSuitName - Details -

"@ @@ -300,7 +299,6 @@ LogGroup 'Test results summary' { $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @"

$containerStatusIcon - $testSuitName - $containerName -

Path: ``$containerPath`` @@ -309,24 +307,22 @@ Path: ``$containerPath`` $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose $containerTests | ForEach-Object { - - - $test = $_ $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @"

$testStatusIcon - $($test.Name) - $formattedDuration -

"@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { $summaryMarkdown += @" `````` + $($test.ErrorRecord.Exception.Message) + `````` -

+
"@ @@ -335,15 +331,15 @@ $($test.ErrorRecord.Exception.Message) $summaryMarkdown += @' -

+ '@ } $summaryMarkdown += @' -

+ '@ Set-GitHubStepSummary -Summary $summaryMarkdown } From 3f9899560a7dbc4ced8b83b84294f63d945a5bdb Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 12:57:55 +0100 Subject: [PATCH 108/176] Refactor markdown summary formatting in main.ps1 to improve readability --- scripts/main.ps1 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 33d6dfc8..9cee245e 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -322,11 +322,14 @@ $($test.ErrorRecord.Exception.Message) `````` +"@ + } + $summaryMarkdown += @'
-"@ - } +'@ + } $summaryMarkdown += @' From c4685789c3d78d8b4b9a8ba110fe9fe271b70fa1 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:00:09 +0100 Subject: [PATCH 109/176] Remove unnecessary blank line in test results summary for cleaner output --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 9cee245e..f89ff1e5 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -285,7 +285,6 @@ LogGroup 'Test results summary' { | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $testSuitStatusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | -
$testSuitStatusIcon - $testSuitName - Details "@ @@ -316,6 +315,7 @@ Path: ``$containerPath`` "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { $summaryMarkdown += @" + `````` $($test.ErrorRecord.Exception.Message) From f0e7eecbff67de6559ca3981e0463a9cdf15bd51 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:04:58 +0100 Subject: [PATCH 110/176] Fix indentation in test results summary for improved readability --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index f89ff1e5..f1658f7b 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -310,7 +310,7 @@ Path: ``$containerPath`` $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @" -
$testStatusIcon - $($test.Name) - $formattedDuration +
$testStatusIcon - $($test.Name) - $formattedDuration "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { From 8e51fa607455cf1320ab7eb12fd50afbc41d235c Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:05:16 +0100 Subject: [PATCH 111/176] Fix indentation in container details summary for improved readability --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index f1658f7b..b613b795 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -297,7 +297,7 @@ LogGroup 'Test results summary' { Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -
$containerStatusIcon - $testSuitName - $containerName +
$containerStatusIcon - $testSuitName - $containerName Path: ``$containerPath`` From a4f332e4081749e060576a4284f98ca6e8c3a35d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:09:19 +0100 Subject: [PATCH 112/176] Remove unnecessary blank lines in test summary for cleaner output --- scripts/main.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index b613b795..9752a465 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -317,9 +317,7 @@ Path: ``$containerPath`` $summaryMarkdown += @" `````` - $($test.ErrorRecord.Exception.Message) - `````` "@ From 25a24e5cfb8a022e0167d70353593185cb5d2c4d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:12:58 +0100 Subject: [PATCH 113/176] Improve indentation and structure of details in test results summary for better readability --- scripts/main.ps1 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 9752a465..8fddcc1c 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -285,7 +285,8 @@ LogGroup 'Test results summary' { | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $testSuitStatusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | -
$testSuitStatusIcon - $testSuitName - Details +
+ $testSuitStatusIcon - $testSuitName - Details "@ @@ -297,7 +298,8 @@ LogGroup 'Test results summary' { Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -
$containerStatusIcon - $testSuitName - $containerName +
+ $containerStatusIcon - $testSuitName - $containerName Path: ``$containerPath`` @@ -310,7 +312,9 @@ Path: ``$containerPath`` $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @" -
$testStatusIcon - $($test.Name) - $formattedDuration +
+
+ $testStatusIcon - $($test.Name) - $formattedDuration "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { @@ -324,7 +328,8 @@ $($test.ErrorRecord.Exception.Message) } $summaryMarkdown += @' -
+
+ '@ @@ -332,7 +337,7 @@ $($test.ErrorRecord.Exception.Message) $summaryMarkdown += @' -
+
'@ } From b064d74e6a086c550ebd097b0d4dc25747aaeabc Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:15:11 +0100 Subject: [PATCH 114/176] Fix indentation and structure in test results summary for improved readability --- scripts/main.ps1 | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 8fddcc1c..55b58011 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -285,8 +285,7 @@ LogGroup 'Test results summary' { | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $testSuitStatusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | -
- $testSuitStatusIcon - $testSuitName - Details +
$testSuitStatusIcon - $testSuitName - Details "@ @@ -298,8 +297,7 @@ LogGroup 'Test results summary' { Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -
- $containerStatusIcon - $testSuitName - $containerName +
| $containerStatusIcon - $testSuitName - $containerName Path: ``$containerPath`` @@ -312,9 +310,7 @@ Path: ``$containerPath`` $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @" -
-
- $testStatusIcon - $($test.Name) - $formattedDuration +
| | $testStatusIcon - $($test.Name) - $formattedDuration "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { @@ -328,8 +324,7 @@ $($test.ErrorRecord.Exception.Message) } $summaryMarkdown += @' -
-
+
'@ @@ -337,7 +332,7 @@ $($test.ErrorRecord.Exception.Message) $summaryMarkdown += @' -
+
'@ } From d5cd8cacb3335d382ce4b4262929eac27dd2836c Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:24:59 +0100 Subject: [PATCH 115/176] Enhance indentation in test results summary for improved clarity --- scripts/main.ps1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 55b58011..ac3a48c0 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -276,6 +276,8 @@ if ($configuration.CodeCoverage.Enabled) { } LogGroup 'Test results summary' { + $unicodeNbsp = [char]0x00A0 # or `\u00A0` + $indent = $unicodeNbsp * 3 $testSuitName = $($configuration.TestResult.TestSuiteName) $testSuitStatusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } @@ -297,7 +299,7 @@ LogGroup 'Test results summary' { Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -
| $containerStatusIcon - $testSuitName - $containerName +
$indent$containerStatusIcon - $testSuitName - $containerName Path: ``$containerPath`` @@ -310,7 +312,7 @@ Path: ``$containerPath`` $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @" -
| | $testStatusIcon - $($test.Name) - $formattedDuration +
$indent$indent$testStatusIcon - $($test.Name) - $formattedDuration "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { From fa98e0be97577a162155e9465000cfea45155787 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:26:48 +0100 Subject: [PATCH 116/176] Adjust indentation in test results summary for improved alignment --- scripts/main.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index ac3a48c0..d3f482c0 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -276,8 +276,8 @@ if ($configuration.CodeCoverage.Enabled) { } LogGroup 'Test results summary' { - $unicodeNbsp = [char]0x00A0 # or `\u00A0` - $indent = $unicodeNbsp * 3 + $nbsp = [char]0x00A0 + $indent = "$nbsp" * 4 $testSuitName = $($configuration.TestResult.TestSuiteName) $testSuitStatusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } From 9ea4d041f8664d84781c83e400bcf710d441abee Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:32:35 +0100 Subject: [PATCH 117/176] Refactor test results summary for improved clarity and detail presentation --- scripts/main.ps1 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index d3f482c0..8b2285a5 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -282,12 +282,12 @@ LogGroup 'Test results summary' { $testSuitName = $($configuration.TestResult.TestSuiteName) $testSuitStatusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } $summaryMarkdown = @" -### '$testSuitName' - Test Results +### $testSuitName - Test Results | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $testSuitStatusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | -
$testSuitStatusIcon - $testSuitName - Details +
$testSuitStatusIcon - $testSuitName "@ @@ -301,18 +301,16 @@ LogGroup 'Test results summary' { $summaryMarkdown += @"
$indent$containerStatusIcon - $testSuitName - $containerName -Path: ``$containerPath`` - "@ - $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } + $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose $containerTests | ForEach-Object { $test = $_ $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @" -
$indent$indent$testStatusIcon - $($test.Name) - $formattedDuration +
$indent$indent$testStatusIcon - $($test.Path) - $formattedDuration "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { From cc8ce9f2da16a6ed6dbb963dee38b8f3b3463a16 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:36:06 +0100 Subject: [PATCH 118/176] Refactor test results summary to include test path in the details summary --- scripts/main.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 8b2285a5..387c30de 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -307,10 +307,11 @@ LogGroup 'Test results summary' { Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose $containerTests | ForEach-Object { $test = $_ + $testPath = $testResults.Tests[0].Path -join '/' $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @" -
$indent$indent$testStatusIcon - $($test.Path) - $formattedDuration +
$indent$indent$testStatusIcon - $testPath ($formattedDuration) "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { From 82058cdcf7150d534034792a48223a48901bf163 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:37:03 +0100 Subject: [PATCH 119/176] Improve formatting in test results summary for better readability --- scripts/main.ps1 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 387c30de..860168b3 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -289,6 +289,7 @@ LogGroup 'Test results summary' { | $testSuitStatusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString |
$testSuitStatusIcon - $testSuitName + "@ Write-Verbose "Processing containers [$($testResults.Containers.Count)]" -Verbose @@ -301,6 +302,7 @@ LogGroup 'Test results summary' { $summaryMarkdown += @"
$indent$containerStatusIcon - $testSuitName - $containerName + "@ $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path @@ -313,6 +315,7 @@ LogGroup 'Test results summary' { $summaryMarkdown += @"
$indent$indent$testStatusIcon - $testPath ($formattedDuration) + "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { $summaryMarkdown += @" @@ -321,12 +324,14 @@ LogGroup 'Test results summary' { $($test.ErrorRecord.Exception.Message) `````` + "@ } $summaryMarkdown += @'
+ '@ } @@ -335,6 +340,7 @@ $($test.ErrorRecord.Exception.Message)
+ '@ } @@ -342,6 +348,7 @@ $($test.ErrorRecord.Exception.Message)
+ '@ Set-GitHubStepSummary -Summary $summaryMarkdown } From f23db6e7e6a7d2af9b33b91e64837cab2ed29700 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:37:47 +0100 Subject: [PATCH 120/176] Fix test path retrieval in test results summary for accurate reporting --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 860168b3..12c544cb 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -309,7 +309,7 @@ LogGroup 'Test results summary' { Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose $containerTests | ForEach-Object { $test = $_ - $testPath = $testResults.Tests[0].Path -join '/' + $testPath = $test.Path -join '/' $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @" From abaaebbbd09dacfeccdf49ec2521402ad6809d24 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 13:41:04 +0100 Subject: [PATCH 121/176] Refactor test results summary to remove redundant details and enhance clarity --- scripts/main.ps1 | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 12c544cb..4c9d1282 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -288,8 +288,6 @@ LogGroup 'Test results summary' { | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $testSuitStatusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString |
$testSuitStatusIcon - $testSuitName - - "@ Write-Verbose "Processing containers [$($testResults.Containers.Count)]" -Verbose @@ -300,9 +298,7 @@ LogGroup 'Test results summary' { Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -
$indent$containerStatusIcon - $testSuitName - $containerName - - +
$indent$containerStatusIcon - $containerName "@ $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path @@ -314,8 +310,6 @@ LogGroup 'Test results summary' { $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $summaryMarkdown += @"
$indent$indent$testStatusIcon - $testPath ($formattedDuration) - - "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { $summaryMarkdown += @" From 40cccfd9b996753871e08f1e7109e73a9e37a20e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 14:03:38 +0100 Subject: [PATCH 122/176] Add function to group tests in markdown by their path for improved summary clarity --- scripts/Helpers.psm1 | 36 ++++++++++++++++++++++++++++++++++++ scripts/main.ps1 | 36 +++++++----------------------------- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index c4c46beb..1b7806dd 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -275,3 +275,39 @@ filter Format-TimeSpan { return $formatted } + +# Function to recursively build markdown grouping tests by parts in their test path +function Get-GroupedTestMarkdown { + param( + [Parameter(Mandatory)] + [array]$Tests, + [int]$Depth, + [string]$BaseIndent + ) + $markdown = '' + # Group tests by the element at position $Depth (or "Ungrouped" if not present) + $groups = $Tests | Group-Object { if ($_.Path.Count -gt $Depth) { $_.Path[$Depth] } else { 'Ungrouped' } } | Sort-Object Name + foreach ($group in $groups) { + $groupName = $group.Name + $groupTests = $group.Group + # If any test has further parts, create a nested details block... + if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { + $markdown += "$BaseIndent
$groupName`n" + $markdown += Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1) -BaseIndent ("$BaseIndent ") + $markdown += "$BaseIndent
`n" + } else { + # Otherwise, list each test at this level + foreach ($test in $groupTests) { + $testName = $test.Path[$Depth] + $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' + $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding + $markdown += "$BaseIndent
$testStatusIcon - $testName ($formattedDuration)`n" + if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { + $markdown += "`n$BaseIndent $($test.ErrorRecord.Exception.Message)`n" + } + $markdown += "$BaseIndent
`n" + } + } + } + return $markdown +} diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 4c9d1282..4840108e 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -288,9 +288,11 @@ LogGroup 'Test results summary' { | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $testSuitStatusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString |
$testSuitStatusIcon - $testSuitName + "@ Write-Verbose "Processing containers [$($testResults.Containers.Count)]" -Verbose + # For each container, group tests by their test path parts foreach ($container in $testResults.Containers) { $containerPath = $container.Item.FullName Write-Verbose "Processing container [$containerPath]" -Verbose @@ -298,43 +300,19 @@ LogGroup 'Test results summary' { Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -
$indent$containerStatusIcon - $containerName -"@ +
$indent$containerStatusIcon - $testSuitName - $containerName +"@ $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose - $containerTests | ForEach-Object { - $test = $_ - $testPath = $test.Path -join '/' - $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' - $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding - $summaryMarkdown += @" -
$indent$indent$testStatusIcon - $testPath ($formattedDuration) -"@ - if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { - $summaryMarkdown += @" - -`````` -$($test.ErrorRecord.Exception.Message) -`````` - -"@ - } - - $summaryMarkdown += @' -
- - -'@ - - } + # Build the nested details markdown grouping tests by their test path parts + $groupedMarkdown = Get-GroupedTestMarkdown -Tests $containerTests -Depth 0 -BaseIndent "$indent " + $summaryMarkdown += $groupedMarkdown $summaryMarkdown += @' -
- '@ } From 11e3c14734da37a7a9f1d77a502730f8e7eae7d4 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 14:16:42 +0100 Subject: [PATCH 123/176] Refactor indentation handling in markdown generation for test results summary --- scripts/Helpers.psm1 | 5 ++++- scripts/main.ps1 | 5 +---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 1b7806dd..c6b264f6 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -293,7 +293,7 @@ function Get-GroupedTestMarkdown { # If any test has further parts, create a nested details block... if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { $markdown += "$BaseIndent
$groupName`n" - $markdown += Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1) -BaseIndent ("$BaseIndent ") + $markdown += Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1) -BaseIndent ("$BaseIndent$script:indent") $markdown += "$BaseIndent
`n" } else { # Otherwise, list each test at this level @@ -311,3 +311,6 @@ function Get-GroupedTestMarkdown { } return $markdown } + +$script:nbsp = [char]0x00A0 +$script:indent = "$nbsp" * 4 diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 4840108e..18dbe1aa 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -276,9 +276,6 @@ if ($configuration.CodeCoverage.Enabled) { } LogGroup 'Test results summary' { - $nbsp = [char]0x00A0 - $indent = "$nbsp" * 4 - $testSuitName = $($configuration.TestResult.TestSuiteName) $testSuitStatusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } $summaryMarkdown = @" @@ -307,7 +304,7 @@ LogGroup 'Test results summary' { Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose # Build the nested details markdown grouping tests by their test path parts - $groupedMarkdown = Get-GroupedTestMarkdown -Tests $containerTests -Depth 0 -BaseIndent "$indent " + $groupedMarkdown = Get-GroupedTestMarkdown -Tests $containerTests -Depth 0 -BaseIndent "$script:indent" $summaryMarkdown += $groupedMarkdown $summaryMarkdown += @' From 6c80487cbe07468b5b0f1ab88ddb71ea15f3c4e1 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 14:22:27 +0100 Subject: [PATCH 124/176] Refactor markdown generation for test results to improve readability and structure --- scripts/Helpers.psm1 | 30 ++++++++++++++++++++++++------ scripts/main.ps1 | 2 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index c6b264f6..e21e19aa 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -292,20 +292,38 @@ function Get-GroupedTestMarkdown { $groupTests = $group.Group # If any test has further parts, create a nested details block... if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { - $markdown += "$BaseIndent
$groupName`n" - $markdown += Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1) -BaseIndent ("$BaseIndent$script:indent") - $markdown += "$BaseIndent
`n" + $markdown += @" +
$BaseIndent$groupName + +$(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1) -BaseIndent ("$BaseIndent$script:indent")) + +
+ +"@ } else { # Otherwise, list each test at this level foreach ($test in $groupTests) { $testName = $test.Path[$Depth] $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding - $markdown += "$BaseIndent
$testStatusIcon - $testName ($formattedDuration)`n" + $markdown += @" +
$BaseIndent$testStatusIcon - $testName ($formattedDuration) + +"@ + if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { - $markdown += "`n$BaseIndent $($test.ErrorRecord.Exception.Message)`n" + $markdown += @" + +`````` +$($test.ErrorRecord.Exception.Message) +`````` + +"@ } - $markdown += "$BaseIndent
`n" + $markdown += @' +
+ +'@ } } } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 18dbe1aa..013ad422 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -297,7 +297,7 @@ LogGroup 'Test results summary' { Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -
$indent$containerStatusIcon - $testSuitName - $containerName +
$script:indent$containerStatusIcon - $testSuitName - $containerName "@ $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path From 4233f155f2279a76da5b7f8f279241b64daf16ed Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 15:50:43 +0100 Subject: [PATCH 125/176] Enhance markdown grouping for test results by adding aggregate status icons and improving indentation for better readability --- scripts/Helpers.psm1 | 12 +++++++----- scripts/main.ps1 | 7 ++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index e21e19aa..a4f1111c 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -276,7 +276,6 @@ filter Format-TimeSpan { return $formatted } -# Function to recursively build markdown grouping tests by parts in their test path function Get-GroupedTestMarkdown { param( [Parameter(Mandatory)] @@ -290,10 +289,13 @@ function Get-GroupedTestMarkdown { foreach ($group in $groups) { $groupName = $group.Name $groupTests = $group.Group + # Calculate aggregate status: if any test failed, mark the group as failed + $groupStatusIcon = if ($groupTests | Where-Object { $_.Result -eq 'Failed' }) { '❌' } else { '✅' } + # If any test has further parts, create a nested details block... if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { $markdown += @" -
$BaseIndent$groupName +
$BaseIndent$groupStatusIcon - $groupName $(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1) -BaseIndent ("$BaseIndent$script:indent")) @@ -314,9 +316,9 @@ $(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1) -BaseIndent ("$ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { $markdown += @" -`````` -$($test.ErrorRecord.Exception.Message) -`````` +$BaseIndent`````` +$BaseIndent$($test.ErrorRecord.Exception.Message) +$BaseIndent`````` "@ } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 013ad422..875e2f7a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -1,3 +1,4 @@ + [CmdletBinding()] param() @@ -78,8 +79,8 @@ LogGroup 'Load inputs' { [pscustomobject]($inputs.GetEnumerator() | Where-Object { -not [string]::IsNullOrEmpty($_.Value) }) | Format-List } -$customConfig = @{} -$customInputs = @{} +$customConfig = @{ } +$customInputs = @{ } LogGroup 'Load configuration - Defaults' { $defaultConfigPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') @@ -283,7 +284,7 @@ LogGroup 'Test results summary' { | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | -| $testSuitStatusIcon |$($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | +| $testSuitStatusIcon | $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString |
$testSuitStatusIcon - $testSuitName "@ From ff9c116ef11c577626c05f918b43c33a9d9e2cda Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 15:59:52 +0100 Subject: [PATCH 126/176] Refactor markdown generation for grouped test results by removing redundant parameters and improving indentation handling --- scripts/Helpers.psm1 | 23 ++++++++++------------- scripts/main.ps1 | 4 ++-- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index a4f1111c..cafe52fe 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -280,8 +280,7 @@ function Get-GroupedTestMarkdown { param( [Parameter(Mandatory)] [array]$Tests, - [int]$Depth, - [string]$BaseIndent + [int]$Depth ) $markdown = '' # Group tests by the element at position $Depth (or "Ungrouped" if not present) @@ -289,15 +288,16 @@ function Get-GroupedTestMarkdown { foreach ($group in $groups) { $groupName = $group.Name $groupTests = $group.Group + $groupIndent = $Indent * $Depth # Calculate aggregate status: if any test failed, mark the group as failed $groupStatusIcon = if ($groupTests | Where-Object { $_.Result -eq 'Failed' }) { '❌' } else { '✅' } # If any test has further parts, create a nested details block... if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { $markdown += @" -
$BaseIndent$groupStatusIcon - $groupName +
$groupIndent$groupStatusIcon - $groupName -$(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1) -BaseIndent ("$BaseIndent$script:indent")) +$(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1))
@@ -309,22 +309,19 @@ $(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1) -BaseIndent ("$ $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $markdown += @" -
$BaseIndent$testStatusIcon - $testName ($formattedDuration) - +
$groupIndent$testStatusIcon - $testName ($formattedDuration) "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { $markdown += @" -$BaseIndent`````` -$BaseIndent$($test.ErrorRecord.Exception.Message) -$BaseIndent`````` - +`````` +$($test.ErrorRecord.Exception.Message) +`````` "@ } $markdown += @'
- '@ } } @@ -332,5 +329,5 @@ $BaseIndent`````` return $markdown } -$script:nbsp = [char]0x00A0 -$script:indent = "$nbsp" * 4 +$nbsp = [char]0x00A0 +$indent = "$nbsp" * 4 diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 875e2f7a..6b9995ff 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -298,14 +298,14 @@ LogGroup 'Test results summary' { Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -
$script:indent$containerStatusIcon - $testSuitName - $containerName +
$Indent$containerStatusIcon - $testSuitName - $containerName "@ $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose # Build the nested details markdown grouping tests by their test path parts - $groupedMarkdown = Get-GroupedTestMarkdown -Tests $containerTests -Depth 0 -BaseIndent "$script:indent" + $groupedMarkdown = Get-GroupedTestMarkdown -Tests $containerTests -Depth 2 $summaryMarkdown += $groupedMarkdown $summaryMarkdown += @' From d17a30a3b3d4b7885f93d69418b64b556d042887 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:04:10 +0100 Subject: [PATCH 127/176] Refactor configuration loading in main script for improved readability and structure --- scripts/Helpers.psm1 | 3 -- scripts/main.ps1 | 73 +++++++++++++++++++++++--------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index cafe52fe..780b3290 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -328,6 +328,3 @@ $($test.ErrorRecord.Exception.Message) } return $markdown } - -$nbsp = [char]0x00A0 -$indent = "$nbsp" * 4 diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 6b9995ff..7c16cdd1 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -216,29 +216,28 @@ LogGroup 'Load configuration - Action overrides' { Write-Output ($customInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } -$run = Merge-Hashtable -Main $defaultConfig.Run -Overrides $customConfig.Run, $customInputs.Run -$filter = Merge-Hashtable -Main $defaultConfig.Filter -Overrides $customConfig.Filter, $customInputs.Filter -$codeCoverage = Merge-Hashtable -Main $defaultConfig.CodeCoverage -Overrides $customConfig.CodeCoverage, $customInputs.CodeCoverage -$testResult = Merge-Hashtable -Main $defaultConfig.TestResult -Overrides $customConfig.TestResult, $customInputs.TestResult -$should = Merge-Hashtable -Main $defaultConfig.Should -Overrides $customConfig.Should, $customInputs.Should -$debug = Merge-Hashtable -Main $defaultConfig.Debug -Overrides $customConfig.Debug, $customInputs.Debug -$output = Merge-Hashtable -Main $defaultConfig.Output -Overrides $customConfig.Output, $customInputs.Output -$testDrive = Merge-Hashtable -Main $defaultConfig.TestDrive -Overrides $customConfig.TestDrive, $customInputs.TestDrive -$testRegistry = Merge-Hashtable -Main $defaultConfig.TestRegistry -Overrides $customConfig.TestRegistry, $customInputs.TestRegistry - -$configuration = @{ - Run = $run - Filter = $filter - CodeCoverage = $codeCoverage - TestResult = $testResult - Should = $should - Debug = $debug - Output = $output - TestDrive = $testDrive - TestRegistry = $testRegistry -} - LogGroup 'Load configuration - Add containers' { + $run = Merge-Hashtable -Main $defaultConfig.Run -Overrides $customConfig.Run, $customInputs.Run + $filter = Merge-Hashtable -Main $defaultConfig.Filter -Overrides $customConfig.Filter, $customInputs.Filter + $codeCoverage = Merge-Hashtable -Main $defaultConfig.CodeCoverage -Overrides $customConfig.CodeCoverage, $customInputs.CodeCoverage + $testResult = Merge-Hashtable -Main $defaultConfig.TestResult -Overrides $customConfig.TestResult, $customInputs.TestResult + $should = Merge-Hashtable -Main $defaultConfig.Should -Overrides $customConfig.Should, $customInputs.Should + $debug = Merge-Hashtable -Main $defaultConfig.Debug -Overrides $customConfig.Debug, $customInputs.Debug + $output = Merge-Hashtable -Main $defaultConfig.Output -Overrides $customConfig.Output, $customInputs.Output + $testDrive = Merge-Hashtable -Main $defaultConfig.TestDrive -Overrides $customConfig.TestDrive, $customInputs.TestDrive + $testRegistry = Merge-Hashtable -Main $defaultConfig.TestRegistry -Overrides $customConfig.TestRegistry, $customInputs.TestRegistry + + $configuration = @{ + Run = $run + Filter = $filter + CodeCoverage = $codeCoverage + TestResult = $testResult + Should = $should + Debug = $debug + Output = $output + TestDrive = $testDrive + TestRegistry = $testRegistry + } $containers = Get-PesterContainer -Path $configuration.Run.Path Write-Output ($containers | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) } @@ -263,20 +262,24 @@ LogGroup 'Test results' { } } -$totalTests = $testResults.TotalCount -$passedTests = $testResults.PassedCount -$failedTests = $testResults.FailedCount -$skippedTests = $testResults.SkippedCount -$inconclusiveTests = $testResults.InconclusiveCount -$notRunTests = $testResults.NotRunCount - -$coverageString = 'N/A' -if ($configuration.CodeCoverage.Enabled) { - $coverage = [System.Math]::Round(($testResults.CodeCoverage.CoveragePercent), 2) - $coverageString = "$coverage%" -} - LogGroup 'Test results summary' { + + $nbsp = [char]0x00A0 + $indent = "$nbsp" * 4 + + $totalTests = $testResults.TotalCount + $passedTests = $testResults.PassedCount + $failedTests = $testResults.FailedCount + $skippedTests = $testResults.SkippedCount + $inconclusiveTests = $testResults.InconclusiveCount + $notRunTests = $testResults.NotRunCount + + $coverageString = 'N/A' + if ($configuration.CodeCoverage.Enabled) { + $coverage = [System.Math]::Round(($testResults.CodeCoverage.CoveragePercent), 2) + $coverageString = "$coverage%" + } + $testSuitName = $($configuration.TestResult.TestSuiteName) $testSuitStatusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } $summaryMarkdown = @" From 05b0452905a7f62285d11bfa88a98b9159123402 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:05:23 +0100 Subject: [PATCH 128/176] Add indentation handling for markdown generation in Helpers.psm1 --- scripts/Helpers.psm1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 780b3290..cafe52fe 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -328,3 +328,6 @@ $($test.ErrorRecord.Exception.Message) } return $markdown } + +$nbsp = [char]0x00A0 +$indent = "$nbsp" * 4 From 4b1eb15c6c0d64989aa6afbf6a50536d0eec420a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:08:32 +0100 Subject: [PATCH 129/176] Fix markdown formatting in Helpers.psm1 by adding missing line breaks for improved readability --- scripts/Helpers.psm1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index cafe52fe..7d7ce6ed 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -310,6 +310,7 @@ $(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1)) $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $markdown += @"
$groupIndent$testStatusIcon - $testName ($formattedDuration) + "@ if ($test.Result -eq 'Failed' -and $test.ErrorRecord.Exception.Message) { @@ -318,10 +319,12 @@ $(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1)) `````` $($test.ErrorRecord.Exception.Message) `````` + "@ } $markdown += @'
+ '@ } } From 323fa93e42fe6abb870b4a64e8b28d5f5a233703 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:21:03 +0100 Subject: [PATCH 130/176] Refactor markdown generation in Get-GroupedTestMarkdown function by removing unnecessary line breaks for improved readability --- scripts/Helpers.psm1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 7d7ce6ed..9206a0d6 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -296,9 +296,7 @@ function Get-GroupedTestMarkdown { if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { $markdown += @"
$groupIndent$groupStatusIcon - $groupName - $(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1)) -
"@ From 4de1502b9fa95ecdf173c2b888e715ad0ece44c6 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:23:48 +0100 Subject: [PATCH 131/176] Comment out container initialization in Pester.Configuration.ps1 for future reference --- tests/3-Advanced/Pester.Configuration.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/3-Advanced/Pester.Configuration.ps1 b/tests/3-Advanced/Pester.Configuration.ps1 index 066f53b9..ccb0f145 100644 --- a/tests/3-Advanced/Pester.Configuration.ps1 +++ b/tests/3-Advanced/Pester.Configuration.ps1 @@ -1,9 +1,9 @@ @{ Run = @{ - Path = $PSScriptRoot - PassThru = $true - Container = Get-ChildItem -Path $config.Run.Path.Value -Filter *.Container.* -Recurse | - ForEach-Object { . $_ } | ForEach-Object { New-PesterContainer @_ } + Path = $PSScriptRoot + PassThru = $true + # Container = Get-ChildItem -Path $config.Run.Path.Value -Filter *.Container.* -Recurse | + # ForEach-Object { . $_ } | ForEach-Object { New-PesterContainer @_ } } TestResult = @{ Enabled = $true From 59c7c8b13618565f0babc112419e9013733b7bc3 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:26:25 +0100 Subject: [PATCH 132/176] Refactor summary markdown generation in main.ps1 by removing test suite name for clarity and adding a separator line --- scripts/main.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 7c16cdd1..1c5d5792 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -301,7 +301,8 @@ LogGroup 'Test results summary' { Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @" -
$Indent$containerStatusIcon - $testSuitName - $containerName +
$Indent$containerStatusIcon - $containerName +------------------------------------------------------ "@ $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path From 934e623119a3a3e68621dfadacb08617033a03cd Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:26:59 +0100 Subject: [PATCH 133/176] Add separator lines to summary markdown generation in main.ps1 for improved clarity --- scripts/main.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 1c5d5792..3e686d1d 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -302,7 +302,7 @@ LogGroup 'Test results summary' { $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @"
$Indent$containerStatusIcon - $containerName ------------------------------------------------------- +---- "@ $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path @@ -313,6 +313,7 @@ LogGroup 'Test results summary' { $summaryMarkdown += $groupedMarkdown $summaryMarkdown += @' +----
'@ From de538398cd3e3c79ba96af1b08b48b6d640cc99d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:30:31 +0100 Subject: [PATCH 134/176] Adjust indentation level in Get-GroupedTestMarkdown and update depth parameter in main.ps1 for improved markdown grouping --- scripts/Helpers.psm1 | 2 +- scripts/main.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 9206a0d6..c5538d55 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -288,7 +288,7 @@ function Get-GroupedTestMarkdown { foreach ($group in $groups) { $groupName = $group.Name $groupTests = $group.Group - $groupIndent = $Indent * $Depth + $groupIndent = $Indent * ($Depth + 1) # Calculate aggregate status: if any test failed, mark the group as failed $groupStatusIcon = if ($groupTests | Where-Object { $_.Result -eq 'Failed' }) { '❌' } else { '✅' } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 3e686d1d..9e65bfa5 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -309,7 +309,7 @@ LogGroup 'Test results summary' { Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose # Build the nested details markdown grouping tests by their test path parts - $groupedMarkdown = Get-GroupedTestMarkdown -Tests $containerTests -Depth 2 + $groupedMarkdown = Get-GroupedTestMarkdown -Tests $containerTests -Depth 0 $summaryMarkdown += $groupedMarkdown $summaryMarkdown += @' From 127b3cb482347b317de0bb2794dcc06df04b7c3e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:33:40 +0100 Subject: [PATCH 135/176] Remove unnecessary line breaks in summary markdown generation for improved readability --- scripts/main.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 9e65bfa5..fc4a7663 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -302,7 +302,7 @@ LogGroup 'Test results summary' { $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @"
$Indent$containerStatusIcon - $containerName ----- + "@ $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path @@ -313,7 +313,7 @@ LogGroup 'Test results summary' { $summaryMarkdown += $groupedMarkdown $summaryMarkdown += @' ----- +
'@ From da15df94e0db09d51fe8260b00e293594fe2f966 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:43:12 +0100 Subject: [PATCH 136/176] Update indentation and add paragraph tags in markdown generation for improved formatting --- scripts/Helpers.psm1 | 6 +++++- scripts/main.ps1 | 7 ++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index c5538d55..85c4a945 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -288,7 +288,7 @@ function Get-GroupedTestMarkdown { foreach ($group in $groups) { $groupName = $group.Name $groupTests = $group.Group - $groupIndent = $Indent * ($Depth + 1) + $groupIndent = $Indent * ($Depth + 2) # Calculate aggregate status: if any test failed, mark the group as failed $groupStatusIcon = if ($groupTests | Where-Object { $_.Result -eq 'Failed' }) { '❌' } else { '✅' } @@ -296,7 +296,9 @@ function Get-GroupedTestMarkdown { if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { $markdown += @"
$groupIndent$groupStatusIcon - $groupName +

$(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1)) +

"@ @@ -308,6 +310,7 @@ $(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1)) $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding $markdown += @"
$groupIndent$testStatusIcon - $testName ($formattedDuration) +

"@ @@ -321,6 +324,7 @@ $($test.ErrorRecord.Exception.Message) "@ } $markdown += @' +

'@ diff --git a/scripts/main.ps1 b/scripts/main.ps1 index fc4a7663..4059fdf6 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -289,7 +289,7 @@ LogGroup 'Test results summary' { | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $testSuitStatusIcon | $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString |
$testSuitStatusIcon - $testSuitName - +

"@ Write-Verbose "Processing containers [$($testResults.Containers.Count)]" -Verbose @@ -302,7 +302,7 @@ LogGroup 'Test results summary' { $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' $summaryMarkdown += @"

$Indent$containerStatusIcon - $containerName - +

"@ $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path @@ -314,6 +314,7 @@ LogGroup 'Test results summary' { $summaryMarkdown += @' +

'@ @@ -321,9 +322,9 @@ LogGroup 'Test results summary' { $summaryMarkdown += @' +

- '@ Set-GitHubStepSummary -Summary $summaryMarkdown } From 127f193bf4a21647d857560ea6f34fd6e1f083b4 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:48:00 +0100 Subject: [PATCH 137/176] Add aggregate duration calculation to grouped test markdown generation --- scripts/Helpers.psm1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 85c4a945..3728e248 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -291,11 +291,13 @@ function Get-GroupedTestMarkdown { $groupIndent = $Indent * ($Depth + 2) # Calculate aggregate status: if any test failed, mark the group as failed $groupStatusIcon = if ($groupTests | Where-Object { $_.Result -eq 'Failed' }) { '❌' } else { '✅' } + # Calculate aggregate duration: sum all test durations + $groupDuration = ($groupTests | Measure-Object -Property Duration -Sum).Sum | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding # If any test has further parts, create a nested details block... if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { $markdown += @" -
$groupIndent$groupStatusIcon - $groupName +
$groupIndent$groupStatusIcon - $groupName ($groupDuration)

$(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1))

From f11413b55eead221fcf1c64186a61f7796a316cf Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:53:38 +0100 Subject: [PATCH 138/176] Refactor aggregate duration calculation in Get-GroupedTestMarkdown for improved accuracy --- scripts/Helpers.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 3728e248..f58196f3 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -292,7 +292,7 @@ function Get-GroupedTestMarkdown { # Calculate aggregate status: if any test failed, mark the group as failed $groupStatusIcon = if ($groupTests | Where-Object { $_.Result -eq 'Failed' }) { '❌' } else { '✅' } # Calculate aggregate duration: sum all test durations - $groupDuration = ($groupTests | Measure-Object -Property Duration -Sum).Sum | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding + $groupDuration = ($groupTests.Duration | Measure-Object -Sum) | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding # If any test has further parts, create a nested details block... if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { From 5ac2a9d0ac1fc972dd39e140c60eff51268227df Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 16:58:02 +0100 Subject: [PATCH 139/176] Fix aggregate duration calculation in Get-GroupedTestMarkdown for improved accuracy --- scripts/Helpers.psm1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index f58196f3..2d048c97 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -292,12 +292,14 @@ function Get-GroupedTestMarkdown { # Calculate aggregate status: if any test failed, mark the group as failed $groupStatusIcon = if ($groupTests | Where-Object { $_.Result -eq 'Failed' }) { '❌' } else { '✅' } # Calculate aggregate duration: sum all test durations - $groupDuration = ($groupTests.Duration | Measure-Object -Sum) | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding + $groupDuration = [System.TimeSpan]::Zero + $groupTests.Duration | ForEach-Object { $groupDuration += $_ } + $formattedGroupDuration = $groupDuration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding # If any test has further parts, create a nested details block... if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { $markdown += @" -
$groupIndent$groupStatusIcon - $groupName ($groupDuration) +
$groupIndent$groupStatusIcon - $groupName ($formattedGroupDuration)

$(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1))

From 61155fe5545ad6939600d34ba678b29b7feb2df0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 17:01:42 +0100 Subject: [PATCH 140/176] Improve aggregate duration formatting in markdown generation for consistency --- scripts/Helpers.psm1 | 4 ++-- scripts/main.ps1 | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 2d048c97..c4a0a26e 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -294,7 +294,7 @@ function Get-GroupedTestMarkdown { # Calculate aggregate duration: sum all test durations $groupDuration = [System.TimeSpan]::Zero $groupTests.Duration | ForEach-Object { $groupDuration += $_ } - $formattedGroupDuration = $groupDuration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding + $formattedGroupDuration = $groupDuration | Format-TimeSpan -AdaptiveRounding # If any test has further parts, create a nested details block... if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { @@ -311,7 +311,7 @@ $(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1)) foreach ($test in $groupTests) { $testName = $test.Path[$Depth] $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' - $formattedDuration = $test.Duration | Format-TimeSpan -Precision Milliseconds -AdaptiveRounding + $formattedDuration = $test.Duration | Format-TimeSpan -AdaptiveRounding $markdown += @"
$groupIndent$testStatusIcon - $testName ($formattedDuration)

diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 4059fdf6..cf65c202 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -300,8 +300,9 @@ LogGroup 'Test results summary' { $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' + $formattedContainerDuration = $container.Duration | Format-TimeSpan -AdaptiveRounding $summaryMarkdown += @" -

$Indent$containerStatusIcon - $containerName +
$Indent$containerStatusIcon - $containerName ()

"@ From 2e01460d1c9ea859f74bd5578c3c837e5a11514e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 17:12:36 +0100 Subject: [PATCH 141/176] Refactor Format-TimeSpan to use AdaptivePrecision for improved duration formatting --- scripts/Helpers.psm1 | 173 +++++++++++++++++++------------------------ scripts/main.ps1 | 2 +- 2 files changed, 79 insertions(+), 96 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index c4a0a26e..c576e434 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -103,9 +103,8 @@ filter Format-TimeSpan { [ValidateSet('Years', 'Months', 'Weeks', 'Days', 'Hours', 'Minutes', 'Seconds', 'Milliseconds', 'Microseconds', 'Nanoseconds')] [string] $Precision = 'Nanoseconds', - # If set to $true, do a rounding pass from nanoseconds -> microseconds -> milliseconds -> seconds, etc. - # so that e.g. 999ms + leftover microseconds could become 1s, dropping microseconds/nanoseconds. - [switch] $AdaptiveRounding + # If set, round the entire timespan to the nearest integer in the highest allowed unit. + [switch] $AdaptivePrecission ) #----- 1) Handle negative TimeSpan ----- @@ -114,6 +113,9 @@ filter Format-TimeSpan { $TimeSpan = New-TimeSpan -Ticks (-1 * $TimeSpan.Ticks) } + # Save original ticks for later fractional math. + $originalTicks = $TimeSpan.Ticks + #----- 2) Define constants ----- [long] $ticks = $TimeSpan.Ticks @@ -164,66 +166,20 @@ filter Format-TimeSpan { # leftover ticks * 100 ns = nanoseconds $nanoseconds = $ticks * 100 - #----- 4) If requested, do an adaptive "rounding up" pass ----- - if ($AdaptiveRounding) { - # Round nanoseconds -> microseconds - # e.g. if nano >= 500, round up microseconds by 1 - if ($nanoseconds -ge 500) { - $microseconds++ - } - $nanoseconds = 0 - - # Carry microseconds -> milliseconds - if ($microseconds -ge 1000) { - $milliseconds += [math]::Floor($microseconds / 1000) - $microseconds = $microseconds % 1000 - } - - # Carry milliseconds -> seconds - if ($milliseconds -ge 1000) { - $seconds += [math]::Floor($milliseconds / 1000) - $milliseconds = $milliseconds % 1000 - } - - # Carry seconds -> minutes - if ($seconds -ge 60) { - $minutes += [math]::Floor($seconds / 60) - $seconds = $seconds % 60 - } - - # Carry minutes -> hours - if ($minutes -ge 60) { - $hours += [math]::Floor($minutes / 60) - $minutes = $minutes % 60 - } - - # Carry hours -> days - if ($hours -ge 24) { - $days += [math]::Floor($hours / 24) - $hours = $hours % 24 - } - - # Carry days -> weeks - if ($days -ge 7) { - $weeks += [math]::Floor($days / 7) - $days = $days % 7 - } - - # Approx: 4 weeks = 1 month - if ($weeks -ge 4) { - $months += [math]::Floor($weeks / 4) - $weeks = $weeks % 4 - } - - # 12 months = 1 year - if ($months -ge 12) { - $years += [math]::Floor($months / 12) - $months = $months % 12 - } - } + #----- 4) Build a list of components ----- + $components = [System.Collections.Generic.List[object]]::new() + $components.Add(@('Years', $years, 'y')) + $components.Add(@('Months', $months, 'mo')) + $components.Add(@('Weeks', $weeks, 'w')) + $components.Add(@('Days', $days, 'd')) + $components.Add(@('Hours', $hours, 'h')) + $components.Add(@('Minutes', $minutes, 'm')) + $components.Add(@('Seconds', $seconds, 's')) + $components.Add(@('Milliseconds', $milliseconds, 'ms')) + $components.Add(@('Microseconds', $microseconds, 'us')) + $components.Add(@('Nanoseconds', $nanoseconds, 'ns')) - #----- 5) Apply Precision Filtering ----- - # Map each unit to a numeric rank + # Map each unit to a numeric rank (lower = more significant) $unitRank = @{ 'Years' = 1 'Months' = 2 @@ -238,42 +194,69 @@ filter Format-TimeSpan { } [int] $lowestUnitAllowed = $unitRank[$Precision] - # Gather all units in descending order - $components = [System.Collections.Generic.List[object]]::new() - $components.Add(@('Years', $years, 'y')) - $components.Add(@('Months', $months, 'mo')) - $components.Add(@('Weeks', $weeks, 'w')) - $components.Add(@('Days', $days, 'd')) - $components.Add(@('Hours', $hours, 'h')) - $components.Add(@('Minutes', $minutes, 'm')) - $components.Add(@('Seconds', $seconds, 's')) - $components.Add(@('Milliseconds', $milliseconds, 'ms')) - $components.Add(@('Microseconds', $microseconds, 'us')) - $components.Add(@('Nanoseconds', $nanoseconds, 'ns')) - - # Filter out units that rank below the chosen precision or have zero value - $parts = foreach ($item in $components) { - $name = $item[0] - $value = $item[1] - $abbr = $item[2] - if ($unitRank[$name] -le $lowestUnitAllowed -and $value -ne 0) { - "$value$abbr" + #----- 5) Adaptive rounding (if switch set) ----- + if ($AdaptivePrecission) { + + # Find the first (highest) allowed unit that is nonzero. + $highestUnitComponent = $null + foreach ($comp in $components) { + $unitName = $comp[0] + $value = $comp[1] + if ($unitRank[$unitName] -le $lowestUnitAllowed -and $value -ne 0) { + $highestUnitComponent = $comp + break + } + } + if (-not $highestUnitComponent) { + # If none of the allowed components are nonzero, use the one matching $Precision. + $highestUnitComponent = $components | Where-Object { $_[0] -eq $Precision } | Select-Object -First 1 + } + $unitName = $highestUnitComponent[0] + $unitAbbr = $highestUnitComponent[2] + + # Compute the full timespan in the chosen unit. + switch ($unitName) { + 'Years' { $fractionalValue = $originalTicks / $ticksInYear } + 'Months' { $fractionalValue = $originalTicks / $ticksInMonth } + 'Weeks' { $fractionalValue = $originalTicks / $ticksInWeek } + 'Days' { $fractionalValue = $originalTicks / $ticksInDay } + 'Hours' { $fractionalValue = $originalTicks / $ticksInHour } + 'Minutes' { $fractionalValue = $originalTicks / $ticksInMinute } + 'Seconds' { $fractionalValue = $originalTicks / $ticksInSecond } + 'Milliseconds' { $fractionalValue = $originalTicks / $ticksInMillisecond } + 'Microseconds' { $fractionalValue = $originalTicks / 10 } + 'Nanoseconds' { $fractionalValue = $originalTicks * 100 } } - } - # If no parts remain, it means everything was 0 => "0s" - if ($parts.Count -eq 0) { - $parts = @('0s') - } + # Round to the nearest integer (i.e. if at least half the next unit, round up) + $roundedValue = [math]::Round($fractionalValue, 0, [System.MidpointRounding]::AwayFromZero) + $formatted = "$roundedValue$unitAbbr" - $formatted = $parts -join ' ' + if ($isNegative) { + $formatted = "-$formatted" + } + return $formatted + } else { + #----- 6) Normal behavior: filter and output multiple components ----- + $parts = foreach ($item in $components) { + $name = $item[0] + $value = $item[1] + $abbr = $item[2] + if ($unitRank[$name] -le $lowestUnitAllowed -and $value -ne 0) { + "$value$abbr" + } + } - #----- 6) Reapply sign if negative ----- - if ($isNegative) { - $formatted = "-$formatted" - } + if ($parts.Count -eq 0) { + $parts = @('0s') + } + $formatted = $parts -join ' ' - return $formatted + if ($isNegative) { + $formatted = "-$formatted" + } + return $formatted + } } function Get-GroupedTestMarkdown { @@ -294,7 +277,7 @@ function Get-GroupedTestMarkdown { # Calculate aggregate duration: sum all test durations $groupDuration = [System.TimeSpan]::Zero $groupTests.Duration | ForEach-Object { $groupDuration += $_ } - $formattedGroupDuration = $groupDuration | Format-TimeSpan -AdaptiveRounding + $formattedGroupDuration = $groupDuration | Format-TimeSpan -AdaptivePrecission # If any test has further parts, create a nested details block... if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { @@ -311,7 +294,7 @@ $(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1)) foreach ($test in $groupTests) { $testName = $test.Path[$Depth] $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' - $formattedDuration = $test.Duration | Format-TimeSpan -AdaptiveRounding + $formattedDuration = $test.Duration | Format-TimeSpan -AdaptivePrecission $markdown += @"

$groupIndent$testStatusIcon - $testName ($formattedDuration)

diff --git a/scripts/main.ps1 b/scripts/main.ps1 index cf65c202..f88b7abb 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -300,7 +300,7 @@ LogGroup 'Test results summary' { $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' - $formattedContainerDuration = $container.Duration | Format-TimeSpan -AdaptiveRounding + $formattedContainerDuration = $container.Duration | Format-TimeSpan -AdaptivePrecission $summaryMarkdown += @"

$Indent$containerStatusIcon - $containerName ()

From 2f0a081ac682c94f1a3a506ed78958680ddf6980 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 17:19:10 +0100 Subject: [PATCH 142/176] Refactor Format-TimeSpan to remove AdaptivePrecision parameter for simplified duration formatting --- scripts/Helpers.psm1 | 153 +++++++++++++++---------------------------- scripts/main.ps1 | 4 +- 2 files changed, 55 insertions(+), 102 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index c576e434..dd809d4a 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -94,17 +94,8 @@ function Merge-Hashtable { filter Format-TimeSpan { [CmdletBinding()] param( - [Parameter(Mandatory, - ValueFromPipeline, - ValueFromPipelineByPropertyName - )] - [TimeSpan] $TimeSpan, - - [ValidateSet('Years', 'Months', 'Weeks', 'Days', 'Hours', 'Minutes', 'Seconds', 'Milliseconds', 'Microseconds', 'Nanoseconds')] - [string] $Precision = 'Nanoseconds', - - # If set, round the entire timespan to the nearest integer in the highest allowed unit. - [switch] $AdaptivePrecission + [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] + [TimeSpan] $TimeSpan ) #----- 1) Handle negative TimeSpan ----- @@ -113,15 +104,13 @@ filter Format-TimeSpan { $TimeSpan = New-TimeSpan -Ticks (-1 * $TimeSpan.Ticks) } - # Save original ticks for later fractional math. + # Save original ticks for fractional math. $originalTicks = $TimeSpan.Ticks #----- 2) Define constants ----- [long] $ticks = $TimeSpan.Ticks - - # 1 tick = 100 ns [long] $ticksInMillisecond = 10000 # 1 ms = 10,000 ticks - [long] $ticksInSecond = 10000000 # 1 s = 10,000,000 ticks + [long] $ticksInSecond = 10000000 # 1 s = 10,000,000 ticks [long] $ticksInMinute = $ticksInSecond * 60 [long] $ticksInHour = $ticksInMinute * 60 [long] $ticksInDay = $ticksInHour * 24 @@ -130,40 +119,28 @@ filter Format-TimeSpan { # Approximate day-based constants for months & years [double] $daysInMonth = 30.436875 [double] $daysInYear = 365.2425 - [long] $ticksInMonth = [long]($daysInMonth * $ticksInDay) [long] $ticksInYear = [long]($daysInYear * $ticksInDay) #----- 3) Extract units from largest to smallest ----- $years = [math]::Floor($ticks / $ticksInYear) - $ticks = $ticks % $ticksInYear - + $ticks %= $ticksInYear $months = [math]::Floor($ticks / $ticksInMonth) - $ticks = $ticks % $ticksInMonth - + $ticks %= $ticksInMonth $weeks = [math]::Floor($ticks / $ticksInWeek) - $ticks = $ticks % $ticksInWeek - + $ticks %= $ticksInWeek $days = [math]::Floor($ticks / $ticksInDay) - $ticks = $ticks % $ticksInDay - + $ticks %= $ticksInDay $hours = [math]::Floor($ticks / $ticksInHour) - $ticks = $ticks % $ticksInHour - + $ticks %= $ticksInHour $minutes = [math]::Floor($ticks / $ticksInMinute) - $ticks = $ticks % $ticksInMinute - + $ticks %= $ticksInMinute $seconds = [math]::Floor($ticks / $ticksInSecond) - $ticks = $ticks % $ticksInSecond - + $ticks %= $ticksInSecond $milliseconds = [math]::Floor($ticks / $ticksInMillisecond) - $ticks = $ticks % $ticksInMillisecond - - # 1 tick = 100 ns, so microseconds = leftover ticks / 10 + $ticks %= $ticksInMillisecond $microseconds = [math]::Floor($ticks / 10) - $ticks = $ticks % 10 - - # leftover ticks * 100 ns = nanoseconds + $ticks %= 10 $nanoseconds = $ticks * 100 #----- 4) Build a list of components ----- @@ -192,71 +169,47 @@ filter Format-TimeSpan { 'Microseconds' = 9 'Nanoseconds' = 10 } - [int] $lowestUnitAllowed = $unitRank[$Precision] - - #----- 5) Adaptive rounding (if switch set) ----- - if ($AdaptivePrecission) { - - # Find the first (highest) allowed unit that is nonzero. - $highestUnitComponent = $null - foreach ($comp in $components) { - $unitName = $comp[0] - $value = $comp[1] - if ($unitRank[$unitName] -le $lowestUnitAllowed -and $value -ne 0) { - $highestUnitComponent = $comp - break - } + # With no Precision parameter, allow all units (Nanoseconds rank is 10) + [int] $lowestUnitAllowed = 10 + + #----- 5) Adaptive rounding: Pick the first (highest) nonzero unit ----- + $highestUnitComponent = $null + foreach ($comp in $components) { + $unitName = $comp[0] + $value = $comp[1] + if ($unitRank[$unitName] -le $lowestUnitAllowed -and $value -ne 0) { + $highestUnitComponent = $comp + break } - if (-not $highestUnitComponent) { - # If none of the allowed components are nonzero, use the one matching $Precision. - $highestUnitComponent = $components | Where-Object { $_[0] -eq $Precision } | Select-Object -First 1 - } - $unitName = $highestUnitComponent[0] - $unitAbbr = $highestUnitComponent[2] - - # Compute the full timespan in the chosen unit. - switch ($unitName) { - 'Years' { $fractionalValue = $originalTicks / $ticksInYear } - 'Months' { $fractionalValue = $originalTicks / $ticksInMonth } - 'Weeks' { $fractionalValue = $originalTicks / $ticksInWeek } - 'Days' { $fractionalValue = $originalTicks / $ticksInDay } - 'Hours' { $fractionalValue = $originalTicks / $ticksInHour } - 'Minutes' { $fractionalValue = $originalTicks / $ticksInMinute } - 'Seconds' { $fractionalValue = $originalTicks / $ticksInSecond } - 'Milliseconds' { $fractionalValue = $originalTicks / $ticksInMillisecond } - 'Microseconds' { $fractionalValue = $originalTicks / 10 } - 'Nanoseconds' { $fractionalValue = $originalTicks * 100 } - } - - # Round to the nearest integer (i.e. if at least half the next unit, round up) - $roundedValue = [math]::Round($fractionalValue, 0, [System.MidpointRounding]::AwayFromZero) - $formatted = "$roundedValue$unitAbbr" - - if ($isNegative) { - $formatted = "-$formatted" - } - return $formatted - } else { - #----- 6) Normal behavior: filter and output multiple components ----- - $parts = foreach ($item in $components) { - $name = $item[0] - $value = $item[1] - $abbr = $item[2] - if ($unitRank[$name] -le $lowestUnitAllowed -and $value -ne 0) { - "$value$abbr" - } - } - - if ($parts.Count -eq 0) { - $parts = @('0s') - } - $formatted = $parts -join ' ' + } + if (-not $highestUnitComponent) { + # If all components are zero, fall back to Nanoseconds. + $highestUnitComponent = $components[-1] + } + $unitName = $highestUnitComponent[0] + $unitAbbr = $highestUnitComponent[2] + + # Compute the full timespan in the chosen unit. + switch ($unitName) { + 'Years' { $fractionalValue = $originalTicks / $ticksInYear } + 'Months' { $fractionalValue = $originalTicks / $ticksInMonth } + 'Weeks' { $fractionalValue = $originalTicks / $ticksInWeek } + 'Days' { $fractionalValue = $originalTicks / $ticksInDay } + 'Hours' { $fractionalValue = $originalTicks / $ticksInHour } + 'Minutes' { $fractionalValue = $originalTicks / $ticksInMinute } + 'Seconds' { $fractionalValue = $originalTicks / $ticksInSecond } + 'Milliseconds' { $fractionalValue = $originalTicks / $ticksInMillisecond } + 'Microseconds' { $fractionalValue = $originalTicks / 10 } + 'Nanoseconds' { $fractionalValue = $originalTicks * 100 } + } - if ($isNegative) { - $formatted = "-$formatted" - } - return $formatted + # Round to the nearest integer. + $roundedValue = [math]::Round($fractionalValue, 0, [System.MidpointRounding]::AwayFromZero) + $formatted = "$roundedValue$unitAbbr" + if ($isNegative) { + $formatted = "-$formatted" } + return $formatted } function Get-GroupedTestMarkdown { @@ -277,7 +230,7 @@ function Get-GroupedTestMarkdown { # Calculate aggregate duration: sum all test durations $groupDuration = [System.TimeSpan]::Zero $groupTests.Duration | ForEach-Object { $groupDuration += $_ } - $formattedGroupDuration = $groupDuration | Format-TimeSpan -AdaptivePrecission + $formattedGroupDuration = $groupDuration | Format-TimeSpan # If any test has further parts, create a nested details block... if ($groupTests | Where-Object { $_.Path.Count -gt ($Depth + 1) }) { @@ -294,7 +247,7 @@ $(Get-GroupedTestMarkdown -Tests $groupTests -Depth ($Depth + 1)) foreach ($test in $groupTests) { $testName = $test.Path[$Depth] $testStatusIcon = $test.Result -eq 'Passed' ? '✅' : '❌' - $formattedDuration = $test.Duration | Format-TimeSpan -AdaptivePrecission + $formattedDuration = $test.Duration | Format-TimeSpan $markdown += @"

$groupIndent$testStatusIcon - $testName ($formattedDuration)

diff --git a/scripts/main.ps1 b/scripts/main.ps1 index f88b7abb..1d2bffed 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -300,9 +300,9 @@ LogGroup 'Test results summary' { $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' Write-Verbose "Container name: [$containerName]" -Verbose $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' - $formattedContainerDuration = $container.Duration | Format-TimeSpan -AdaptivePrecission + $formattedContainerDuration = $container.Duration | Format-TimeSpan $summaryMarkdown += @" -

$Indent$containerStatusIcon - $containerName () +
$Indent$containerStatusIcon - $containerName ($formattedContainerDuration)

"@ From b1874249d9f8c38a91527fa2697df8aa41e8f645 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 17:36:03 +0100 Subject: [PATCH 143/176] Add formatted test duration to summary markdown for improved clarity --- scripts/main.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 1d2bffed..c3f246d5 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -282,13 +282,14 @@ LogGroup 'Test results summary' { $testSuitName = $($configuration.TestResult.TestSuiteName) $testSuitStatusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } + $formattedTestDuration = $testResults.Duration | Format-TimeSpan $summaryMarkdown = @" ### $testSuitName - Test Results | Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | | ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | | $testSuitStatusIcon | $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | -

$testSuitStatusIcon - $testSuitName +
$testSuitStatusIcon - $testSuitName ($formattedTestDuration)

"@ From f68664fdb35270f6811768dcda56d64654178f01 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 18:32:36 +0100 Subject: [PATCH 144/176] Initialize container configuration if not set during load --- scripts/main.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index c3f246d5..4203d6b3 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -239,11 +239,13 @@ LogGroup 'Load configuration - Add containers' { TestRegistry = $testRegistry } $containers = Get-PesterContainer -Path $configuration.Run.Path + if (-not $configuration.Run.Container) { + $configuration.Run.Container = $containers | ForEach-Object { New-PesterContainer $_ } + } Write-Output ($containers | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) } LogGroup 'Load configuration - Result' { - $configuration.Run.Container += $containers | ForEach-Object { New-PesterContainer @_ } Write-Output ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } From e2ef1f0af17e70939775061838cb516b5273b0fc Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 18:35:45 +0100 Subject: [PATCH 145/176] Refactor container initialization in Pester configuration scripts for improved clarity and consistency --- tests/2-Standard/Emoji.Configuration.ps1 | 2 +- tests/3-Advanced/Pester.Configuration.ps1 | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/2-Standard/Emoji.Configuration.ps1 b/tests/2-Standard/Emoji.Configuration.ps1 index 43798070..61ec8184 100644 --- a/tests/2-Standard/Emoji.Configuration.ps1 +++ b/tests/2-Standard/Emoji.Configuration.ps1 @@ -1,7 +1,7 @@ @{ Run = @{ Path = $PSScriptRoot - Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* | ForEach-Object { . $_ } + Container = [PesterContainer](Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* | ForEach-Object { . $_ }) PassThru = $true } TestResult = @{ diff --git a/tests/3-Advanced/Pester.Configuration.ps1 b/tests/3-Advanced/Pester.Configuration.ps1 index ccb0f145..066f53b9 100644 --- a/tests/3-Advanced/Pester.Configuration.ps1 +++ b/tests/3-Advanced/Pester.Configuration.ps1 @@ -1,9 +1,9 @@ @{ Run = @{ - Path = $PSScriptRoot - PassThru = $true - # Container = Get-ChildItem -Path $config.Run.Path.Value -Filter *.Container.* -Recurse | - # ForEach-Object { . $_ } | ForEach-Object { New-PesterContainer @_ } + Path = $PSScriptRoot + PassThru = $true + Container = Get-ChildItem -Path $config.Run.Path.Value -Filter *.Container.* -Recurse | + ForEach-Object { . $_ } | ForEach-Object { New-PesterContainer @_ } } TestResult = @{ Enabled = $true From 791a8ca4b485d4d2fe6175d6a8306986c6e0d807 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 18:37:33 +0100 Subject: [PATCH 146/176] Refactor container initialization in Emoji configuration to use New-PesterContainer for improved clarity --- tests/2-Standard/Emoji.Configuration.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/2-Standard/Emoji.Configuration.ps1 b/tests/2-Standard/Emoji.Configuration.ps1 index 61ec8184..a3092f8d 100644 --- a/tests/2-Standard/Emoji.Configuration.ps1 +++ b/tests/2-Standard/Emoji.Configuration.ps1 @@ -1,7 +1,8 @@ @{ Run = @{ Path = $PSScriptRoot - Container = [PesterContainer](Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* | ForEach-Object { . $_ }) + Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* | ForEach-Object { . $_ } | + ForEach-Object { New-PesterContainer @_ } PassThru = $true } TestResult = @{ From aefe9b8f103405648f99591092010998384b7517 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 18:43:41 +0100 Subject: [PATCH 147/176] Refactor container handling in main script to improve container initialization logic and output clarity --- scripts/main.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 4203d6b3..0d13eb0d 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -238,11 +238,11 @@ LogGroup 'Load configuration - Add containers' { TestDrive = $testDrive TestRegistry = $testRegistry } - $containers = Get-PesterContainer -Path $configuration.Run.Path - if (-not $configuration.Run.Container) { + if ($configuration.Run.Container.Count -eq 0) { + $containers = Get-PesterContainer -Path $configuration.Run.Path $configuration.Run.Container = $containers | ForEach-Object { New-PesterContainer $_ } } - Write-Output ($containers | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) + Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) } LogGroup 'Load configuration - Result' { From 1574be0314ab0100195250b27315cb91bd284e25 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 18:54:18 +0100 Subject: [PATCH 148/176] Fix container initialization logic to correctly pass parameters to New-PesterContainer --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 0d13eb0d..8c207a46 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -240,7 +240,7 @@ LogGroup 'Load configuration - Add containers' { } if ($configuration.Run.Container.Count -eq 0) { $containers = Get-PesterContainer -Path $configuration.Run.Path - $configuration.Run.Container = $containers | ForEach-Object { New-PesterContainer $_ } + $configuration.Run.Container = $containers | ForEach-Object { New-PesterContainer @_ } } Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) } From 7af9e2e183dfc9db84e16cfbd5904d10a4c2968c Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 19:30:05 +0100 Subject: [PATCH 149/176] Enhance container initialization logic to dynamically load containers from specified directories and convert hashtables to PesterContainer objects --- scripts/main.ps1 | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 8c207a46..fca6ce0c 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -238,10 +238,34 @@ LogGroup 'Load configuration - Add containers' { TestDrive = $testDrive TestRegistry = $testRegistry } + # Load configuration - Add containers if ($configuration.Run.Container.Count -eq 0) { - $containers = Get-PesterContainer -Path $configuration.Run.Path - $configuration.Run.Container = $containers | ForEach-Object { New-PesterContainer @_ } + # If no containers are specified, search for "*.Container.*" files in each Run.Path directory + $configuration.Run.Container = @() # initialize as empty array + foreach ($testDir in $configuration.Run.Path) { + if (Test-Path -LiteralPath $testDir -PathType Container) { + Get-ChildItem -Path $testDir -Filter '*.Container.*' -File -Recurse | ForEach-Object { + # Create a Pester container object for each found file + $configuration.Run.Container += New-PesterContainer -Path $_.FullName + } + } + } } + + # If any containers are defined as hashtables, convert them to PesterContainer objects + for ($i = 0; $i -lt $configuration.Run.Container.Count; $i++) { + $entry = $configuration.Run.Container[$i] + if ($entry -is [hashtable]) { + if ($entry.ContainsKey('Path')) { + # Convert hashtable with Path to a ContainerInfo object + $configuration.Run.Container[$i] = New-PesterContainer -Path $entry.Path -Data $entry.Data + } elseif ($entry.ContainsKey('ScriptBlock')) { + # Convert hashtable with ScriptBlock to a ContainerInfo object + $configuration.Run.Container[$i] = New-PesterContainer -ScriptBlock $entry.ScriptBlock -Data $entry.Data + } + } + } + Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) } From 10afe25a92d1673805dd39e90c8fd16c3fa51d7e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 19:34:57 +0100 Subject: [PATCH 150/176] Refactor Emoji configuration to simplify container initialization logic --- tests/2-Standard/Emoji.Configuration.ps1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/2-Standard/Emoji.Configuration.ps1 b/tests/2-Standard/Emoji.Configuration.ps1 index a3092f8d..43798070 100644 --- a/tests/2-Standard/Emoji.Configuration.ps1 +++ b/tests/2-Standard/Emoji.Configuration.ps1 @@ -1,8 +1,7 @@ @{ Run = @{ Path = $PSScriptRoot - Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* | ForEach-Object { . $_ } | - ForEach-Object { New-PesterContainer @_ } + Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* | ForEach-Object { . $_ } PassThru = $true } TestResult = @{ From 2070be18de79deba5bb1a3a13734a3e9b54dd76a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 19:37:44 +0100 Subject: [PATCH 151/176] Remove direct container loading from Emoji configuration to streamline initialization --- tests/2-Standard/Emoji.Configuration.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/2-Standard/Emoji.Configuration.ps1 b/tests/2-Standard/Emoji.Configuration.ps1 index 43798070..059a0990 100644 --- a/tests/2-Standard/Emoji.Configuration.ps1 +++ b/tests/2-Standard/Emoji.Configuration.ps1 @@ -1,7 +1,6 @@ @{ Run = @{ Path = $PSScriptRoot - Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* | ForEach-Object { . $_ } PassThru = $true } TestResult = @{ From c30a623ed152ee7228c5dbfdf657f29b03e205ec Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 19:44:50 +0100 Subject: [PATCH 152/176] Refactor container initialization to simplify conversion of hashtables to PesterContainer objects --- scripts/main.ps1 | 9 ++------- tests/2-Standard/Emoji.Configuration.ps1 | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index fca6ce0c..1daa47b2 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -256,13 +256,8 @@ LogGroup 'Load configuration - Add containers' { for ($i = 0; $i -lt $configuration.Run.Container.Count; $i++) { $entry = $configuration.Run.Container[$i] if ($entry -is [hashtable]) { - if ($entry.ContainsKey('Path')) { - # Convert hashtable with Path to a ContainerInfo object - $configuration.Run.Container[$i] = New-PesterContainer -Path $entry.Path -Data $entry.Data - } elseif ($entry.ContainsKey('ScriptBlock')) { - # Convert hashtable with ScriptBlock to a ContainerInfo object - $configuration.Run.Container[$i] = New-PesterContainer -ScriptBlock $entry.ScriptBlock -Data $entry.Data - } + $cont = $configuration.Run.Container[$i] + $configuration.Run.Container[$i] = New-PesterContainer @cont } } diff --git a/tests/2-Standard/Emoji.Configuration.ps1 b/tests/2-Standard/Emoji.Configuration.ps1 index 059a0990..fe7f2df2 100644 --- a/tests/2-Standard/Emoji.Configuration.ps1 +++ b/tests/2-Standard/Emoji.Configuration.ps1 @@ -1,7 +1,7 @@ @{ Run = @{ - Path = $PSScriptRoot - PassThru = $true + Path = $PSScriptRoot + PassThru = $true } TestResult = @{ Enabled = $true From 067202d7bcebf64fa826c0d89c59f9e6b6a49418 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 19:50:08 +0100 Subject: [PATCH 153/176] Refactor container loading logic to utilize Get-PesterContainer for directory-based container retrieval --- scripts/main.ps1 | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 1daa47b2..2641e284 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -241,23 +241,18 @@ LogGroup 'Load configuration - Add containers' { # Load configuration - Add containers if ($configuration.Run.Container.Count -eq 0) { # If no containers are specified, search for "*.Container.*" files in each Run.Path directory - $configuration.Run.Container = @() # initialize as empty array foreach ($testDir in $configuration.Run.Path) { if (Test-Path -LiteralPath $testDir -PathType Container) { - Get-ChildItem -Path $testDir -Filter '*.Container.*' -File -Recurse | ForEach-Object { - # Create a Pester container object for each found file - $configuration.Run.Container += New-PesterContainer -Path $_.FullName - } + $configuration.Run.Container += Get-PesterContainer -Path $testDir } } } # If any containers are defined as hashtables, convert them to PesterContainer objects for ($i = 0; $i -lt $configuration.Run.Container.Count; $i++) { - $entry = $configuration.Run.Container[$i] - if ($entry -is [hashtable]) { - $cont = $configuration.Run.Container[$i] - $configuration.Run.Container[$i] = New-PesterContainer @cont + $cntnr = $configuration.Run.cntnrainer[$i] + if ($cntnr -is [hashtable]) { + $configuration.Run.Container[$i] = New-PesterContainer @cntnr } } From 79f32afa25c77c23a35702c517a9d53a67c72119 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 19:53:39 +0100 Subject: [PATCH 154/176] Fix typo in container retrieval logic to correctly reference the Container array --- scripts/main.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 2641e284..73860194 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -250,7 +250,7 @@ LogGroup 'Load configuration - Add containers' { # If any containers are defined as hashtables, convert them to PesterContainer objects for ($i = 0; $i -lt $configuration.Run.Container.Count; $i++) { - $cntnr = $configuration.Run.cntnrainer[$i] + $cntnr = $configuration.Run.Container[$i] if ($cntnr -is [hashtable]) { $configuration.Run.Container[$i] = New-PesterContainer @cntnr } From 6fac8ada365a4a7153eea67cb72bb51da640080e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 20:16:15 +0100 Subject: [PATCH 155/176] Clean up whitespace in configuration initialization --- scripts/main.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 73860194..50a7d40f 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -79,8 +79,8 @@ LogGroup 'Load inputs' { [pscustomobject]($inputs.GetEnumerator() | Where-Object { -not [string]::IsNullOrEmpty($_.Value) }) | Format-List } -$customConfig = @{ } -$customInputs = @{ } +$customConfig = @{} +$customInputs = @{} LogGroup 'Load configuration - Defaults' { $defaultConfigPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') From 53d85f753a37d5b6b01a95c72f743868910cd7d7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 20:19:48 +0100 Subject: [PATCH 156/176] Fix expected output for Get-Emoji test to return the correct emoji for giraffe --- tests/3-Advanced/Emoji/Emoji.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/3-Advanced/Emoji/Emoji.Tests.ps1 b/tests/3-Advanced/Emoji/Emoji.Tests.ps1 index 2615e7bb..78f88ae3 100644 --- a/tests/3-Advanced/Emoji/Emoji.Tests.ps1 +++ b/tests/3-Advanced/Emoji/Emoji.Tests.ps1 @@ -17,7 +17,7 @@ Describe 'Get-Emoji' { } It 'Returns 🦒 (giraffe)' { - Get-Emoji -Name giraffe | Should -Be '🌵'#'🦒' + Get-Emoji -Name giraffe | Should -Be '🦒' } } From 27d99ca8f44a4663bf19437c6bdb6952a737e8d5 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 20:24:02 +0100 Subject: [PATCH 157/176] Update test results summary markdown format for improved readability --- scripts/main.ps1 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 50a7d40f..4750670a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -300,13 +300,14 @@ LogGroup 'Test results summary' { $testSuitStatusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } $formattedTestDuration = $testResults.Duration | Format-TimeSpan $summaryMarkdown = @" -### $testSuitName - Test Results -| Status | Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | -| ----- | ----- | ------ | ------ | ------- | ------------ | ------ | -------- | -| $testSuitStatusIcon | $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString |

$testSuitStatusIcon - $testSuitName ($formattedTestDuration)

+ +| Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | +| ----- | ------ | ------ | ------- | ------------ | ------ | -------- | +| $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | + "@ Write-Verbose "Processing containers [$($testResults.Containers.Count)]" -Verbose From ad40c31d2d51275c056612c30674d4c7a7e92a7e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 20:42:03 +0100 Subject: [PATCH 158/176] Add output statements to log container counts and details during configuration loading --- scripts/main.ps1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 4750670a..7605d092 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -238,6 +238,10 @@ LogGroup 'Load configuration - Add containers' { TestDrive = $testDrive TestRegistry = $testRegistry } + + Write-Output "Containers from configuration: [$($configuration.Run.Container.Count)]" + Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) + # Load configuration - Add containers if ($configuration.Run.Container.Count -eq 0) { # If no containers are specified, search for "*.Container.*" files in each Run.Path directory @@ -256,6 +260,7 @@ LogGroup 'Load configuration - Add containers' { } } + Write-Output "Added containers: [$($configuration.Run.Container.Count)]" Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) } From bf99c9b354b7bd99e5a1838a874a4d4d350aeb99 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 20:48:16 +0100 Subject: [PATCH 159/176] Fix container retrieval logic to use the correct script root path --- tests/3-Advanced/Pester.Configuration.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/3-Advanced/Pester.Configuration.ps1 b/tests/3-Advanced/Pester.Configuration.ps1 index 066f53b9..de1437cc 100644 --- a/tests/3-Advanced/Pester.Configuration.ps1 +++ b/tests/3-Advanced/Pester.Configuration.ps1 @@ -2,7 +2,7 @@ Run = @{ Path = $PSScriptRoot PassThru = $true - Container = Get-ChildItem -Path $config.Run.Path.Value -Filter *.Container.* -Recurse | + Container = Get-ChildItem -Path $PSScriptRoot -Filter *.Container.* -Recurse | ForEach-Object { . $_ } | ForEach-Object { New-PesterContainer @_ } } TestResult = @{ From c3783b25a9dc58fdb526c1b0e5f01b6ad5290d49 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 21:26:35 +0100 Subject: [PATCH 160/176] Enhance action.yml to include detailed test result outputs and upload artifacts for test results and code coverage --- README.md | 13 ------ action.yml | 112 ++++++++++++++++++++++++++++++++++++++++++++++- scripts/main.ps1 | 6 +-- 3 files changed, 111 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 49c9c0b5..3e74c20c 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,6 @@ A template repository for GitHub Actions -

- Outer Details - Outer details content. - -
- Inner Details - Inner details content. -
- - More outer details content. -
- ## Usage ### Inputs @@ -27,4 +15,3 @@ A template repository for GitHub Actions ```yaml Example here ``` - diff --git a/action.yml b/action.yml index a2cb371c..d8d52f90 100644 --- a/action.yml +++ b/action.yml @@ -193,9 +193,102 @@ inputs: required: false default: 'false' outputs: - result: + Containers: + description: Containers object used during the test. + value: ${{ fromJSON(steps.test.outputs.result).Containers }} + Result: description: If the tests passed. - value: ${{ fromJSON(steps.test.outputs.result).result }} + value: ${{ fromJSON(steps.test.outputs.result).Result }} + FailedCount: + description: Number of failed tests. + value: ${{ fromJSON(steps.test.outputs.result).FailedCount }} + FailedBlocksCount: + description: Number of failed blocks. + value: ${{ fromJSON(steps.test.outputs.result).FailedBlocksCount }} + FailedContainersCount: + description: Number of failed containers. + value: ${{ fromJSON(steps.test.outputs.result).FailedContainersCount }} + PassedCount: + description: Number of passed tests. + value: ${{ fromJSON(steps.test.outputs.result).PassedCount }} + SkippedCount: + description: Number of skipped tests. + value: ${{ fromJSON(steps.test.outputs.result).SkippedCount }} + InconclusiveCount: + description: Number of inconclusive tests. + value: ${{ fromJSON(steps.test.outputs.result).InconclusiveCount }} + NotRunCount: + description: Number of tests that were not run. + value: ${{ fromJSON(steps.test.outputs.result).NotRunCount }} + TotalCount: + description: Total number of tests. + value: ${{ fromJSON(steps.test.outputs.result).TotalCount }} + Duration: + description: Duration of the test run. + value: ${{ fromJSON(steps.test.outputs.result).Duration }} + Executed: + description: Number of tests executed. + value: ${{ fromJSON(steps.test.outputs.result).Executed }} + ExecutedAt: + description: Time when the tests were executed. + value: ${{ fromJSON(steps.test.outputs.result).ExecutedAt }} + Version: + description: Version of Pester used. + value: ${{ fromJSON(steps.test.outputs.result).Version }} + PSVersion: + description: Version of PowerShell used. + value: ${{ fromJSON(steps.test.outputs.result).PSVersion }} + PSBoundParameters: + description: Parameters used to run the tests. + value: ${{ fromJSON(steps.test.outputs.result).PSBoundParameters }} + Plugins: + description: Plugins used during the test run. + value: ${{ fromJSON(steps.test.outputs.result).Plugins }} + PluginConfiguration: + description: Configuration of the plugins. + value: ${{ fromJSON(steps.test.outputs.result).PluginConfiguration }} + PluginData: + description: Data of the plugins. + value: ${{ fromJSON(steps.test.outputs.result).PluginData }} + Configuration: + description: Configuration used during the test run. + value: ${{ fromJSON(steps.test.outputs.result).Configuration }} + DiscoveryDuration: + description: Duration of the discovery phase. + value: ${{ fromJSON(steps.test.outputs.result).DiscoveryDuration }} + UserDuration: + description: Duration of the user code execution. + value: ${{ fromJSON(steps.test.outputs.result).UserDuration }} + FrameworkDuration: + description: Duration of the framework code execution. + value: ${{ fromJSON(steps.test.outputs.result).FrameworkDuration }} + Failed: + description: Failed tests. + value: ${{ fromJSON(steps.test.outputs.result).Failed }} + FailedBlocks: + description: Failed blocks. + value: ${{ fromJSON(steps.test.outputs.result).FailedBlocks }} + FailedContainers: + description: Failed containers. + value: ${{ fromJSON(steps.test.outputs.result).FailedContainers }} + Passed: + description: Passed tests. + value: ${{ fromJSON(steps.test.outputs.result).Passed }} + Skipped: + description: Skipped tests. + value: ${{ fromJSON(steps.test.outputs.result).Skipped }} + Inconclusive: + description: Inconclusive tests. + value: ${{ fromJSON(steps.test.outputs.result).Inconclusive }} + NotRun: + description: Tests that were not run. + value: ${{ fromJSON(steps.test.outputs.result).NotRun }} + Tests: + description: All tests. + value: ${{ fromJSON(steps.test.outputs.result).Tests }} + CodeCoverage: + description: Code coverage report. + value: ${{ fromJSON(steps.test.outputs.result).CodeCoverage }} runs: using: composite @@ -206,6 +299,7 @@ runs: - name: Invoke-Pester uses: PSModule/GitHub-Script@v1 id: test + continue-on-error: true env: GITHUB_ACTION_INPUT_Run_Path: ${{ inputs.Run_Path }} GITHUB_ACTION_INPUT_Run_ExcludePath: ${{ inputs.Run_ExcludePath }} @@ -256,3 +350,17 @@ runs: Script: | # Invoke-Pester ${{ github.action_path }}\scripts\main.ps1 + + - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-TestResults] + uses: actions/upload-artifact@v4 + if: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.Enabled.Value && (success() || failure()) }} + with: + name: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-TestResults + path: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.OutputPath.Value }} + + - name: Upload code coverage report - [${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-CodeCoverage] + uses: actions/upload-artifact@v4 + if: ${{ fromJSON(steps.test.outputs.result).Configuration.CodeCoverage.Enabled.Value && (success() || failure()) }} + with: + name: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-CodeCoverage + path: ${{ fromJSON(steps.test.outputs.result).Configuration.CodeCoverage.OutputPath.Value }} diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 7605d092..92ea1e2c 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -353,13 +353,9 @@ LogGroup 'Test results summary' { Set-GitHubStepSummary -Summary $summaryMarkdown } -$results = $testResults | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue -# Provide structured JSON as an output for potential downstream steps -Set-GitHubOutput -Name 'results' -Value $results - # For each property of testresults, output the value as a JSON object foreach ($property in $testResults.PSObject.Properties) { - Write-Verbose "Setting output for [$($property.Name)]" -Verbose + Write-Verbose "Setting output for [$($property.Name)]" $name = $property.Name $value = -not [string]::IsNullOrEmpty($property.Value) ? ($property.Value | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) : '' Set-GitHubOutput -Name $name -Value $value From e1587981c7a2d080ba3343a17c7213bbca22ead5 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 21:30:51 +0100 Subject: [PATCH 161/176] Add output check step to action.yml for enhanced test result visibility --- action.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/action.yml b/action.yml index d8d52f90..3c71ade3 100644 --- a/action.yml +++ b/action.yml @@ -351,6 +351,13 @@ runs: # Invoke-Pester ${{ github.action_path }}\scripts\main.ps1 + - name: Check outputs + shell: pwsh + env: + RESULT: ${{ fromJSON(steps.test.outputs.result) }} + run: | + $env:RESULT | ConvertTo-Json -Depth 10 + - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-TestResults] uses: actions/upload-artifact@v4 if: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.Enabled.Value && (success() || failure()) }} From 3c39ed290fa189d5037128dafc9804011f283717 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 21:33:54 +0100 Subject: [PATCH 162/176] Fix output handling in action.yml to correctly parse test results --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 3c71ade3..6fe8e8c6 100644 --- a/action.yml +++ b/action.yml @@ -354,9 +354,9 @@ runs: - name: Check outputs shell: pwsh env: - RESULT: ${{ fromJSON(steps.test.outputs.result) }} + RESULT: ${{ steps.test.outputs.result }} run: | - $env:RESULT | ConvertTo-Json -Depth 10 + $env:RESULT | ConvertFrom-Json -Depth 10 - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-TestResults] uses: actions/upload-artifact@v4 From d2830092fad1195e206d3ebb8ab9d01e469f512b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 21:43:45 +0100 Subject: [PATCH 163/176] Enhance action.yml and main.ps1 to output detailed test result and code coverage information --- action.yml | 12 ++++++++++-- scripts/main.ps1 | 6 ++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 6fe8e8c6..4a204e8a 100644 --- a/action.yml +++ b/action.yml @@ -354,9 +354,17 @@ runs: - name: Check outputs shell: pwsh env: - RESULT: ${{ steps.test.outputs.result }} + TestResultEnabled: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled }} + TestResultOutputPath: ${{ fromJSON(steps.test.outputs.result).TestResultOutputPath }} + TestSuiteName: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }} + CodeCoverageEnabled: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled }} + CodeCoverageOutputPath: ${{ fromJSON(steps.test.outputs.result).CodeCoverageOutputPath }} run: | - $env:RESULT | ConvertFrom-Json -Depth 10 + Write-Host "TestResultEnabled : $env:TestResultEnabled" + Write-Host "TestResultOutputPath : $env:TestResultOutputPath" + Write-Host "TestSuiteName : $env:TestSuiteName" + Write-Host "CodeCoverageEnabled : $env:CodeCoverageEnabled" + Write-Host "CodeCoverageOutputPath : $env:CodeCoverageOutputPath" - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-TestResults] uses: actions/upload-artifact@v4 diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 92ea1e2c..e45e8663 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -361,4 +361,10 @@ foreach ($property in $testResults.PSObject.Properties) { Set-GitHubOutput -Name $name -Value $value } +Set-GitHubOutput -Name 'TestResultEnabled' -Value $testResults.Configuration.TestResult.Enabled.Value +Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResults.Configuration.TestResult.OutputPath.Value +Set-GitHubOutput -Name 'TestSuiteName' -Value $testResults.Configuration.TestResult.TestSuiteName.Value +Set-GitHubOutput -Name 'CodeCoverageEnabled' -Value $testResults.Configuration.CodeCoverage.Enabled.Value +Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $testResults.Configuration.CodeCoverage.OutputPath.Value + exit $failedTests From 972fc2e08d237615d2a0f9f6b95127a58c00bd8b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 21:45:51 +0100 Subject: [PATCH 164/176] Fix condition checks in action.yml for uploading test results and code coverage reports --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 4a204e8a..563d23f6 100644 --- a/action.yml +++ b/action.yml @@ -368,14 +368,14 @@ runs: - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-TestResults] uses: actions/upload-artifact@v4 - if: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.Enabled.Value && (success() || failure()) }} + if: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.Enabled.Value == 'true' && (success() || failure()) }} with: name: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-TestResults path: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.OutputPath.Value }} - name: Upload code coverage report - [${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-CodeCoverage] uses: actions/upload-artifact@v4 - if: ${{ fromJSON(steps.test.outputs.result).Configuration.CodeCoverage.Enabled.Value && (success() || failure()) }} + if: ${{ fromJSON(steps.test.outputs.result).Configuration.CodeCoverage.Enabled.Value == 'true' && (success() || failure()) }} with: name: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-CodeCoverage path: ${{ fromJSON(steps.test.outputs.result).Configuration.CodeCoverage.OutputPath.Value }} From c00ae756bfbab63a09818359defa5f8b928c6e48 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 21:49:28 +0100 Subject: [PATCH 165/176] Refactor action.yml to simplify test result and code coverage report uploads --- action.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/action.yml b/action.yml index 563d23f6..9baed49e 100644 --- a/action.yml +++ b/action.yml @@ -366,16 +366,16 @@ runs: Write-Host "CodeCoverageEnabled : $env:CodeCoverageEnabled" Write-Host "CodeCoverageOutputPath : $env:CodeCoverageOutputPath" - - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-TestResults] + - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-TestResults] uses: actions/upload-artifact@v4 - if: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.Enabled.Value == 'true' && (success() || failure()) }} + if: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled == 'true' && (success() || failure()) }} with: - name: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-TestResults - path: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.OutputPath.Value }} + name: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-TestResults + path: ${{ fromJSON(steps.test.outputs.result).TestResultOutputPath }} - - name: Upload code coverage report - [${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-CodeCoverage] + - name: Upload code coverage report - [${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-CodeCoverage] uses: actions/upload-artifact@v4 - if: ${{ fromJSON(steps.test.outputs.result).Configuration.CodeCoverage.Enabled.Value == 'true' && (success() || failure()) }} + if: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled == 'true' && (success() || failure()) }} with: - name: ${{ fromJSON(steps.test.outputs.result).Configuration.TestResult.TestSuiteName.Value }}-CodeCoverage - path: ${{ fromJSON(steps.test.outputs.result).Configuration.CodeCoverage.OutputPath.Value }} + name: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-CodeCoverage + path: ${{ fromJSON(steps.test.outputs.result).CodeCoverageOutputPath }} From f6529023f9bc96b16c22d3aecec709d0eff812a2 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 21:52:58 +0100 Subject: [PATCH 166/176] Comment out condition checks for uploading test results and code coverage reports in action.yml --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 9baed49e..044948a1 100644 --- a/action.yml +++ b/action.yml @@ -368,14 +368,14 @@ runs: - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-TestResults] uses: actions/upload-artifact@v4 - if: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled == 'true' && (success() || failure()) }} + # if: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled == 'true' && (success() || failure()) }} with: name: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-TestResults path: ${{ fromJSON(steps.test.outputs.result).TestResultOutputPath }} - name: Upload code coverage report - [${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-CodeCoverage] uses: actions/upload-artifact@v4 - if: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled == 'true' && (success() || failure()) }} + # if: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled == 'true' && (success() || failure()) }} with: name: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-CodeCoverage path: ${{ fromJSON(steps.test.outputs.result).CodeCoverageOutputPath }} From 2f4520ca17396a413f2a194e4da35d94ed83d5dd Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 21:55:24 +0100 Subject: [PATCH 167/176] Add .gitattributes and update markdown-lint.yml for consistent line endings and linting rules --- .gitattributes | 15 + .github/linters/.markdown-lint.yml | 16 +- .github/workflows/Action-Test.yml | 114 ++--- .github/workflows/Auto-Release.yml | 68 +-- .github/workflows/Linter.yml | 62 +-- action.yml | 762 ++++++++++++++--------------- 6 files changed, 528 insertions(+), 509 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..96c2e0d3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +# Needed for publishing of examples, build worker defaults to core.autocrlf=input. +* text eol=autocrlf + +*.mof text eol=crlf +*.sh text eol=lf +*.svg eol=lf + +# Ensure any exe files are treated as binary +*.exe binary +*.jpg binary +*.xl* binary +*.pfx binary +*.png binary +*.dll binary +*.so binary diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml index b9ecdfa9..8e719c26 100644 --- a/.github/linters/.markdown-lint.yml +++ b/.github/linters/.markdown-lint.yml @@ -8,18 +8,18 @@ ############### # Rules by id # ############### -MD004: false # Unordered list style +MD004: false # Unordered list style MD007: - indent: 2 # Unordered list indentation + indent: 2 # Unordered list indentation MD013: - line_length: 808 # Line length + line_length: 808 # Line length MD026: - punctuation: ".,;:!。,;:" # List of not allowed -MD029: false # Ordered list item prefix -MD033: false # Allow inline HTML -MD036: false # Emphasis used instead of a heading + punctuation: '.,;:!。,;:' # List of not allowed +MD029: false # Ordered list item prefix +MD033: false # Allow inline HTML +MD036: false # Emphasis used instead of a heading ################# # Rules by tags # ################# -blank_lines: false # Error on blank lines +blank_lines: false # Error on blank lines diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index 3c90b8ff..7a4ffa3d 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -1,57 +1,57 @@ -name: Action-Test - -run-name: "Action-Test - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}" - -on: - workflow_dispatch: - pull_request: - schedule: - - cron: '0 0 * * *' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: - contents: read - pull-requests: read - -jobs: - ActionTest1Simple: - name: Action-Test - [1-Simple] - runs-on: ubuntu-latest - steps: - # Need to check out as part of the test, as its a local action - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Action-Test [1-Simple] - uses: ./ - with: - Run_Path: tests/1-Simple - - ActionTest2Standard: - name: Action-Test - [2-Standard] - runs-on: ubuntu-latest - steps: - # Need to check out as part of the test, as its a local action - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Action-Test [2-Standard] - uses: ./ - with: - Run_Path: tests/2-Standard - - ActionTestAdvanced: - name: Action-Test - [3-Advanced] - runs-on: ubuntu-latest - steps: - # Need to check out as part of the test, as its a local action - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Action-Test [3-Advanced] - uses: ./ - with: - ConfigurationFilePath: tests/3-Advanced/Pester.Configuration.ps1 +name: Action-Test + +run-name: "Action-Test - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}" + +on: + workflow_dispatch: + pull_request: + schedule: + - cron: '0 0 * * *' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: read + +jobs: + ActionTest1Simple: + name: Action-Test - [1-Simple] + runs-on: ubuntu-latest + steps: + # Need to check out as part of the test, as its a local action + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Action-Test [1-Simple] + uses: ./ + with: + Run_Path: tests/1-Simple + + ActionTest2Standard: + name: Action-Test - [2-Standard] + runs-on: ubuntu-latest + steps: + # Need to check out as part of the test, as its a local action + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Action-Test [2-Standard] + uses: ./ + with: + Run_Path: tests/2-Standard + + ActionTestAdvanced: + name: Action-Test - [3-Advanced] + runs-on: ubuntu-latest + steps: + # Need to check out as part of the test, as its a local action + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Action-Test [3-Advanced] + uses: ./ + with: + ConfigurationFilePath: tests/3-Advanced/Pester.Configuration.ps1 diff --git a/.github/workflows/Auto-Release.yml b/.github/workflows/Auto-Release.yml index d6c477b7..1a580b87 100644 --- a/.github/workflows/Auto-Release.yml +++ b/.github/workflows/Auto-Release.yml @@ -1,34 +1,34 @@ -name: Auto-Release - -run-name: "Auto-Release - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}" - -on: - pull_request_target: - branches: - - main - types: - - closed - - opened - - reopened - - synchronize - - labeled - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: - contents: write # Required to create releases - pull-requests: write # Required to create comments on the PRs - -jobs: - Auto-Release: - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Auto-Release - uses: PSModule/Auto-Release@v1 - env: - GITHUB_TOKEN: ${{ github.token }} +name: Auto-Release + +run-name: "Auto-Release - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}" + +on: + pull_request_target: + branches: + - main + types: + - closed + - opened + - reopened + - synchronize + - labeled + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: write # Required to create releases + pull-requests: write # Required to create comments on the PRs + +jobs: + Auto-Release: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Auto-Release + uses: PSModule/Auto-Release@v1 + env: + GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/Linter.yml b/.github/workflows/Linter.yml index 187c17e6..bb47b678 100644 --- a/.github/workflows/Linter.yml +++ b/.github/workflows/Linter.yml @@ -1,29 +1,33 @@ -name: Linter - -run-name: "Linter - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}" - -on: [pull_request] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: - contents: read - packages: read - statuses: write - -jobs: - Lint: - name: Lint code base - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Lint code base - uses: super-linter/super-linter/slim@latest - env: - GITHUB_TOKEN: ${{ github.token }} +name: Linter + +run-name: "Linter - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}" + +on: [pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + packages: read + statuses: write + +jobs: + Lint: + name: Lint code base + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Lint code base + uses: super-linter/super-linter/slim@latest + env: + GITHUB_TOKEN: ${{ github.token }} + VALIDATE_MARKDOWN_PRETTIER: false + VALIDATE_JSON_PRETTIER: false + VALIDATE_YAML_PRETTIER: false + VALIDATE_JSCPD: false diff --git a/action.yml b/action.yml index 044948a1..fae9af01 100644 --- a/action.yml +++ b/action.yml @@ -1,381 +1,381 @@ -name: Invoke-Pester -description: Runs test, using Pester and PowerShell. -author: PSModule -branding: - icon: check-square - color: gray-dark - -inputs: - Run_Path: - description: | - Directories to be searched for tests, paths directly to test files, or combination of both. - required: false - Run_ExcludePath: - description: | - Directories or files to be excluded from the run. - required: false - Run_ScriptBlock: - description: | - ScriptBlocks containing tests to be executed. - required: false - Run_Container: - description: | - ContainerInfo objects containing tests to be executed. - required: false - Run_TestExtension: - description: | - Filter used to identify test files. - required: false - Run_Exit: - description: | - Exit with non-zero exit code when the test run fails. Exit code is always set to `$LASTEXITCODE` even when this option is `$false`. - When used together with Throw, throwing an exception is preferred. - required: false - Run_Throw: - description: | - Throw an exception when test run fails. When used together with Exit, throwing an exception is preferred. - required: false - Run_PassThru: - description: | - Return result object to the pipeline after finishing the test run. - required: false - Run_SkipRun: - description: | - Runs the discovery phase but skips run. Use it with PassThru to get object populated with all tests. - required: false - Run_SkipRemainingOnFailure: - description: | - Skips remaining tests after failure for selected scope, options are None, Run, Container and Block. - required: false - Filter_Tag: - description: | - Tags of Describe, Context or It to be run. - required: false - Filter_ExcludeTag: - description: | - Tags of Describe, Context or It to be excluded from the run. - required: false - Filter_Line: - description: | - Filter by file and scriptblock start line, useful to run parsed tests programmatically to avoid problems with expanded names. - Example: 'C:\tests\file1.Tests.ps1:37' - required: false - Filter_ExcludeLine: - description: | - Exclude by file and scriptblock start line, takes precedence over Line. - required: false - Filter_FullName: - description: | - Full name of test with -like wildcards, joined by dot. Example: '*.describe Get-Item.test1' - required: false - CodeCoverage_Enabled: - description: | - Enable CodeCoverage. - required: false - CodeCoverage_OutputFormat: - description: | - Format to use for code coverage report. Possible values: JaCoCo, CoverageGutters, Cobertura - required: false - CodeCoverage_OutputPath: - description: | - Path relative to the current directory where code coverage report is saved. - required: false - CodeCoverage_OutputEncoding: - description: | - Encoding of the output file. - required: false - CodeCoverage_Path: - description: | - Directories or files to be used for code coverage, by default the Path(s) from general settings are used, unless overridden here. - required: false - CodeCoverage_ExcludeTests: - description: | - Exclude tests from code coverage. This uses the TestFilter from general configuration. - required: false - CodeCoverage_RecursePaths: - description: | - Will recurse through directories in the Path option. - required: false - CodeCoverage_CoveragePercentTarget: - description: | - Target percent of code coverage that you want to achieve. - required: false - CodeCoverage_UseBreakpoints: - description: | - EXPERIMENTAL: When false, use Profiler based tracer to do CodeCoverage instead of using breakpoints. - required: false - CodeCoverage_SingleHitBreakpoints: - description: | - Remove breakpoint when it is hit. - required: false - TestResult_Enabled: - description: | - Enable TestResult. - required: false - TestResult_OutputFormat: - description: | - Format to use for test result report. Possible values: NUnitXml, NUnit2.5, NUnit3 or JUnitXml - required: false - TestResult_OutputPath: - description: | - Path relative to the current directory where test result report is saved. - required: false - TestResult_OutputEncoding: - description: | - Encoding of the output file. - required: false - TestResult_TestSuiteName: - description: | - Set the name assigned to the root 'test-suite' element. - required: false - Should_ErrorAction: - description: | - Controls if Should throws on error. Use 'Stop' to throw on error, or 'Continue' to fail at the end of the test. - required: false - Debug_ShowFullErrors: - description: | - Show full errors including Pester internal stack. This property is deprecated, and if set to true it will override Output.StackTraceVerbosity to 'Full'. - required: false - Debug_WriteDebugMessages: - description: | - Write Debug messages to screen. - required: false - Debug_WriteDebugMessagesFrom: - description: | - Write Debug messages from a given source, WriteDebugMessages must be set to true for this to work. - You can use like wildcards to get messages from multiple sources, as well as * to get everything. - required: false - Debug_ShowNavigationMarkers: - description: | - Write paths after every block and test, for easy navigation in VSCode. - required: false - Debug_ReturnRawResultObject: - description: | - Returns unfiltered result object, this is for development only. Do not rely on this object for additional properties, - non-public properties will be renamed without previous notice. - required: false - Output_Verbosity: - description: | - The verbosity of output, options are None, Normal, Detailed and Diagnostic. - required: false - Output_StackTraceVerbosity: - description: | - The verbosity of stacktrace output, options are None, FirstLine, Filtered and Full. - required: false - Output_CIFormat: - description: | - The CI format of error output in build logs, options are None, Auto, AzureDevops and GithubActions. - required: false - Output_CILogLevel: - description: | - The CI log level in build logs, options are Error and Warning. - required: false - Output_RenderMode: - description: | - The mode used to render console output, options are Auto, Ansi, ConsoleColor and Plaintext. - required: false - TestDrive_Enabled: - description: | - Enable TestDrive. - required: false - TestRegistry_Enabled: - description: | - Enable TestRegistry. - required: false - ConfigurationFilePath: - description: | - Path to the configuration file. - required: false - default: '${{ github.workspace }}/.github/pester.settings.ps1' - Debug: - description: | - Enable debug mode. - required: false - default: 'false' -outputs: - Containers: - description: Containers object used during the test. - value: ${{ fromJSON(steps.test.outputs.result).Containers }} - Result: - description: If the tests passed. - value: ${{ fromJSON(steps.test.outputs.result).Result }} - FailedCount: - description: Number of failed tests. - value: ${{ fromJSON(steps.test.outputs.result).FailedCount }} - FailedBlocksCount: - description: Number of failed blocks. - value: ${{ fromJSON(steps.test.outputs.result).FailedBlocksCount }} - FailedContainersCount: - description: Number of failed containers. - value: ${{ fromJSON(steps.test.outputs.result).FailedContainersCount }} - PassedCount: - description: Number of passed tests. - value: ${{ fromJSON(steps.test.outputs.result).PassedCount }} - SkippedCount: - description: Number of skipped tests. - value: ${{ fromJSON(steps.test.outputs.result).SkippedCount }} - InconclusiveCount: - description: Number of inconclusive tests. - value: ${{ fromJSON(steps.test.outputs.result).InconclusiveCount }} - NotRunCount: - description: Number of tests that were not run. - value: ${{ fromJSON(steps.test.outputs.result).NotRunCount }} - TotalCount: - description: Total number of tests. - value: ${{ fromJSON(steps.test.outputs.result).TotalCount }} - Duration: - description: Duration of the test run. - value: ${{ fromJSON(steps.test.outputs.result).Duration }} - Executed: - description: Number of tests executed. - value: ${{ fromJSON(steps.test.outputs.result).Executed }} - ExecutedAt: - description: Time when the tests were executed. - value: ${{ fromJSON(steps.test.outputs.result).ExecutedAt }} - Version: - description: Version of Pester used. - value: ${{ fromJSON(steps.test.outputs.result).Version }} - PSVersion: - description: Version of PowerShell used. - value: ${{ fromJSON(steps.test.outputs.result).PSVersion }} - PSBoundParameters: - description: Parameters used to run the tests. - value: ${{ fromJSON(steps.test.outputs.result).PSBoundParameters }} - Plugins: - description: Plugins used during the test run. - value: ${{ fromJSON(steps.test.outputs.result).Plugins }} - PluginConfiguration: - description: Configuration of the plugins. - value: ${{ fromJSON(steps.test.outputs.result).PluginConfiguration }} - PluginData: - description: Data of the plugins. - value: ${{ fromJSON(steps.test.outputs.result).PluginData }} - Configuration: - description: Configuration used during the test run. - value: ${{ fromJSON(steps.test.outputs.result).Configuration }} - DiscoveryDuration: - description: Duration of the discovery phase. - value: ${{ fromJSON(steps.test.outputs.result).DiscoveryDuration }} - UserDuration: - description: Duration of the user code execution. - value: ${{ fromJSON(steps.test.outputs.result).UserDuration }} - FrameworkDuration: - description: Duration of the framework code execution. - value: ${{ fromJSON(steps.test.outputs.result).FrameworkDuration }} - Failed: - description: Failed tests. - value: ${{ fromJSON(steps.test.outputs.result).Failed }} - FailedBlocks: - description: Failed blocks. - value: ${{ fromJSON(steps.test.outputs.result).FailedBlocks }} - FailedContainers: - description: Failed containers. - value: ${{ fromJSON(steps.test.outputs.result).FailedContainers }} - Passed: - description: Passed tests. - value: ${{ fromJSON(steps.test.outputs.result).Passed }} - Skipped: - description: Skipped tests. - value: ${{ fromJSON(steps.test.outputs.result).Skipped }} - Inconclusive: - description: Inconclusive tests. - value: ${{ fromJSON(steps.test.outputs.result).Inconclusive }} - NotRun: - description: Tests that were not run. - value: ${{ fromJSON(steps.test.outputs.result).NotRun }} - Tests: - description: All tests. - value: ${{ fromJSON(steps.test.outputs.result).Tests }} - CodeCoverage: - description: Code coverage report. - value: ${{ fromJSON(steps.test.outputs.result).CodeCoverage }} - -runs: - using: composite - steps: - - uses: PSModule/Debug@v0 - if: ${{ inputs.Debug == 'true' }} - - - name: Invoke-Pester - uses: PSModule/GitHub-Script@v1 - id: test - continue-on-error: true - env: - GITHUB_ACTION_INPUT_Run_Path: ${{ inputs.Run_Path }} - GITHUB_ACTION_INPUT_Run_ExcludePath: ${{ inputs.Run_ExcludePath }} - GITHUB_ACTION_INPUT_Run_ScriptBlock: ${{ inputs.Run_ScriptBlock }} - GITHUB_ACTION_INPUT_Run_Container: ${{ inputs.Run_Container }} - GITHUB_ACTION_INPUT_Run_TestExtension: ${{ inputs.Run_TestExtension }} - GITHUB_ACTION_INPUT_Run_Exit: ${{ inputs.Run_Exit }} - GITHUB_ACTION_INPUT_Run_Throw: ${{ inputs.Run_Throw }} - GITHUB_ACTION_INPUT_Run_PassThru: ${{ inputs.Run_PassThru }} - GITHUB_ACTION_INPUT_Run_SkipRun: ${{ inputs.Run_SkipRun }} - GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure: ${{ inputs.Run_SkipRemainingOnFailure }} - GITHUB_ACTION_INPUT_Filter_Tag: ${{ inputs.Filter_Tag }} - GITHUB_ACTION_INPUT_Filter_ExcludeTag: ${{ inputs.Filter_ExcludeTag }} - GITHUB_ACTION_INPUT_Filter_Line: ${{ inputs.Filter_Line }} - GITHUB_ACTION_INPUT_Filter_ExcludeLine: ${{ inputs.Filter_ExcludeLine }} - GITHUB_ACTION_INPUT_Filter_FullName: ${{ inputs.Filter_FullName }} - GITHUB_ACTION_INPUT_CodeCoverage_Enabled: ${{ inputs.CodeCoverage_Enabled }} - GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat: ${{ inputs.CodeCoverage_OutputFormat }} - GITHUB_ACTION_INPUT_CodeCoverage_OutputPath: ${{ inputs.CodeCoverage_OutputPath }} - GITHUB_ACTION_INPUT_CodeCoverage_OutputEncoding: ${{ inputs.CodeCoverage_OutputEncoding }} - GITHUB_ACTION_INPUT_CodeCoverage_Path: ${{ inputs.CodeCoverage_Path }} - GITHUB_ACTION_INPUT_CodeCoverage_ExcludeTests: ${{ inputs.CodeCoverage_ExcludeTests }} - GITHUB_ACTION_INPUT_CodeCoverage_RecursePaths: ${{ inputs.CodeCoverage_RecursePaths }} - GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget: ${{ inputs.CodeCoverage_CoveragePercentTarget }} - GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints: ${{ inputs.CodeCoverage_UseBreakpoints }} - GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints: ${{ inputs.CodeCoverage_SingleHitBreakpoints }} - GITHUB_ACTION_INPUT_TestResult_Enabled: ${{ inputs.TestResult_Enabled }} - GITHUB_ACTION_INPUT_TestResult_OutputFormat: ${{ inputs.TestResult_OutputFormat }} - GITHUB_ACTION_INPUT_TestResult_OutputPath: ${{ inputs.TestResult_OutputPath }} - GITHUB_ACTION_INPUT_TestResult_OutputEncoding: ${{ inputs.TestResult_OutputEncoding }} - GITHUB_ACTION_INPUT_TestResult_TestSuiteName: ${{ inputs.TestResult_TestSuiteName }} - GITHUB_ACTION_INPUT_Should_ErrorAction: ${{ inputs.Should_ErrorAction }} - GITHUB_ACTION_INPUT_Debug_ShowFullErrors: ${{ inputs.Debug_ShowFullErrors }} - GITHUB_ACTION_INPUT_Debug_WriteDebugMessages: ${{ inputs.Debug_WriteDebugMessages }} - GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom: ${{ inputs.Debug_WriteDebugMessagesFrom }} - GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers: ${{ inputs.Debug_ShowNavigationMarkers }} - GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject: ${{ inputs.Debug_ReturnRawResultObject }} - GITHUB_ACTION_INPUT_Output_Verbosity: ${{ inputs.Output_Verbosity }} - GITHUB_ACTION_INPUT_Output_StackTraceVerbosity: ${{ inputs.Output_StackTraceVerbosity }} - GITHUB_ACTION_INPUT_Output_CIFormat: ${{ inputs.Output_CIFormat }} - GITHUB_ACTION_INPUT_Output_CILogLevel: ${{ inputs.Output_CILogLevel }} - GITHUB_ACTION_INPUT_Output_RenderMode: ${{ inputs.Output_RenderMode }} - GITHUB_ACTION_INPUT_TestDrive_Enabled: ${{ inputs.TestDrive_Enabled }} - GITHUB_ACTION_INPUT_TestRegistry_Enabled: ${{ inputs.TestRegistry_Enabled }} - GITHUB_ACTION_INPUT_ConfigurationFilePath: ${{ inputs.ConfigurationFilePath }} - with: - ShowOutput: true - Script: | - # Invoke-Pester - ${{ github.action_path }}\scripts\main.ps1 - - - name: Check outputs - shell: pwsh - env: - TestResultEnabled: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled }} - TestResultOutputPath: ${{ fromJSON(steps.test.outputs.result).TestResultOutputPath }} - TestSuiteName: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }} - CodeCoverageEnabled: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled }} - CodeCoverageOutputPath: ${{ fromJSON(steps.test.outputs.result).CodeCoverageOutputPath }} - run: | - Write-Host "TestResultEnabled : $env:TestResultEnabled" - Write-Host "TestResultOutputPath : $env:TestResultOutputPath" - Write-Host "TestSuiteName : $env:TestSuiteName" - Write-Host "CodeCoverageEnabled : $env:CodeCoverageEnabled" - Write-Host "CodeCoverageOutputPath : $env:CodeCoverageOutputPath" - - - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-TestResults] - uses: actions/upload-artifact@v4 - # if: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled == 'true' && (success() || failure()) }} - with: - name: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-TestResults - path: ${{ fromJSON(steps.test.outputs.result).TestResultOutputPath }} - - - name: Upload code coverage report - [${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-CodeCoverage] - uses: actions/upload-artifact@v4 - # if: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled == 'true' && (success() || failure()) }} - with: - name: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-CodeCoverage - path: ${{ fromJSON(steps.test.outputs.result).CodeCoverageOutputPath }} +name: Invoke-Pester +description: Runs test, using Pester and PowerShell. +author: PSModule +branding: + icon: check-square + color: gray-dark + +inputs: + Run_Path: + description: | + Directories to be searched for tests, paths directly to test files, or combination of both. + required: false + Run_ExcludePath: + description: | + Directories or files to be excluded from the run. + required: false + Run_ScriptBlock: + description: | + ScriptBlocks containing tests to be executed. + required: false + Run_Container: + description: | + ContainerInfo objects containing tests to be executed. + required: false + Run_TestExtension: + description: | + Filter used to identify test files. + required: false + Run_Exit: + description: | + Exit with non-zero exit code when the test run fails. Exit code is always set to `$LASTEXITCODE` even when this option is `$false`. + When used together with Throw, throwing an exception is preferred. + required: false + Run_Throw: + description: | + Throw an exception when test run fails. When used together with Exit, throwing an exception is preferred. + required: false + Run_PassThru: + description: | + Return result object to the pipeline after finishing the test run. + required: false + Run_SkipRun: + description: | + Runs the discovery phase but skips run. Use it with PassThru to get object populated with all tests. + required: false + Run_SkipRemainingOnFailure: + description: | + Skips remaining tests after failure for selected scope, options are None, Run, Container and Block. + required: false + Filter_Tag: + description: | + Tags of Describe, Context or It to be run. + required: false + Filter_ExcludeTag: + description: | + Tags of Describe, Context or It to be excluded from the run. + required: false + Filter_Line: + description: | + Filter by file and scriptblock start line, useful to run parsed tests programmatically to avoid problems with expanded names. + Example: 'C:\tests\file1.Tests.ps1:37' + required: false + Filter_ExcludeLine: + description: | + Exclude by file and scriptblock start line, takes precedence over Line. + required: false + Filter_FullName: + description: | + Full name of test with -like wildcards, joined by dot. Example: '*.describe Get-Item.test1' + required: false + CodeCoverage_Enabled: + description: | + Enable CodeCoverage. + required: false + CodeCoverage_OutputFormat: + description: | + Format to use for code coverage report. Possible values: JaCoCo, CoverageGutters, Cobertura + required: false + CodeCoverage_OutputPath: + description: | + Path relative to the current directory where code coverage report is saved. + required: false + CodeCoverage_OutputEncoding: + description: | + Encoding of the output file. + required: false + CodeCoverage_Path: + description: | + Directories or files to be used for code coverage, by default the Path(s) from general settings are used, unless overridden here. + required: false + CodeCoverage_ExcludeTests: + description: | + Exclude tests from code coverage. This uses the TestFilter from general configuration. + required: false + CodeCoverage_RecursePaths: + description: | + Will recurse through directories in the Path option. + required: false + CodeCoverage_CoveragePercentTarget: + description: | + Target percent of code coverage that you want to achieve. + required: false + CodeCoverage_UseBreakpoints: + description: | + EXPERIMENTAL: When false, use Profiler based tracer to do CodeCoverage instead of using breakpoints. + required: false + CodeCoverage_SingleHitBreakpoints: + description: | + Remove breakpoint when it is hit. + required: false + TestResult_Enabled: + description: | + Enable TestResult. + required: false + TestResult_OutputFormat: + description: | + Format to use for test result report. Possible values: NUnitXml, NUnit2.5, NUnit3 or JUnitXml + required: false + TestResult_OutputPath: + description: | + Path relative to the current directory where test result report is saved. + required: false + TestResult_OutputEncoding: + description: | + Encoding of the output file. + required: false + TestResult_TestSuiteName: + description: | + Set the name assigned to the root 'test-suite' element. + required: false + Should_ErrorAction: + description: | + Controls if Should throws on error. Use 'Stop' to throw on error, or 'Continue' to fail at the end of the test. + required: false + Debug_ShowFullErrors: + description: | + Show full errors including Pester internal stack. This property is deprecated, and if set to true it will override Output.StackTraceVerbosity to 'Full'. + required: false + Debug_WriteDebugMessages: + description: | + Write Debug messages to screen. + required: false + Debug_WriteDebugMessagesFrom: + description: | + Write Debug messages from a given source, WriteDebugMessages must be set to true for this to work. + You can use like wildcards to get messages from multiple sources, as well as * to get everything. + required: false + Debug_ShowNavigationMarkers: + description: | + Write paths after every block and test, for easy navigation in VSCode. + required: false + Debug_ReturnRawResultObject: + description: | + Returns unfiltered result object, this is for development only. Do not rely on this object for additional properties, + non-public properties will be renamed without previous notice. + required: false + Output_Verbosity: + description: | + The verbosity of output, options are None, Normal, Detailed and Diagnostic. + required: false + Output_StackTraceVerbosity: + description: | + The verbosity of stacktrace output, options are None, FirstLine, Filtered and Full. + required: false + Output_CIFormat: + description: | + The CI format of error output in build logs, options are None, Auto, AzureDevops and GithubActions. + required: false + Output_CILogLevel: + description: | + The CI log level in build logs, options are Error and Warning. + required: false + Output_RenderMode: + description: | + The mode used to render console output, options are Auto, Ansi, ConsoleColor and Plaintext. + required: false + TestDrive_Enabled: + description: | + Enable TestDrive. + required: false + TestRegistry_Enabled: + description: | + Enable TestRegistry. + required: false + ConfigurationFilePath: + description: | + Path to the configuration file. + required: false + default: '${{ github.workspace }}/.github/pester.settings.ps1' + Debug: + description: | + Enable debug mode. + required: false + default: 'false' +outputs: + Containers: + description: Containers object used during the test. + value: ${{ fromJSON(steps.test.outputs.result).Containers }} + Result: + description: If the tests passed. + value: ${{ fromJSON(steps.test.outputs.result).Result }} + FailedCount: + description: Number of failed tests. + value: ${{ fromJSON(steps.test.outputs.result).FailedCount }} + FailedBlocksCount: + description: Number of failed blocks. + value: ${{ fromJSON(steps.test.outputs.result).FailedBlocksCount }} + FailedContainersCount: + description: Number of failed containers. + value: ${{ fromJSON(steps.test.outputs.result).FailedContainersCount }} + PassedCount: + description: Number of passed tests. + value: ${{ fromJSON(steps.test.outputs.result).PassedCount }} + SkippedCount: + description: Number of skipped tests. + value: ${{ fromJSON(steps.test.outputs.result).SkippedCount }} + InconclusiveCount: + description: Number of inconclusive tests. + value: ${{ fromJSON(steps.test.outputs.result).InconclusiveCount }} + NotRunCount: + description: Number of tests that were not run. + value: ${{ fromJSON(steps.test.outputs.result).NotRunCount }} + TotalCount: + description: Total number of tests. + value: ${{ fromJSON(steps.test.outputs.result).TotalCount }} + Duration: + description: Duration of the test run. + value: ${{ fromJSON(steps.test.outputs.result).Duration }} + Executed: + description: Number of tests executed. + value: ${{ fromJSON(steps.test.outputs.result).Executed }} + ExecutedAt: + description: Time when the tests were executed. + value: ${{ fromJSON(steps.test.outputs.result).ExecutedAt }} + Version: + description: Version of Pester used. + value: ${{ fromJSON(steps.test.outputs.result).Version }} + PSVersion: + description: Version of PowerShell used. + value: ${{ fromJSON(steps.test.outputs.result).PSVersion }} + PSBoundParameters: + description: Parameters used to run the tests. + value: ${{ fromJSON(steps.test.outputs.result).PSBoundParameters }} + Plugins: + description: Plugins used during the test run. + value: ${{ fromJSON(steps.test.outputs.result).Plugins }} + PluginConfiguration: + description: Configuration of the plugins. + value: ${{ fromJSON(steps.test.outputs.result).PluginConfiguration }} + PluginData: + description: Data of the plugins. + value: ${{ fromJSON(steps.test.outputs.result).PluginData }} + Configuration: + description: Configuration used during the test run. + value: ${{ fromJSON(steps.test.outputs.result).Configuration }} + DiscoveryDuration: + description: Duration of the discovery phase. + value: ${{ fromJSON(steps.test.outputs.result).DiscoveryDuration }} + UserDuration: + description: Duration of the user code execution. + value: ${{ fromJSON(steps.test.outputs.result).UserDuration }} + FrameworkDuration: + description: Duration of the framework code execution. + value: ${{ fromJSON(steps.test.outputs.result).FrameworkDuration }} + Failed: + description: Failed tests. + value: ${{ fromJSON(steps.test.outputs.result).Failed }} + FailedBlocks: + description: Failed blocks. + value: ${{ fromJSON(steps.test.outputs.result).FailedBlocks }} + FailedContainers: + description: Failed containers. + value: ${{ fromJSON(steps.test.outputs.result).FailedContainers }} + Passed: + description: Passed tests. + value: ${{ fromJSON(steps.test.outputs.result).Passed }} + Skipped: + description: Skipped tests. + value: ${{ fromJSON(steps.test.outputs.result).Skipped }} + Inconclusive: + description: Inconclusive tests. + value: ${{ fromJSON(steps.test.outputs.result).Inconclusive }} + NotRun: + description: Tests that were not run. + value: ${{ fromJSON(steps.test.outputs.result).NotRun }} + Tests: + description: All tests. + value: ${{ fromJSON(steps.test.outputs.result).Tests }} + CodeCoverage: + description: Code coverage report. + value: ${{ fromJSON(steps.test.outputs.result).CodeCoverage }} + +runs: + using: composite + steps: + - uses: PSModule/Debug@v0 + if: ${{ inputs.Debug == 'true' }} + + - name: Invoke-Pester + uses: PSModule/GitHub-Script@v1 + id: test + continue-on-error: true + env: + GITHUB_ACTION_INPUT_Run_Path: ${{ inputs.Run_Path }} + GITHUB_ACTION_INPUT_Run_ExcludePath: ${{ inputs.Run_ExcludePath }} + GITHUB_ACTION_INPUT_Run_ScriptBlock: ${{ inputs.Run_ScriptBlock }} + GITHUB_ACTION_INPUT_Run_Container: ${{ inputs.Run_Container }} + GITHUB_ACTION_INPUT_Run_TestExtension: ${{ inputs.Run_TestExtension }} + GITHUB_ACTION_INPUT_Run_Exit: ${{ inputs.Run_Exit }} + GITHUB_ACTION_INPUT_Run_Throw: ${{ inputs.Run_Throw }} + GITHUB_ACTION_INPUT_Run_PassThru: ${{ inputs.Run_PassThru }} + GITHUB_ACTION_INPUT_Run_SkipRun: ${{ inputs.Run_SkipRun }} + GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure: ${{ inputs.Run_SkipRemainingOnFailure }} + GITHUB_ACTION_INPUT_Filter_Tag: ${{ inputs.Filter_Tag }} + GITHUB_ACTION_INPUT_Filter_ExcludeTag: ${{ inputs.Filter_ExcludeTag }} + GITHUB_ACTION_INPUT_Filter_Line: ${{ inputs.Filter_Line }} + GITHUB_ACTION_INPUT_Filter_ExcludeLine: ${{ inputs.Filter_ExcludeLine }} + GITHUB_ACTION_INPUT_Filter_FullName: ${{ inputs.Filter_FullName }} + GITHUB_ACTION_INPUT_CodeCoverage_Enabled: ${{ inputs.CodeCoverage_Enabled }} + GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat: ${{ inputs.CodeCoverage_OutputFormat }} + GITHUB_ACTION_INPUT_CodeCoverage_OutputPath: ${{ inputs.CodeCoverage_OutputPath }} + GITHUB_ACTION_INPUT_CodeCoverage_OutputEncoding: ${{ inputs.CodeCoverage_OutputEncoding }} + GITHUB_ACTION_INPUT_CodeCoverage_Path: ${{ inputs.CodeCoverage_Path }} + GITHUB_ACTION_INPUT_CodeCoverage_ExcludeTests: ${{ inputs.CodeCoverage_ExcludeTests }} + GITHUB_ACTION_INPUT_CodeCoverage_RecursePaths: ${{ inputs.CodeCoverage_RecursePaths }} + GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget: ${{ inputs.CodeCoverage_CoveragePercentTarget }} + GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints: ${{ inputs.CodeCoverage_UseBreakpoints }} + GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints: ${{ inputs.CodeCoverage_SingleHitBreakpoints }} + GITHUB_ACTION_INPUT_TestResult_Enabled: ${{ inputs.TestResult_Enabled }} + GITHUB_ACTION_INPUT_TestResult_OutputFormat: ${{ inputs.TestResult_OutputFormat }} + GITHUB_ACTION_INPUT_TestResult_OutputPath: ${{ inputs.TestResult_OutputPath }} + GITHUB_ACTION_INPUT_TestResult_OutputEncoding: ${{ inputs.TestResult_OutputEncoding }} + GITHUB_ACTION_INPUT_TestResult_TestSuiteName: ${{ inputs.TestResult_TestSuiteName }} + GITHUB_ACTION_INPUT_Should_ErrorAction: ${{ inputs.Should_ErrorAction }} + GITHUB_ACTION_INPUT_Debug_ShowFullErrors: ${{ inputs.Debug_ShowFullErrors }} + GITHUB_ACTION_INPUT_Debug_WriteDebugMessages: ${{ inputs.Debug_WriteDebugMessages }} + GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom: ${{ inputs.Debug_WriteDebugMessagesFrom }} + GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers: ${{ inputs.Debug_ShowNavigationMarkers }} + GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject: ${{ inputs.Debug_ReturnRawResultObject }} + GITHUB_ACTION_INPUT_Output_Verbosity: ${{ inputs.Output_Verbosity }} + GITHUB_ACTION_INPUT_Output_StackTraceVerbosity: ${{ inputs.Output_StackTraceVerbosity }} + GITHUB_ACTION_INPUT_Output_CIFormat: ${{ inputs.Output_CIFormat }} + GITHUB_ACTION_INPUT_Output_CILogLevel: ${{ inputs.Output_CILogLevel }} + GITHUB_ACTION_INPUT_Output_RenderMode: ${{ inputs.Output_RenderMode }} + GITHUB_ACTION_INPUT_TestDrive_Enabled: ${{ inputs.TestDrive_Enabled }} + GITHUB_ACTION_INPUT_TestRegistry_Enabled: ${{ inputs.TestRegistry_Enabled }} + GITHUB_ACTION_INPUT_ConfigurationFilePath: ${{ inputs.ConfigurationFilePath }} + with: + ShowOutput: true + Script: | + # Invoke-Pester + ${{ github.action_path }}\scripts\main.ps1 + + - name: Check outputs + shell: pwsh + env: + TestResultEnabled: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled }} + TestResultOutputPath: ${{ fromJSON(steps.test.outputs.result).TestResultOutputPath }} + TestSuiteName: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }} + CodeCoverageEnabled: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled }} + CodeCoverageOutputPath: ${{ fromJSON(steps.test.outputs.result).CodeCoverageOutputPath }} + run: | + Write-Host "TestResultEnabled : $env:TestResultEnabled" + Write-Host "TestResultOutputPath : $env:TestResultOutputPath" + Write-Host "TestSuiteName : $env:TestSuiteName" + Write-Host "CodeCoverageEnabled : $env:CodeCoverageEnabled" + Write-Host "CodeCoverageOutputPath : $env:CodeCoverageOutputPath" + + - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-TestResults] + uses: actions/upload-artifact@v4 + # if: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled == 'true' && (success() || failure()) }} + with: + name: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-TestResults + path: ${{ fromJSON(steps.test.outputs.result).TestResultOutputPath }} + + - name: Upload code coverage report - [${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-CodeCoverage] + uses: actions/upload-artifact@v4 + # if: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled == 'true' && (success() || failure()) }} + with: + name: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-CodeCoverage + path: ${{ fromJSON(steps.test.outputs.result).CodeCoverageOutputPath }} From 6e5e9d81afa40172c39d3fd534d0c6c675bb6a1d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 22:04:22 +0100 Subject: [PATCH 168/176] Refactor action.yml to improve condition checks for uploading test results and code coverage reports --- action.yml | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/action.yml b/action.yml index fae9af01..124550b0 100644 --- a/action.yml +++ b/action.yml @@ -351,31 +351,16 @@ runs: # Invoke-Pester ${{ github.action_path }}\scripts\main.ps1 - - name: Check outputs - shell: pwsh - env: - TestResultEnabled: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled }} - TestResultOutputPath: ${{ fromJSON(steps.test.outputs.result).TestResultOutputPath }} - TestSuiteName: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }} - CodeCoverageEnabled: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled }} - CodeCoverageOutputPath: ${{ fromJSON(steps.test.outputs.result).CodeCoverageOutputPath }} - run: | - Write-Host "TestResultEnabled : $env:TestResultEnabled" - Write-Host "TestResultOutputPath : $env:TestResultOutputPath" - Write-Host "TestSuiteName : $env:TestSuiteName" - Write-Host "CodeCoverageEnabled : $env:CodeCoverageEnabled" - Write-Host "CodeCoverageOutputPath : $env:CodeCoverageOutputPath" - - name: Upload test results - [${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-TestResults] uses: actions/upload-artifact@v4 - # if: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled == 'true' && (success() || failure()) }} + if: ${{ fromJSON(steps.test.outputs.result).TestResultEnabled && (success() || failure()) }} with: name: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-TestResults path: ${{ fromJSON(steps.test.outputs.result).TestResultOutputPath }} - name: Upload code coverage report - [${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-CodeCoverage] uses: actions/upload-artifact@v4 - # if: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled == 'true' && (success() || failure()) }} + if: ${{ fromJSON(steps.test.outputs.result).CodeCoverageEnabled && (success() || failure()) }} with: name: ${{ fromJSON(steps.test.outputs.result).TestSuiteName }}-CodeCoverage path: ${{ fromJSON(steps.test.outputs.result).CodeCoverageOutputPath }} From af80636562940c5c2e558f3560973c1abbe41c2e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 22:17:20 +0100 Subject: [PATCH 169/176] Update test configurations to specify test suite names and comment out output paths --- scripts/Pester.Configuration.ps1 | 4 +- scripts/main.ps1 | 744 +++++++++++----------- tests/2-Standard/Emoji.Configuration.ps1 | 12 +- tests/3-Advanced/Pester.Configuration.ps1 | 3 +- 4 files changed, 381 insertions(+), 382 deletions(-) diff --git a/scripts/Pester.Configuration.ps1 b/scripts/Pester.Configuration.ps1 index e991d09a..facd6bfc 100644 --- a/scripts/Pester.Configuration.ps1 +++ b/scripts/Pester.Configuration.ps1 @@ -23,7 +23,7 @@ CodeCoverage = @{ Enabled = $true OutputFormat = 'JaCoCo' - OutputPath = 'test_reports/CodeCoverage-Report.xml' + # OutputPath = 'test_reports/-CodeCoverage-Report.xml' OutputEncoding = 'UTF8' Path = @() ExcludeTests = $true @@ -35,7 +35,7 @@ TestResult = @{ Enabled = $true OutputFormat = 'NUnitXml' - OutputPath = 'test_reports/TestResult-Report.xml' + # OutputPath = 'test_reports/-TestResult-Report.xml' OutputEncoding = 'UTF8' TestSuiteName = 'Unit tests' } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index e45e8663..f4b74ae9 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -1,370 +1,374 @@ - -[CmdletBinding()] -param() - -LogGroup 'Setup prerequisites' { - 'Pester', 'PSScriptAnalyzer' | ForEach-Object { - Install-PSResource -Name $_ -Verbose:$false -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery - Import-Module -Name $_ -Verbose:$false - } - Import-Module "$PSScriptRoot/Helpers.psm1" -} - -LogGroup 'Get test kit versions' { - $PSSAModule = Get-PSResource -Name PSScriptAnalyzer -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 - $pesterModule = Get-PSResource -Name Pester -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 - - [PSCustomObject]@{ - PowerShell = $PSVersionTable.PSVersion.ToString() - Pester = $pesterModule.Version - PSScriptAnalyzer = $PSSAModule.Version - } | Format-List -} - -LogGroup 'Load inputs' { - $inputs = @{ - Run_Path = $env:GITHUB_ACTION_INPUT_Run_Path - Run_ExcludePath = $env:GITHUB_ACTION_INPUT_Run_ExcludePath - Run_ScriptBlock = $env:GITHUB_ACTION_INPUT_Run_ScriptBlock - Run_Container = $env:GITHUB_ACTION_INPUT_Run_Container - Run_TestExtension = $env:GITHUB_ACTION_INPUT_Run_TestExtension - Run_Exit = $env:GITHUB_ACTION_INPUT_Run_Exit - Run_Throw = $env:GITHUB_ACTION_INPUT_Run_Throw - Run_PassThru = $env:GITHUB_ACTION_INPUT_Run_PassThru - Run_SkipRun = $env:GITHUB_ACTION_INPUT_Run_SkipRun - Run_SkipRemainingOnFailure = $env:GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure - - Filter_Tag = $env:GITHUB_ACTION_INPUT_Filter_Tag - Filter_ExcludeTag = $env:GITHUB_ACTION_INPUT_Filter_ExcludeTag - Filter_Line = $env:GITHUB_ACTION_INPUT_Filter_Line - Filter_ExcludeLine = $env:GITHUB_ACTION_INPUT_Filter_ExcludeLine - Filter_FullName = $env:GITHUB_ACTION_INPUT_Filter_FullName - - CodeCoverage_Enabled = $env:GITHUB_ACTION_INPUT_CodeCoverage_Enabled - CodeCoverage_OutputFormat = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat - CodeCoverage_OutputPath = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputPath - CodeCoverage_OutputEncoding = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputEncoding - CodeCoverage_Path = $env:GITHUB_ACTION_INPUT_CodeCoverage_Path - CodeCoverage_ExcludeTests = $env:GITHUB_ACTION_INPUT_CodeCoverage_ExcludeTests - CodeCoverage_RecursePaths = $env:GITHUB_ACTION_INPUT_CodeCoverage_RecursePaths - CodeCoverage_CoveragePercentTarget = $env:GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget - CodeCoverage_UseBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints - CodeCoverage_SingleHitBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints - - TestResult_Enabled = $env:GITHUB_ACTION_INPUT_TestResult_Enabled - TestResult_OutputFormat = $env:GITHUB_ACTION_INPUT_TestResult_OutputFormat - TestResult_OutputPath = $env:GITHUB_ACTION_INPUT_TestResult_OutputPath - TestResult_OutputEncoding = $env:GITHUB_ACTION_INPUT_TestResult_OutputEncoding - TestResult_TestSuiteName = $env:GITHUB_ACTION_INPUT_TestResult_TestSuiteName - - Should_ErrorAction = $env:GITHUB_ACTION_INPUT_Should_ErrorAction - - Debug_ShowFullErrors = $env:GITHUB_ACTION_INPUT_Debug_ShowFullErrors - Debug_WriteDebugMessages = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessages - Debug_WriteDebugMessagesFrom = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom - Debug_ShowNavigationMarkers = $env:GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers - Debug_ReturnRawResultObject = $env:GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject - - Output_Verbosity = $env:GITHUB_ACTION_INPUT_Output_Verbosity - Output_StackTraceVerbosity = $env:GITHUB_ACTION_INPUT_Output_StackTraceVerbosity - Output_CIFormat = $env:GITHUB_ACTION_INPUT_Output_CIFormat - Output_CILogLevel = $env:GITHUB_ACTION_INPUT_Output_CILogLevel - Output_RenderMode = $env:GITHUB_ACTION_INPUT_Output_RenderMode - - TestDrive_Enabled = $env:GITHUB_ACTION_INPUT_TestDrive_Enabled - TestRegistry_Enabled = $env:GITHUB_ACTION_INPUT_TestRegistry_Enabled - ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath - } - - [pscustomobject]($inputs.GetEnumerator() | Where-Object { -not [string]::IsNullOrEmpty($_.Value) }) | Format-List -} - -$customConfig = @{} -$customInputs = @{} - -LogGroup 'Load configuration - Defaults' { - $defaultConfigPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') - if (Test-Path -Path $defaultConfigPath) { - $tmpDefault = . $defaultConfigPath - } - $defaultConfig = @{ - Run = $tmpDefault.Run ?? @{} - Filter = $tmpDefault.Filter ?? @{} - CodeCoverage = $tmpDefault.CodeCoverage ?? @{} - TestResult = $tmpDefault.TestResult ?? @{} - Should = $tmpDefault.Should ?? @{} - Debug = $tmpDefault.Debug ?? @{} - Output = $tmpDefault.Output ?? @{} - TestDrive = $tmpDefault.TestDrive ?? @{} - TestRegistry = $tmpDefault.TestRegistry ?? @{} - } - Write-Output ($defaultConfig | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) -} - -LogGroup 'Load configuration - Custom settings file' { - $customConfigFilePath = $inputs.ConfigurationFilePath - Write-Output "Custom configuration file path: [$customConfigFilePath]" - if ($customConfigFilePath) { - $fileExists = Test-Path -Path $customConfigFilePath - Write-Output "File exists: [$fileExists]" - if ($fileExists) { - $tmpCustom = . $customConfigFilePath - } - } - $tmpCustomConfiguration = @{ - Run = $tmpCustom.Run ?? @{} - Filter = $tmpCustom.Filter ?? @{} - CodeCoverage = $tmpCustom.CodeCoverage ?? @{} - TestResult = $tmpCustom.TestResult ?? @{} - Should = $tmpCustom.Should ?? @{} - Debug = $tmpCustom.Debug ?? @{} - Output = $tmpCustom.Output ?? @{} - TestDrive = $tmpCustom.TestDrive ?? @{} - TestRegistry = $tmpCustom.TestRegistry ?? @{} - } - - foreach ($section in $tmpCustomConfiguration.Keys) { - $filteredProperties = @{} - foreach ($property in $tmpCustomConfiguration[$section].Keys) { - $value = $tmpCustomConfiguration[$section][$property] - if (-not [string]::IsNullOrEmpty($Value)) { - $filteredProperties[$property] = $Value - } - } - $customConfig[$section] = $filteredProperties - } - - Write-Output ($customConfig | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) -} - -LogGroup 'Load configuration - Action overrides' { - $customConfigInputMap = @{ - Run = @{ - Path = $inputs.Run_Path - ExcludePath = $inputs.Run_ExcludePath - ScriptBlock = $inputs.Run_ScriptBlock - Container = $inputs.Run_Container - TestExtension = $inputs.Run_TestExtension - Exit = $inputs.Run_Exit - Throw = $inputs.Run_Throw - PassThru = $inputs.Run_PassThru - SkipRun = $inputs.Run_SkipRun - SkipRemainingOnFailure = $inputs.Run_SkipRemainingOnFailure - } - Filter = @{ - Tag = $inputs.Filter_Tag - ExcludeTag = $inputs.Filter_ExcludeTag - Line = $inputs.Filter_Line - ExcludeLine = $inputs.Filter_ExcludeLine - FullName = $inputs.Filter_FullName - } - CodeCoverage = @{ - Enabled = $inputs.CodeCoverage_Enabled - OutputFormat = $inputs.CodeCoverage_OutputFormat - OutputPath = $inputs.CodeCoverage_OutputPath - OutputEncoding = $inputs.CodeCoverage_OutputEncoding - Path = $inputs.CodeCoverage_Path - ExcludeTests = $inputs.CodeCoverage_ExcludeTests - RecursePaths = $inputs.CodeCoverage_RecursePaths - CoveragePercentTarget = $inputs.CodeCoverage_CoveragePercentTarget - UseBreakpoints = $inputs.CodeCoverage_UseBreakpoints - SingleHitBreakpoints = $inputs.CodeCoverage_SingleHitBreakpoints - } - TestResult = @{ - Enabled = $inputs.TestResult_Enabled - OutputFormat = $inputs.TestResult_OutputFormat - OutputPath = $inputs.TestResult_OutputPath - OutputEncoding = $inputs.TestResult_OutputEncoding - TestSuiteName = $inputs.TestResult_TestSuiteName - } - Should = @{ - ErrorAction = $inputs.Should_ErrorAction - } - Debug = @{ - ShowFullErrors = $inputs.Debug_ShowFullErrors - WriteDebugMessages = $inputs.Debug_WriteDebugMessages - WriteDebugMessagesFrom = $inputs.Debug_WriteDebugMessagesFrom - ShowNavigationMarkers = $inputs.Debug_ShowNavigationMarkers - ReturnRawResultObject = $inputs.Debug_ReturnRawResultObject - } - Output = @{ - CIFormat = $inputs.Output_CIFormat - StackTraceVerbosity = $inputs.Output_StackTraceVerbosity - Verbosity = $inputs.Output_Verbosity - CILogLevel = $inputs.Output_CILogLevel - RenderMode = $inputs.Output_RenderMode - } - TestDrive = @{ - Enabled = $inputs.TestDrive_Enabled - } - TestRegistry = @{ - Enabled = $inputs.TestRegistry_Enabled - } - } - - foreach ($section in $customConfigInputMap.Keys) { - $filteredProperties = @{} - foreach ($property in $customConfigInputMap[$section].Keys) { - $value = $customConfigInputMap[$section][$property] - if (-not [string]::IsNullOrEmpty($Value)) { - $filteredProperties[$property] = $Value - } - } - $customInputs[$section] = $filteredProperties - } - - Write-Output ($customInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) -} - -LogGroup 'Load configuration - Add containers' { - $run = Merge-Hashtable -Main $defaultConfig.Run -Overrides $customConfig.Run, $customInputs.Run - $filter = Merge-Hashtable -Main $defaultConfig.Filter -Overrides $customConfig.Filter, $customInputs.Filter - $codeCoverage = Merge-Hashtable -Main $defaultConfig.CodeCoverage -Overrides $customConfig.CodeCoverage, $customInputs.CodeCoverage - $testResult = Merge-Hashtable -Main $defaultConfig.TestResult -Overrides $customConfig.TestResult, $customInputs.TestResult - $should = Merge-Hashtable -Main $defaultConfig.Should -Overrides $customConfig.Should, $customInputs.Should - $debug = Merge-Hashtable -Main $defaultConfig.Debug -Overrides $customConfig.Debug, $customInputs.Debug - $output = Merge-Hashtable -Main $defaultConfig.Output -Overrides $customConfig.Output, $customInputs.Output - $testDrive = Merge-Hashtable -Main $defaultConfig.TestDrive -Overrides $customConfig.TestDrive, $customInputs.TestDrive - $testRegistry = Merge-Hashtable -Main $defaultConfig.TestRegistry -Overrides $customConfig.TestRegistry, $customInputs.TestRegistry - - $configuration = @{ - Run = $run - Filter = $filter - CodeCoverage = $codeCoverage - TestResult = $testResult - Should = $should - Debug = $debug - Output = $output - TestDrive = $testDrive - TestRegistry = $testRegistry - } - - Write-Output "Containers from configuration: [$($configuration.Run.Container.Count)]" - Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) - - # Load configuration - Add containers - if ($configuration.Run.Container.Count -eq 0) { - # If no containers are specified, search for "*.Container.*" files in each Run.Path directory - foreach ($testDir in $configuration.Run.Path) { - if (Test-Path -LiteralPath $testDir -PathType Container) { - $configuration.Run.Container += Get-PesterContainer -Path $testDir - } - } - } - - # If any containers are defined as hashtables, convert them to PesterContainer objects - for ($i = 0; $i -lt $configuration.Run.Container.Count; $i++) { - $cntnr = $configuration.Run.Container[$i] - if ($cntnr -is [hashtable]) { - $configuration.Run.Container[$i] = New-PesterContainer @cntnr - } - } - - Write-Output "Added containers: [$($configuration.Run.Container.Count)]" - Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) -} - -LogGroup 'Load configuration - Result' { - Write-Output ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) -} - -$testResults = Invoke-Pester -Configuration $configuration - -LogGroup 'Test results' { - $testResults | Format-List - - $failedTests = [int]$testResults.FailedCount - - if (($failedTests -gt 0) -or ($testResults.Result -ne 'Passed')) { - Write-GitHubError "❌ Some [$failedTests] tests failed." - } - if ($failedTests -eq 0) { - Write-GitHubNotice '✅ All tests passed.' - } -} - -LogGroup 'Test results summary' { - - $nbsp = [char]0x00A0 - $indent = "$nbsp" * 4 - - $totalTests = $testResults.TotalCount - $passedTests = $testResults.PassedCount - $failedTests = $testResults.FailedCount - $skippedTests = $testResults.SkippedCount - $inconclusiveTests = $testResults.InconclusiveCount - $notRunTests = $testResults.NotRunCount - - $coverageString = 'N/A' - if ($configuration.CodeCoverage.Enabled) { - $coverage = [System.Math]::Round(($testResults.CodeCoverage.CoveragePercent), 2) - $coverageString = "$coverage%" - } - - $testSuitName = $($configuration.TestResult.TestSuiteName) - $testSuitStatusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } - $formattedTestDuration = $testResults.Duration | Format-TimeSpan - $summaryMarkdown = @" - -
$testSuitStatusIcon - $testSuitName ($formattedTestDuration) -

- -| Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | -| ----- | ------ | ------ | ------- | ------------ | ------ | -------- | -| $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | - -"@ - - Write-Verbose "Processing containers [$($testResults.Containers.Count)]" -Verbose - # For each container, group tests by their test path parts - foreach ($container in $testResults.Containers) { - $containerPath = $container.Item.FullName - Write-Verbose "Processing container [$containerPath]" -Verbose - $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' - Write-Verbose "Container name: [$containerName]" -Verbose - $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' - $formattedContainerDuration = $container.Duration | Format-TimeSpan - $summaryMarkdown += @" -

$Indent$containerStatusIcon - $containerName ($formattedContainerDuration) -

- -"@ - $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path - Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose - - # Build the nested details markdown grouping tests by their test path parts - $groupedMarkdown = Get-GroupedTestMarkdown -Tests $containerTests -Depth 0 - $summaryMarkdown += $groupedMarkdown - - $summaryMarkdown += @' - -

-
- -'@ - } - - $summaryMarkdown += @' - -

-
- -'@ - Set-GitHubStepSummary -Summary $summaryMarkdown -} - -# For each property of testresults, output the value as a JSON object -foreach ($property in $testResults.PSObject.Properties) { - Write-Verbose "Setting output for [$($property.Name)]" - $name = $property.Name - $value = -not [string]::IsNullOrEmpty($property.Value) ? ($property.Value | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) : '' - Set-GitHubOutput -Name $name -Value $value -} - -Set-GitHubOutput -Name 'TestResultEnabled' -Value $testResults.Configuration.TestResult.Enabled.Value -Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResults.Configuration.TestResult.OutputPath.Value -Set-GitHubOutput -Name 'TestSuiteName' -Value $testResults.Configuration.TestResult.TestSuiteName.Value -Set-GitHubOutput -Name 'CodeCoverageEnabled' -Value $testResults.Configuration.CodeCoverage.Enabled.Value -Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $testResults.Configuration.CodeCoverage.OutputPath.Value - -exit $failedTests + +[CmdletBinding()] +param() + +LogGroup 'Setup prerequisites' { + 'Pester', 'PSScriptAnalyzer' | ForEach-Object { + Install-PSResource -Name $_ -Verbose:$false -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery + Import-Module -Name $_ -Verbose:$false + } + Import-Module "$PSScriptRoot/Helpers.psm1" +} + +LogGroup 'Get test kit versions' { + $PSSAModule = Get-PSResource -Name PSScriptAnalyzer -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 + $pesterModule = Get-PSResource -Name Pester -Verbose:$false | Sort-Object Version -Descending | Select-Object -First 1 + + [PSCustomObject]@{ + PowerShell = $PSVersionTable.PSVersion.ToString() + Pester = $pesterModule.Version + PSScriptAnalyzer = $PSSAModule.Version + } | Format-List +} + +LogGroup 'Load inputs' { + $inputs = @{ + Run_Path = $env:GITHUB_ACTION_INPUT_Run_Path + Run_ExcludePath = $env:GITHUB_ACTION_INPUT_Run_ExcludePath + Run_ScriptBlock = $env:GITHUB_ACTION_INPUT_Run_ScriptBlock + Run_Container = $env:GITHUB_ACTION_INPUT_Run_Container + Run_TestExtension = $env:GITHUB_ACTION_INPUT_Run_TestExtension + Run_Exit = $env:GITHUB_ACTION_INPUT_Run_Exit + Run_Throw = $env:GITHUB_ACTION_INPUT_Run_Throw + Run_PassThru = $env:GITHUB_ACTION_INPUT_Run_PassThru + Run_SkipRun = $env:GITHUB_ACTION_INPUT_Run_SkipRun + Run_SkipRemainingOnFailure = $env:GITHUB_ACTION_INPUT_Run_SkipRemainingOnFailure + + Filter_Tag = $env:GITHUB_ACTION_INPUT_Filter_Tag + Filter_ExcludeTag = $env:GITHUB_ACTION_INPUT_Filter_ExcludeTag + Filter_Line = $env:GITHUB_ACTION_INPUT_Filter_Line + Filter_ExcludeLine = $env:GITHUB_ACTION_INPUT_Filter_ExcludeLine + Filter_FullName = $env:GITHUB_ACTION_INPUT_Filter_FullName + + CodeCoverage_Enabled = $env:GITHUB_ACTION_INPUT_CodeCoverage_Enabled + CodeCoverage_OutputFormat = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputFormat + CodeCoverage_OutputPath = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputPath + CodeCoverage_OutputEncoding = $env:GITHUB_ACTION_INPUT_CodeCoverage_OutputEncoding + CodeCoverage_Path = $env:GITHUB_ACTION_INPUT_CodeCoverage_Path + CodeCoverage_ExcludeTests = $env:GITHUB_ACTION_INPUT_CodeCoverage_ExcludeTests + CodeCoverage_RecursePaths = $env:GITHUB_ACTION_INPUT_CodeCoverage_RecursePaths + CodeCoverage_CoveragePercentTarget = $env:GITHUB_ACTION_INPUT_CodeCoverage_CoveragePercentTarget + CodeCoverage_UseBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_UseBreakpoints + CodeCoverage_SingleHitBreakpoints = $env:GITHUB_ACTION_INPUT_CodeCoverage_SingleHitBreakpoints + + TestResult_Enabled = $env:GITHUB_ACTION_INPUT_TestResult_Enabled + TestResult_OutputFormat = $env:GITHUB_ACTION_INPUT_TestResult_OutputFormat + TestResult_OutputPath = $env:GITHUB_ACTION_INPUT_TestResult_OutputPath + TestResult_OutputEncoding = $env:GITHUB_ACTION_INPUT_TestResult_OutputEncoding + TestResult_TestSuiteName = $env:GITHUB_ACTION_INPUT_TestResult_TestSuiteName + + Should_ErrorAction = $env:GITHUB_ACTION_INPUT_Should_ErrorAction + + Debug_ShowFullErrors = $env:GITHUB_ACTION_INPUT_Debug_ShowFullErrors + Debug_WriteDebugMessages = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessages + Debug_WriteDebugMessagesFrom = $env:GITHUB_ACTION_INPUT_Debug_WriteDebugMessagesFrom + Debug_ShowNavigationMarkers = $env:GITHUB_ACTION_INPUT_Debug_ShowNavigationMarkers + Debug_ReturnRawResultObject = $env:GITHUB_ACTION_INPUT_Debug_ReturnRawResultObject + + Output_Verbosity = $env:GITHUB_ACTION_INPUT_Output_Verbosity + Output_StackTraceVerbosity = $env:GITHUB_ACTION_INPUT_Output_StackTraceVerbosity + Output_CIFormat = $env:GITHUB_ACTION_INPUT_Output_CIFormat + Output_CILogLevel = $env:GITHUB_ACTION_INPUT_Output_CILogLevel + Output_RenderMode = $env:GITHUB_ACTION_INPUT_Output_RenderMode + + TestDrive_Enabled = $env:GITHUB_ACTION_INPUT_TestDrive_Enabled + TestRegistry_Enabled = $env:GITHUB_ACTION_INPUT_TestRegistry_Enabled + ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath + } + + [pscustomobject]($inputs.GetEnumerator() | Where-Object { -not [string]::IsNullOrEmpty($_.Value) }) | Format-List +} + +$customConfig = @{} +$customInputs = @{} + +LogGroup 'Load configuration - Defaults' { + $defaultConfigPath = (Join-Path $PSScriptRoot -ChildPath 'Pester.Configuration.ps1') + if (Test-Path -Path $defaultConfigPath) { + $tmpDefault = . $defaultConfigPath + } + $defaultConfig = @{ + Run = $tmpDefault.Run ?? @{} + Filter = $tmpDefault.Filter ?? @{} + CodeCoverage = $tmpDefault.CodeCoverage ?? @{} + TestResult = $tmpDefault.TestResult ?? @{} + Should = $tmpDefault.Should ?? @{} + Debug = $tmpDefault.Debug ?? @{} + Output = $tmpDefault.Output ?? @{} + TestDrive = $tmpDefault.TestDrive ?? @{} + TestRegistry = $tmpDefault.TestRegistry ?? @{} + } + Write-Output ($defaultConfig | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) +} + +LogGroup 'Load configuration - Custom settings file' { + $customConfigFilePath = $inputs.ConfigurationFilePath + Write-Output "Custom configuration file path: [$customConfigFilePath]" + if ($customConfigFilePath) { + $fileExists = Test-Path -Path $customConfigFilePath + Write-Output "File exists: [$fileExists]" + if ($fileExists) { + $tmpCustom = . $customConfigFilePath + } + } + $tmpCustomConfiguration = @{ + Run = $tmpCustom.Run ?? @{} + Filter = $tmpCustom.Filter ?? @{} + CodeCoverage = $tmpCustom.CodeCoverage ?? @{} + TestResult = $tmpCustom.TestResult ?? @{} + Should = $tmpCustom.Should ?? @{} + Debug = $tmpCustom.Debug ?? @{} + Output = $tmpCustom.Output ?? @{} + TestDrive = $tmpCustom.TestDrive ?? @{} + TestRegistry = $tmpCustom.TestRegistry ?? @{} + } + + foreach ($section in $tmpCustomConfiguration.Keys) { + $filteredProperties = @{} + foreach ($property in $tmpCustomConfiguration[$section].Keys) { + $value = $tmpCustomConfiguration[$section][$property] + if (-not [string]::IsNullOrEmpty($Value)) { + $filteredProperties[$property] = $Value + } + } + $customConfig[$section] = $filteredProperties + } + + Write-Output ($customConfig | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) +} + +LogGroup 'Load configuration - Action overrides' { + $customConfigInputMap = @{ + Run = @{ + Path = $inputs.Run_Path + ExcludePath = $inputs.Run_ExcludePath + ScriptBlock = $inputs.Run_ScriptBlock + Container = $inputs.Run_Container + TestExtension = $inputs.Run_TestExtension + Exit = $inputs.Run_Exit + Throw = $inputs.Run_Throw + PassThru = $inputs.Run_PassThru + SkipRun = $inputs.Run_SkipRun + SkipRemainingOnFailure = $inputs.Run_SkipRemainingOnFailure + } + Filter = @{ + Tag = $inputs.Filter_Tag + ExcludeTag = $inputs.Filter_ExcludeTag + Line = $inputs.Filter_Line + ExcludeLine = $inputs.Filter_ExcludeLine + FullName = $inputs.Filter_FullName + } + CodeCoverage = @{ + Enabled = $inputs.CodeCoverage_Enabled + OutputFormat = $inputs.CodeCoverage_OutputFormat + OutputPath = $inputs.CodeCoverage_OutputPath + OutputEncoding = $inputs.CodeCoverage_OutputEncoding + Path = $inputs.CodeCoverage_Path + ExcludeTests = $inputs.CodeCoverage_ExcludeTests + RecursePaths = $inputs.CodeCoverage_RecursePaths + CoveragePercentTarget = $inputs.CodeCoverage_CoveragePercentTarget + UseBreakpoints = $inputs.CodeCoverage_UseBreakpoints + SingleHitBreakpoints = $inputs.CodeCoverage_SingleHitBreakpoints + } + TestResult = @{ + Enabled = $inputs.TestResult_Enabled + OutputFormat = $inputs.TestResult_OutputFormat + OutputPath = $inputs.TestResult_OutputPath + OutputEncoding = $inputs.TestResult_OutputEncoding + TestSuiteName = $inputs.TestResult_TestSuiteName + } + Should = @{ + ErrorAction = $inputs.Should_ErrorAction + } + Debug = @{ + ShowFullErrors = $inputs.Debug_ShowFullErrors + WriteDebugMessages = $inputs.Debug_WriteDebugMessages + WriteDebugMessagesFrom = $inputs.Debug_WriteDebugMessagesFrom + ShowNavigationMarkers = $inputs.Debug_ShowNavigationMarkers + ReturnRawResultObject = $inputs.Debug_ReturnRawResultObject + } + Output = @{ + CIFormat = $inputs.Output_CIFormat + StackTraceVerbosity = $inputs.Output_StackTraceVerbosity + Verbosity = $inputs.Output_Verbosity + CILogLevel = $inputs.Output_CILogLevel + RenderMode = $inputs.Output_RenderMode + } + TestDrive = @{ + Enabled = $inputs.TestDrive_Enabled + } + TestRegistry = @{ + Enabled = $inputs.TestRegistry_Enabled + } + } + + foreach ($section in $customConfigInputMap.Keys) { + $filteredProperties = @{} + foreach ($property in $customConfigInputMap[$section].Keys) { + $value = $customConfigInputMap[$section][$property] + if (-not [string]::IsNullOrEmpty($Value)) { + $filteredProperties[$property] = $Value + } + } + $customInputs[$section] = $filteredProperties + } + + Write-Output ($customInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) +} + +LogGroup 'Load configuration - Add containers' { + $run = Merge-Hashtable -Main $defaultConfig.Run -Overrides $customConfig.Run, $customInputs.Run + $filter = Merge-Hashtable -Main $defaultConfig.Filter -Overrides $customConfig.Filter, $customInputs.Filter + $codeCoverage = Merge-Hashtable -Main $defaultConfig.CodeCoverage -Overrides $customConfig.CodeCoverage, $customInputs.CodeCoverage + $testResult = Merge-Hashtable -Main $defaultConfig.TestResult -Overrides $customConfig.TestResult, $customInputs.TestResult + $should = Merge-Hashtable -Main $defaultConfig.Should -Overrides $customConfig.Should, $customInputs.Should + $debug = Merge-Hashtable -Main $defaultConfig.Debug -Overrides $customConfig.Debug, $customInputs.Debug + $output = Merge-Hashtable -Main $defaultConfig.Output -Overrides $customConfig.Output, $customInputs.Output + $testDrive = Merge-Hashtable -Main $defaultConfig.TestDrive -Overrides $customConfig.TestDrive, $customInputs.TestDrive + $testRegistry = Merge-Hashtable -Main $defaultConfig.TestRegistry -Overrides $customConfig.TestRegistry, $customInputs.TestRegistry + + $configuration = @{ + Run = $run + Filter = $filter + CodeCoverage = $codeCoverage + TestResult = $testResult + Should = $should + Debug = $debug + Output = $output + TestDrive = $testDrive + TestRegistry = $testRegistry + } + + Write-Output "Containers from configuration: [$($configuration.Run.Container.Count)]" + Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) + + # Load configuration - Add containers + if ($configuration.Run.Container.Count -eq 0) { + # If no containers are specified, search for "*.Container.*" files in each Run.Path directory + foreach ($testDir in $configuration.Run.Path) { + if (Test-Path -LiteralPath $testDir -PathType Container) { + $configuration.Run.Container += Get-PesterContainer -Path $testDir + } + } + } + + # If any containers are defined as hashtables, convert them to PesterContainer objects + for ($i = 0; $i -lt $configuration.Run.Container.Count; $i++) { + $cntnr = $configuration.Run.Container[$i] + if ($cntnr -is [hashtable]) { + $configuration.Run.Container[$i] = New-PesterContainer @cntnr + } + } + + Write-Output "Added containers: [$($configuration.Run.Container.Count)]" + Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) +} + +LogGroup 'Load configuration - Result' { + $artifactName = $configuration.TestResult.TestSuiteName + $configuration.TestResult.OutputPath = "test_reports/$artifactName-TestResult-Report.xml" + $configuration.CodeCoverage.OutputPath = "test_reports/$artifactName-CodeCoverage-Report.xml" + + Write-Output ($configuration | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) +} + +$testResults = Invoke-Pester -Configuration $configuration + +LogGroup 'Test results' { + $testResults | Format-List + + $failedTests = [int]$testResults.FailedCount + + if (($failedTests -gt 0) -or ($testResults.Result -ne 'Passed')) { + Write-GitHubError "❌ Some [$failedTests] tests failed." + } + if ($failedTests -eq 0) { + Write-GitHubNotice '✅ All tests passed.' + } +} + +LogGroup 'Test results summary' { + + $nbsp = [char]0x00A0 + $indent = "$nbsp" * 4 + + $totalTests = $testResults.TotalCount + $passedTests = $testResults.PassedCount + $failedTests = $testResults.FailedCount + $skippedTests = $testResults.SkippedCount + $inconclusiveTests = $testResults.InconclusiveCount + $notRunTests = $testResults.NotRunCount + + $coverageString = 'N/A' + if ($configuration.CodeCoverage.Enabled) { + $coverage = [System.Math]::Round(($testResults.CodeCoverage.CoveragePercent), 2) + $coverageString = "$coverage%" + } + + $testSuitName = $($configuration.TestResult.TestSuiteName) + $testSuitStatusIcon = if ($failedTests -gt 0) { '❌' } else { '✅' } + $formattedTestDuration = $testResults.Duration | Format-TimeSpan + $summaryMarkdown = @" + +
$testSuitStatusIcon - $testSuitName ($formattedTestDuration) +

+ +| Total | Passed | Failed | Skipped | Inconclusive | NotRun | Coverage | +| ----- | ------ | ------ | ------- | ------------ | ------ | -------- | +| $($totalTests) | $($passedTests) | $($failedTests) | $($skippedTests) | $($inconclusiveTests) | $($notRunTests) | $coverageString | + +"@ + + Write-Verbose "Processing containers [$($testResults.Containers.Count)]" -Verbose + # For each container, group tests by their test path parts + foreach ($container in $testResults.Containers) { + $containerPath = $container.Item.FullName + Write-Verbose "Processing container [$containerPath]" -Verbose + $containerName = (Split-Path $container.Name -Leaf) -replace '.Tests.ps1' + Write-Verbose "Container name: [$containerName]" -Verbose + $containerStatusIcon = $container.Result -eq 'Passed' ? '✅' : '❌' + $formattedContainerDuration = $container.Duration | Format-TimeSpan + $summaryMarkdown += @" +

$Indent$containerStatusIcon - $containerName ($formattedContainerDuration) +

+ +"@ + $containerTests = $testResults.Tests | Where-Object { $_.Block.BlockContainer.Item.FullName -eq $containerPath } | Sort-Object -Property Path + Write-Verbose "Processing tests [$($containerTests.Count)]" -Verbose + + # Build the nested details markdown grouping tests by their test path parts + $groupedMarkdown = Get-GroupedTestMarkdown -Tests $containerTests -Depth 0 + $summaryMarkdown += $groupedMarkdown + + $summaryMarkdown += @' + +

+
+ +'@ + } + + $summaryMarkdown += @' + +

+
+ +'@ + Set-GitHubStepSummary -Summary $summaryMarkdown +} + +# For each property of testresults, output the value as a JSON object +foreach ($property in $testResults.PSObject.Properties) { + Write-Verbose "Setting output for [$($property.Name)]" + $name = $property.Name + $value = -not [string]::IsNullOrEmpty($property.Value) ? ($property.Value | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) : '' + Set-GitHubOutput -Name $name -Value $value +} + +Set-GitHubOutput -Name 'TestResultEnabled' -Value $testResults.Configuration.TestResult.Enabled.Value +Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResults.Configuration.TestResult.OutputPath.Value +Set-GitHubOutput -Name 'TestSuiteName' -Value $testResults.Configuration.TestResult.TestSuiteName.Value +Set-GitHubOutput -Name 'CodeCoverageEnabled' -Value $testResults.Configuration.CodeCoverage.Enabled.Value +Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $testResults.Configuration.CodeCoverage.OutputPath.Value + +exit $failedTests diff --git a/tests/2-Standard/Emoji.Configuration.ps1 b/tests/2-Standard/Emoji.Configuration.ps1 index fe7f2df2..d91b1e1b 100644 --- a/tests/2-Standard/Emoji.Configuration.ps1 +++ b/tests/2-Standard/Emoji.Configuration.ps1 @@ -1,17 +1,13 @@ @{ - Run = @{ + Run = @{ Path = $PSScriptRoot PassThru = $true } - TestResult = @{ + TestResult = @{ Enabled = $true - OutputPath = 'outputs\AnotherPath.xml' - TestSuiteName = 'Pester' + TestSuiteName = 'Standard' } - CodeCoverage = @{ - Path = 'Emoji.psm1' - } - Output = @{ + Output = @{ CIFormat = 'Auto' StackTraceVerbosity = 'Filtered' Verbosity = 'Detailed' diff --git a/tests/3-Advanced/Pester.Configuration.ps1 b/tests/3-Advanced/Pester.Configuration.ps1 index de1437cc..791150a6 100644 --- a/tests/3-Advanced/Pester.Configuration.ps1 +++ b/tests/3-Advanced/Pester.Configuration.ps1 @@ -7,8 +7,7 @@ } TestResult = @{ Enabled = $true - OutputPath = 'outputs\AnotherPath.xml' - TestSuiteName = 'Pester' + TestSuiteName = 'Advanced' } Output = @{ CIFormat = 'Auto' From 4082f123745fe59af6a5b98e9307ff4986617ee2 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 22:38:05 +0100 Subject: [PATCH 170/176] Refactor action inputs to unify path handling and improve configuration file loading --- .github/workflows/Action-Test.yml | 6 +++--- action.yml | 12 +++++------ scripts/Helpers.psm1 | 34 +++++++++++++++++++++++-------- scripts/main.ps1 | 13 +++--------- 4 files changed, 37 insertions(+), 28 deletions(-) diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml index 7a4ffa3d..3c834225 100644 --- a/.github/workflows/Action-Test.yml +++ b/.github/workflows/Action-Test.yml @@ -28,7 +28,7 @@ jobs: - name: Action-Test [1-Simple] uses: ./ with: - Run_Path: tests/1-Simple + Path: tests/1-Simple ActionTest2Standard: name: Action-Test - [2-Standard] @@ -41,7 +41,7 @@ jobs: - name: Action-Test [2-Standard] uses: ./ with: - Run_Path: tests/2-Standard + Path: tests/2-Standard ActionTestAdvanced: name: Action-Test - [3-Advanced] @@ -54,4 +54,4 @@ jobs: - name: Action-Test [3-Advanced] uses: ./ with: - ConfigurationFilePath: tests/3-Advanced/Pester.Configuration.ps1 + Path: tests/3-Advanced/Pester.Configuration.ps1 diff --git a/action.yml b/action.yml index 124550b0..7f4fd5ad 100644 --- a/action.yml +++ b/action.yml @@ -6,6 +6,11 @@ branding: color: gray-dark inputs: + Path: + description: | + Path to where tests are located or a configuration file. + required: false + default: ${{ github.workspace }}/tests Run_Path: description: | Directories to be searched for tests, paths directly to test files, or combination of both. @@ -182,11 +187,6 @@ inputs: description: | Enable TestRegistry. required: false - ConfigurationFilePath: - description: | - Path to the configuration file. - required: false - default: '${{ github.workspace }}/.github/pester.settings.ps1' Debug: description: | Enable debug mode. @@ -301,6 +301,7 @@ runs: id: test continue-on-error: true env: + GITHUB_ACTION_INPUT_Path: ${{ inputs.Path }} GITHUB_ACTION_INPUT_Run_Path: ${{ inputs.Run_Path }} GITHUB_ACTION_INPUT_Run_ExcludePath: ${{ inputs.Run_ExcludePath }} GITHUB_ACTION_INPUT_Run_ScriptBlock: ${{ inputs.Run_ScriptBlock }} @@ -344,7 +345,6 @@ runs: GITHUB_ACTION_INPUT_Output_RenderMode: ${{ inputs.Output_RenderMode }} GITHUB_ACTION_INPUT_TestDrive_Enabled: ${{ inputs.TestDrive_Enabled }} GITHUB_ACTION_INPUT_TestRegistry_Enabled: ${{ inputs.TestRegistry_Enabled }} - GITHUB_ACTION_INPUT_ConfigurationFilePath: ${{ inputs.ConfigurationFilePath }} with: ShowOutput: true Script: | diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index dd809d4a..70cadabf 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -21,15 +21,31 @@ function Get-PesterConfiguration { [string] $Path ) - Get-ChildItem -Path $Path -Filter *.Configuration.ps* | ForEach-Object { - $file = $_ - switch ($file.Extension) { - '.ps1' { - . $file - } - '.psd1' { - Import-PowerShellDataFile -Path $file - } + Write-Output "Path: [$Path]" + $pathExists = Test-Path -Path $Path + if (-not $pathExists) { + throw "Test path does not exist: [$Path]" + } + $item = $Path | Get-Item + + if ($item.PSIsContainer) { + $file = Get-ChildItem -Path $Path -Filter *.Configuration.* + if ($file.Count -eq 0) { + throw "No configuration files found in path: [$Path]" + } + if ($file.Count -gt 1) { + throw "Multiple configuration files found in path: [$Path]" + } + } else { + $file = $item + } + + switch ($file.Extension) { + '.ps1' { + . $file + } + '.psd1' { + Import-PowerShellDataFile -Path $file } } } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index f4b74ae9..6ae61959 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -23,6 +23,8 @@ LogGroup 'Get test kit versions' { LogGroup 'Load inputs' { $inputs = @{ + Path = $env:GITHUB_ACTION_INPUT_Path + Run_Path = $env:GITHUB_ACTION_INPUT_Run_Path Run_ExcludePath = $env:GITHUB_ACTION_INPUT_Run_ExcludePath Run_ScriptBlock = $env:GITHUB_ACTION_INPUT_Run_ScriptBlock @@ -73,7 +75,6 @@ LogGroup 'Load inputs' { TestDrive_Enabled = $env:GITHUB_ACTION_INPUT_TestDrive_Enabled TestRegistry_Enabled = $env:GITHUB_ACTION_INPUT_TestRegistry_Enabled - ConfigurationFilePath = $env:GITHUB_ACTION_INPUT_ConfigurationFilePath } [pscustomobject]($inputs.GetEnumerator() | Where-Object { -not [string]::IsNullOrEmpty($_.Value) }) | Format-List @@ -102,15 +103,7 @@ LogGroup 'Load configuration - Defaults' { } LogGroup 'Load configuration - Custom settings file' { - $customConfigFilePath = $inputs.ConfigurationFilePath - Write-Output "Custom configuration file path: [$customConfigFilePath]" - if ($customConfigFilePath) { - $fileExists = Test-Path -Path $customConfigFilePath - Write-Output "File exists: [$fileExists]" - if ($fileExists) { - $tmpCustom = . $customConfigFilePath - } - } + $tmpCustom = Get-PesterConfiguration -Path $inputs.Path $tmpCustomConfiguration = @{ Run = $tmpCustom.Run ?? @{} Filter = $tmpCustom.Filter ?? @{} From 4d203013e6106d05e21a54ba129f7907fa1cb927 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 22:42:06 +0100 Subject: [PATCH 171/176] Update Get-PesterConfiguration to use Write-Verbose for missing configuration files --- scripts/Helpers.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 70cadabf..6a979f98 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -31,7 +31,8 @@ function Get-PesterConfiguration { if ($item.PSIsContainer) { $file = Get-ChildItem -Path $Path -Filter *.Configuration.* if ($file.Count -eq 0) { - throw "No configuration files found in path: [$Path]" + Write-Verbose "No configuration files found in path: [$Path]" + return @{} } if ($file.Count -gt 1) { throw "Multiple configuration files found in path: [$Path]" From 4b1792a4b9fd0d1c99175ebf4bc07e7ed841c5e5 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 15 Feb 2025 22:59:30 +0100 Subject: [PATCH 172/176] Add Clear-PesterConfigurationEmptyValues filter to clean empty hashtable values --- scripts/Helpers.psm1 | 33 +++++++++++++++++++++++++++++++++ scripts/main.ps1 | 34 +++++++++++----------------------- 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 6a979f98..b6081ca0 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -51,6 +51,39 @@ function Get-PesterConfiguration { } } +filter Clear-PesterConfigurationEmptyValues { + [OutputType([Hashtable])] + [CmdletBinding()] + param ( + [Parameter( + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName + )] + [hashtable] $Hashtable + ) + + $return = @{} + + foreach ($section in $Hashtable.Keys) { + $filteredProperties = @{} + + foreach ($property in $Hashtable[$section].Keys) { + $value = $Hashtable[$section][$property] + + # If the value isn't null or empty string, keep it. + if (-not [string]::IsNullOrEmpty($value)) { + $filteredProperties[$property] = $value + } + } + + $return[$section] = $filteredProperties + } + + return $return +} + + function Merge-Hashtable { <# .SYNOPSIS diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 6ae61959..5c23f10f 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -116,17 +116,7 @@ LogGroup 'Load configuration - Custom settings file' { TestRegistry = $tmpCustom.TestRegistry ?? @{} } - foreach ($section in $tmpCustomConfiguration.Keys) { - $filteredProperties = @{} - foreach ($property in $tmpCustomConfiguration[$section].Keys) { - $value = $tmpCustomConfiguration[$section][$property] - if (-not [string]::IsNullOrEmpty($Value)) { - $filteredProperties[$property] = $Value - } - } - $customConfig[$section] = $filteredProperties - } - + $customConfig = $tmpCustomConfiguration | Clear-PesterConfigurationEmptyValues Write-Output ($customConfig | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } @@ -195,21 +185,11 @@ LogGroup 'Load configuration - Action overrides' { } } - foreach ($section in $customConfigInputMap.Keys) { - $filteredProperties = @{} - foreach ($property in $customConfigInputMap[$section].Keys) { - $value = $customConfigInputMap[$section][$property] - if (-not [string]::IsNullOrEmpty($Value)) { - $filteredProperties[$property] = $Value - } - } - $customInputs[$section] = $filteredProperties - } - + $customInputs = $customConfigInputMap | Clear-PesterConfigurationEmptyValues Write-Output ($customInputs | ConvertTo-Json -Depth 5 -WarningAction SilentlyContinue) } -LogGroup 'Load configuration - Add containers' { +LogGroup 'Load configuration - Merge' { $run = Merge-Hashtable -Main $defaultConfig.Run -Overrides $customConfig.Run, $customInputs.Run $filter = Merge-Hashtable -Main $defaultConfig.Filter -Overrides $customConfig.Filter, $customInputs.Filter $codeCoverage = Merge-Hashtable -Main $defaultConfig.CodeCoverage -Overrides $customConfig.CodeCoverage, $customInputs.CodeCoverage @@ -232,6 +212,14 @@ LogGroup 'Load configuration - Add containers' { TestRegistry = $testRegistry } + if (-not $configuration.Run.Path) { + $configuration.Run.Path = $inputs.Path + } +} + +LogGroup 'Load configuration - Add containers' { + + Write-Output "Containers from configuration: [$($configuration.Run.Container.Count)]" Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) From 417bdd62e5bdffbef28bc0b7fdc2280bfcc5f60d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 16 Feb 2025 01:01:07 +0100 Subject: [PATCH 173/176] Update action.yml to reflect author as PSModule and clean up whitespace in scripts --- README.md | 212 ++++++++++++++++++++++++++++++++++++++++++- action.yml | 2 +- scripts/Helpers.psm1 | 1 - scripts/main.ps1 | 2 - 4 files changed, 209 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3e74c20c..2902ab51 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,221 @@ -# Template-action +# Invoke-Pester -A template repository for GitHub Actions +This GitHub Action runs [Pester](https://pester.dev) tests in PowerShell, producing code coverage and test result artifacts. + +The action handles many tedious tasks so that you only have to focus on designing the tests. Here are some key features: + +- Installation and import of Pester (and PSScriptAnalyzer) modules. +- Automatic merging of default Pester configuration, custom test configuration, and direct GitHub Action inputs. +- Support for uploading test results and code coverage reports as workflow artifacts based on provided Pester configuration. +- Detailed step summary in GitHub’s job logs. + +## Details + +1. **Prerequisite Setup** + - The action installs the required PowerShell modules — namely Pester (for testing) and PSScriptAnalyzer (for static analysis). + - It then imports those modules to make sure all test commands and analysis functions are available. + +2. **Loading Inputs and Configuration** + - The script collects settings using a hierarchicallooks for a default configuration (`Pester.Configuration.ps1`) in the Action’s folder. If it finds one, it loads that into memory as the “base” config. + - All Action inputs are read from the environment (these come from your `action.yml` definitions). + - Next, the script runs `Get-PesterConfiguration -Path` on the `Path` you specified. If a Pester configuration file is found there, it merges that into the base config. + - Finally, any Action-level overrides (the actual GitHub Action inputs) are merged on top. This layered approach ensures you can define defaults in multiple places and still be able to override them easily from the GitHub Workflow. + +3. **Building the Final Pester Configuration** + - After merging all those sources, the script constructs a final Pester configuration hash table. This tells Pester exactly which tests to run, how to filter them, whether to enable code coverage, etc. + - If no test “containers” are defined in the config, the script also attempts to discover any container files (`*.Container.*` patterns) inside the path(s) given. In Pester 5, containers are used to organize or group tests, but if you aren’t explicitly using them, Pester falls back to normal test discovery. + +4. **Running the Tests** + - The script invokes `Invoke-Pester` with the merged configuration. This is where the actual tests are run: + - **Discovery Phase**: Pester looks for tests in the paths and/or containers defined. + - **Execution Phase**: Each discovered test is executed. If containers are defined, they are run in the order and grouping Pester sees fit. + - **Results Gathering**: Pester aggregates pass/fail/skipped/inconclusive results into a final test result object. + +5. **Generating Reports (Optional)** + - **Test Results** (e.g., NUnit/JUnit) are generated if `TestResult_Enabled` is `true`. The result file location is defined by `TestResult_OutputPath`. The Action can then automatically upload this file as an artifact if the run succeeds or fails. + - **Code Coverage** can also be enabled by setting `CodeCoverage_Enabled` to `true`. This generates a coverage report in the format you select (e.g., Cobertura, JaCoCo) and saves it to `CodeCoverage_OutputPath`. That file is also automatically uploaded as an artifact, if enabled. + +6. **Summary in GitHub** + - A summary block is added to the GitHub Actions logs, detailing how many tests passed, failed, or were skipped, along with total coverage. + - If you are using containers, each container’s results are displayed in a collapsible section. This helps you see exactly which tests failed and why. + +7. **Publishing Outputs** + - The Action then extracts key pieces of information—like `Result`, `FailedCount`, `Duration`, etc.—from the final Pester run object. + - Each piece of data is converted to JSON and set as a GitHub Action output. This means subsequent steps or workflows can read those values to make decisions (for instance, fail the build if coverage is below a certain threshold). + +8. **Exit Code** + - The Action returns a non-zero exit code if any tests fail (or if you configured `Run_Throw`, it can throw an exception). This ensures GitHub will mark the job as a failure when tests do not pass. + +--- + +### Why the Configurations Are Layered +- **Default Config**: A built-in Pester configuration (in `Pester.Configuration.ps1` if provided) holds fallback defaults. +- **Repo Config**: Your repository may include a Pester config file that further tailors defaults. +- **Action Inputs**: Finally, everything can be overridden by GitHub Actions inputs. This layering is especially helpful if you want a single set of “global” defaults but occasionally need to tweak the test-run behavior (e.g., skipping slow tests in some branches). + +### Potential Pitfalls +- If your code is in a subfolder and you forget to update `Path` or `Run_Path`, the tests might not be found. +- When code coverage is enabled, make sure the coverage tool you choose is compatible with your environment (e.g., breakpoints vs. profiler-based coverage). +- If you rely on containers but forgot to add them to your config or name them correctly, tests may be skipped (or discovered in an unintended way). + +### Automation Notes +Because all the output is published as JSON, you can chain additional actions or scripts to automatically parse the results. For instance, you could: +- Use a script to compare `CoveragePercent` against a required threshold and automatically open an issue if coverage decreases. +- Parse `Failed` tests in a subsequent step to highlight them in your Slack or Teams notifications. +- Automatically tag or release a build only if `FailedCount` is zero. + +Overall, the Action’s approach is meant to be flexible and extensible, giving you control via the Pester configuration system without making you rewrite existing test logic. ## Usage ### Inputs -### Secrets +Below is a comprehensive list of inputs pulled directly from `action.yml`. All are **optional** unless otherwise noted. + +| **Input** | **Description** | **Default** | +|--------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------| +| `Path` | Path to where tests are located or a configuration file. | `${{ github.workspace }}/tests` | +| `Run_Path` | Directories/files to be searched for tests. | *(none)* | +| `Run_ExcludePath` | Directories/files to exclude from the run. | *(none)* | +| `Run_ScriptBlock` | ScriptBlocks containing tests to be executed. | *(none)* | +| `Run_Container` | ContainerInfo objects containing tests to be executed. See [pester.dev/docs/usage/containers](https://pester.dev/docs/usage/containers). | *(none)* | +| `Run_TestExtension` | Filter used to identify test files (e.g. `.Tests.ps1`). | *(none)* | +| `Run_Exit` | Whether to exit with a non-zero exit code on failure. | *(none)* | +| `Run_Throw` | Whether to throw an exception on test failure. | *(none)* | +| `Run_PassThru` | Return result object to pipeline after finishing the test run. | *(none)* | +| `Run_SkipRun` | Discovery only, skip actual test run. | *(none)* | +| `Run_SkipRemainingOnFailure` | Skips remaining tests after the first failure. Options: `None`, `Run`, `Container`, `Block`. | *(none)* | +| `Filter_Tag` | Tags of Describe/Context/It blocks to run. | *(none)* | +| `Filter_ExcludeTag` | Tags of Describe/Context/It blocks to exclude. | *(none)* | +| `Filter_Line` | Filter by file + scriptblock start line (e.g. `C:\tests\file1.Tests.ps1:37`). | *(none)* | +| `Filter_ExcludeLine` | Exclude by file + scriptblock start line. Precedence over `Filter_Line`. | *(none)* | +| `Filter_FullName` | Full name of a test with wildcards, joined by dot. E.g. `*.describe Get-Item.test1` | *(none)* | +| `CodeCoverage_Enabled` | Enable code coverage. | *(none)* | +| `CodeCoverage_OutputFormat` | Format for the coverage report. Possible values: `JaCoCo`, `CoverageGutters`, `Cobertura`. | *(none)* | +| `CodeCoverage_OutputPath` | Where to save the code coverage report (relative to the current dir). | *(none)* | +| `CodeCoverage_OutputEncoding` | Encoding of the coverage file. | *(none)* | +| `CodeCoverage_Path` | Files/directories to measure coverage on (by default, reuses `Path` from the general settings). | *(none)* | +| `CodeCoverage_ExcludeTests` | Exclude tests themselves from coverage. | *(none)* | +| `CodeCoverage_RecursePaths` | Recurse through coverage directories. | *(none)* | +| `CodeCoverage_CoveragePercentTarget` | Desired minimum coverage percentage. | *(none)* | +| `CodeCoverage_UseBreakpoints` | **Experimental**: When `false`, use a Profiler-based tracer instead of breakpoints. | *(none)* | +| `CodeCoverage_SingleHitBreakpoints` | Remove breakpoints after first hit. | *(none)* | +| `TestResult_Enabled` | Enable test-result output (e.g. NUnitXml, JUnitXml). | *(none)* | +| `TestResult_OutputFormat` | Possible values: `NUnitXml`, `NUnit2.5`, `NUnit3`, `JUnitXml`. | *(none)* | +| `TestResult_OutputPath` | Where to save the test-result report (relative path). | *(none)* | +| `TestResult_OutputEncoding` | Encoding of the test-result file. | *(none)* | +| `TestResult_TestSuiteName` | Name used for the root `test-suite` element in the result file. | *(none)* | +| `Should_ErrorAction` | Controls if `Should` throws on error. Use `Stop` to throw, or `Continue` to fail at the end. | *(none)* | +| `Debug_ShowFullErrors` | Show Pester internal stack on errors. (Deprecated – overrides `Output.StackTraceVerbosity` to `Full`). | *(none)* | +| `Debug_WriteDebugMessages` | Write debug messages to screen. | *(none)* | +| `Debug_WriteDebugMessagesFrom` | Filter debug messages by source. Wildcards allowed. | *(none)* | +| `Debug_ShowNavigationMarkers` | Write paths after every block/test for easy navigation in VSCode. | *(none)* | +| `Debug_ReturnRawResultObject` | Returns an unfiltered result object, for development only. | *(none)* | +| `Output_Verbosity` | Verbosity: `None`, `Normal`, `Detailed`, `Diagnostic`. | *(none)* | +| `Output_StackTraceVerbosity` | Stacktrace detail: `None`, `FirstLine`, `Filtered`, `Full`. | *(none)* | +| `Output_CIFormat` | CI format of error output: `None`, `Auto`, `AzureDevops`, `GithubActions`. | *(none)* | +| `Output_CILogLevel` | CI log level: `Error` or `Warning`. | *(none)* | +| `Output_RenderMode` | How to render console output: `Auto`, `Ansi`, `ConsoleColor`, `Plaintext`. | *(none)* | +| `TestDrive_Enabled` | Enable `TestDrive`. | *(none)* | +| `TestRegistry_Enabled` | Enable `TestRegistry`. | *(none)* | +| `Debug` | Enable debug mode (`true`/`false`). When `true`, uses `PSModule/Debug@v0`. | `false` | + +No secrets are directly required by this Action. ### Outputs +After the test run completes, these outputs become available. They are all JSON-encoded strings, so you can parse them in subsequent steps if needed: + +| **Output** | **Description** | +|--------------------------|------------------------------------------------------| +| `Containers` | Containers object used during the test. | +| `Result` | Whether the tests passed (`Passed`, `Failed`, etc.). | +| `FailedCount` | Number of failed tests. | +| `FailedBlocksCount` | Number of failed blocks. | +| `FailedContainersCount` | Number of failed containers. | +| `PassedCount` | Number of passed tests. | +| `SkippedCount` | Number of skipped tests. | +| `InconclusiveCount` | Number of inconclusive tests. | +| `NotRunCount` | Number of tests not run. | +| `TotalCount` | Total number of tests. | +| `Duration` | Duration of the test run. | +| `Executed` | Number of tests actually executed. | +| `ExecutedAt` | DateTime of the test run. | +| `Version` | Pester version. | +| `PSVersion` | PowerShell version. | +| `PSBoundParameters` | The final set of parameters used to run the tests. | +| `Plugins` | Plugins used during the run. | +| `PluginConfiguration` | Configuration for those plugins. | +| `PluginData` | Data from those plugins. | +| `Configuration` | The merged final Pester configuration used. | +| `DiscoveryDuration` | Discovery-phase duration. | +| `UserDuration` | Duration of user code execution. | +| `FrameworkDuration` | Duration of framework code execution. | +| `Failed` | Info on failed tests. | +| `FailedBlocks` | Info on failed blocks. | +| `FailedContainers` | Info on failed containers. | +| `Passed` | Info on passed tests. | +| `Skipped` | Info on skipped tests. | +| `Inconclusive` | Info on inconclusive tests. | +| `NotRun` | Info on tests not run. | +| `Tests` | All discovered tests. | +| `CodeCoverage` | Code coverage report object. | +| `TestResultEnabled` | `true`/`false` based on `TestResult_Enabled`. | +| `TestResultOutputPath` | Path to the test result file. | +| `TestSuiteName` | Name of the test suite. | +| `CodeCoverageEnabled` | `true`/`false` based on `CodeCoverage_Enabled`. | +| `CodeCoverageOutputPath` | Where the coverage report was saved. | + ### Example +Below is a complete example of using this Action in a workflow. It: + +- Checks out the repo +- Runs Pester tests in the `tests` folder +- Produces coverage and test results +- Uploads each report as an artifact if applicable + ```yaml -Example here +name: Pester Tests + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + test-pester: + runs-on: ubuntu-latest + + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Run Pester Tests + uses: PSModule/Invoke-Pester@v1 + with: + Path: './tests' + CodeCoverage_Enabled: 'true' + TestResult_Enabled: 'true' + TestResult_TestSuiteName: 'IntegrationTests' + Debug: 'false' + + # Note: The action already includes artifact uploads if coverage & results are enabled. + # The final pass/fail status is determined by the test results. If any test fails, + # the step exit code will be non-zero (assuming Run_Exit and/or Run_Throw is true). ``` + +### Tips & Notes + +- If you want to **skip** the coverage or test results upload, set `TestResult_Enabled` or `CodeCoverage_Enabled` to `false`. +- If you prefer the step *never fails*, set `Run_Exit: false` and `Run_Throw: false`. (Not recommended, but possible.) +- The final test run’s pass/fail is also reflected in the step exit code by default if `Run_Exit` is `true`. +- Use `Debug: 'true'` to show extra logs from the action (via `PSModule/Debug@v0`). +- If your tests rely on a custom Pester configuration file, place that file in your repo (for example, `MyTests.Configuration.psd1`) and point `Path` or `Run_Path` to that. This action merges your config with the defaults. + +## Contributing + +1. Open a pull request with your changes. +2. Ensure you’ve tested your updated action in a real or test workflow. +3. We welcome bug reports, feature requests, and suggestions for improvement. diff --git a/action.yml b/action.yml index 7f4fd5ad..4f1900dd 100644 --- a/action.yml +++ b/action.yml @@ -1,4 +1,4 @@ -name: Invoke-Pester +name: Invoke-Pester (by PSModule) description: Runs test, using Pester and PowerShell. author: PSModule branding: diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index b6081ca0..41c93129 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -83,7 +83,6 @@ filter Clear-PesterConfigurationEmptyValues { return $return } - function Merge-Hashtable { <# .SYNOPSIS diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 5c23f10f..42f85c11 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -218,8 +218,6 @@ LogGroup 'Load configuration - Merge' { } LogGroup 'Load configuration - Add containers' { - - Write-Output "Containers from configuration: [$($configuration.Run.Container.Count)]" Write-Output ($configuration.Run.Container | ConvertTo-Json -Depth 2 -WarningAction SilentlyContinue) From 76ecec5704526ed1c02a3ad385291e06dde2adee Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 16 Feb 2025 01:23:28 +0100 Subject: [PATCH 174/176] Add README --- README.md | 226 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 138 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index 2902ab51..23842250 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,158 @@ # Invoke-Pester -This GitHub Action runs [Pester](https://pester.dev) tests in PowerShell, producing code coverage and test result artifacts. +This GitHub Action runs [Pester](https://pester.dev) tests in PowerShell, producing code coverage and test result artifacts. It automates many tasks to streamline continuous integration for PowerShell projects: -The action handles many tedious tasks so that you only have to focus on designing the tests. Here are some key features: +- Installation and import of required modules (Pester, PSScriptAnalyzer). +- Automatic merging of default, repo-level, and direct inputs into a final Pester configuration. +- Optional uploading of test results and coverage reports. +- Clear step summary in GitHub’s job logs. -- Installation and import of Pester (and PSScriptAnalyzer) modules. -- Automatic merging of default Pester configuration, custom test configuration, and direct GitHub Action inputs. -- Support for uploading test results and code coverage reports as workflow artifacts based on provided Pester configuration. -- Detailed step summary in GitHub’s job logs. +## Introduction & Scope -## Details +**Invoke-Pester** is designed to: +- **Execute all Pester tests** in your repository, with optional container-based test organization. +- **Collect code coverage** metrics, if desired. +- **Summarize test results** with a neat table in the workflow’s step summary. +- **Upload artifacts** (e.g. coverage reports, test results) to GitHub for later inspection. +- **Allow flexible configuration** through a layered approach—defaults, repository-level config, and direct inputs. + +By default, it tries to “just work” for the majority of scenarios. Advanced users can configure everything from coverage thresholds to skipping slow tests. + +## Configuration Hierarchy + +The action’s behavior is controlled by **layered configuration**: + +1. **Default Config** + Packaged with the action (in `Pester.Configuration.ps1` if provided). Sets base paths, coverage toggles, artifact names, etc. + +2. **Repo-Level Config** + If your repository contains a Pester config file (e.g., `MyTests.Configuration.psd1` or `Pester.Configuration.ps1`), the action loads and merges those settings on top of the defaults. + +3. **Direct Inputs** + Finally, any inputs specified under the `with:` clause in your GitHub Action workflow override both the default and repo-level config. + > *Example:* If you specify `CodeCoverage_Enabled: true` here, it will enable coverage even if the repo config says otherwise. + +This **“last-write-wins”** strategy means you can set global defaults while retaining the flexibility to override them at the action level. + + +## How This Action Processes Your Tests 1. **Prerequisite Setup** - - The action installs the required PowerShell modules — namely Pester (for testing) and PSScriptAnalyzer (for static analysis). - - It then imports those modules to make sure all test commands and analysis functions are available. + - Installs required PowerShell modules (Pester, PSScriptAnalyzer) if they’re not present. + - Imports the modules so the testing framework is ready to use. 2. **Loading Inputs and Configuration** - - The script collects settings using a hierarchicallooks for a default configuration (`Pester.Configuration.ps1`) in the Action’s folder. If it finds one, it loads that into memory as the “base” config. - - All Action inputs are read from the environment (these come from your `action.yml` definitions). - - Next, the script runs `Get-PesterConfiguration -Path` on the `Path` you specified. If a Pester configuration file is found there, it merges that into the base config. - - Finally, any Action-level overrides (the actual GitHub Action inputs) are merged on top. This layered approach ensures you can define defaults in multiple places and still be able to override them easily from the GitHub Workflow. + - Reads all GitHub Action inputs from `action.yml` environment variables. + - (Optional) Loads a base config file included with the action (e.g., `Pester.Configuration.ps1` in the action folder). + - If `Path` points to a location with a Pester configuration file, merges that config. + - Finally, merges any direct inputs provided in your workflow. + - The result is a **final Pester configuration** that determines what tests to run and how to run them. 3. **Building the Final Pester Configuration** - - After merging all those sources, the script constructs a final Pester configuration hash table. This tells Pester exactly which tests to run, how to filter them, whether to enable code coverage, etc. - - If no test “containers” are defined in the config, the script also attempts to discover any container files (`*.Container.*` patterns) inside the path(s) given. In Pester 5, containers are used to organize or group tests, but if you aren’t explicitly using them, Pester falls back to normal test discovery. + - Collects all merged settings into a single configuration object. + - If no “containers” (advanced Pester 5 grouping) are explicitly defined, it attempts to discover them automatically (files matching `*.Container.*`). 4. **Running the Tests** - - The script invokes `Invoke-Pester` with the merged configuration. This is where the actual tests are run: - - **Discovery Phase**: Pester looks for tests in the paths and/or containers defined. - - **Execution Phase**: Each discovered test is executed. If containers are defined, they are run in the order and grouping Pester sees fit. - - **Results Gathering**: Pester aggregates pass/fail/skipped/inconclusive results into a final test result object. + - Calls [`Invoke-Pester`](https://pester.dev/docs/commands/Invoke-Pester) using that final configuration. + - **Discovery Phase**: Finds test files/containers. + - **Execution Phase**: Runs tests, logs pass/fail/skipped/inconclusive. + - **Results Gathering**: Aggregates outcomes into a final test object. 5. **Generating Reports (Optional)** - - **Test Results** (e.g., NUnit/JUnit) are generated if `TestResult_Enabled` is `true`. The result file location is defined by `TestResult_OutputPath`. The Action can then automatically upload this file as an artifact if the run succeeds or fails. - - **Code Coverage** can also be enabled by setting `CodeCoverage_Enabled` to `true`. This generates a coverage report in the format you select (e.g., Cobertura, JaCoCo) and saves it to `CodeCoverage_OutputPath`. That file is also automatically uploaded as an artifact, if enabled. + - **Test Results** (e.g., NUnit/XML) if `TestResult_Enabled` is `true`. The file is saved to `TestResult_OutputPath`. + - **Code Coverage** if `CodeCoverage_Enabled` is `true`. Saves coverage data (Cobertura, JaCoCo, etc.) to `CodeCoverage_OutputPath`. + - These reports can automatically be uploaded as workflow artifacts. 6. **Summary in GitHub** - - A summary block is added to the GitHub Actions logs, detailing how many tests passed, failed, or were skipped, along with total coverage. - - If you are using containers, each container’s results are displayed in a collapsible section. This helps you see exactly which tests failed and why. + - A step summary is generated, showing how many tests passed/failed/skipped, plus coverage info. + - If containers are in use, each container’s results appear in a collapsible section. 7. **Publishing Outputs** - - The Action then extracts key pieces of information—like `Result`, `FailedCount`, `Duration`, etc.—from the final Pester run object. - - Each piece of data is converted to JSON and set as a GitHub Action output. This means subsequent steps or workflows can read those values to make decisions (for instance, fail the build if coverage is below a certain threshold). + - Key metrics (e.g., `Result`, `FailedCount`, `Duration`) are encoded in JSON and published as outputs. + - Subsequent steps can parse these to decide whether to fail the build, open an issue, or notify a channel. 8. **Exit Code** - - The Action returns a non-zero exit code if any tests fail (or if you configured `Run_Throw`, it can throw an exception). This ensures GitHub will mark the job as a failure when tests do not pass. + - By default, returns a non-zero exit code if any tests fail (unless you override with `Run_Exit: false` or `Run_Throw: false`). + - This ensures the GitHub job is marked as failed if your tests do not pass. + + +## Failure Handling + +- **No Immediate Fail on First Test Error**: + The entire suite runs, capturing all failures before deciding on pass/fail. +- **Allowed Failures / Coverage Threshold**: + You can configure if any test failure leads to a fail, or whether certain coverage levels must be met. +- **Default Behavior**: + If any test fails, the job fails at the end (exit code != 0). You can change this via `Run_Exit` or `Run_Throw`. + + +## Artifact Management + +- **Test Result Artifacts** + - By default, if `TestResult_Enabled` is true, the action saves a test result file (XML/JSON) to `TestResult_OutputPath` and uploads it with GitHub’s `actions/upload-artifact`. +- **Coverage Report Artifacts** + - If `CodeCoverage_Enabled` is true, a coverage file (Cobertura, JaCoCo, etc.) is generated and uploaded similarly. +- **Naming & Paths** + - You can override default filenames or directories in your config or direct inputs. +- **Logs & Extras** + - Generally, the action only uploads essential coverage and test result files, though you can adapt it to collect additional logs if needed. + +## Step Summary & Coverage Reporting + +- **Detailed Markdown Summary**: + Displays overall test results (passed, failed, skipped) and coverage in a table. +- **Collapsible Breakdown**: + Each container or test file can be expanded for deeper inspection. +- **Always Visible**: + Even if the action fails, the summary is posted so you can quickly see why. ---- +## Potential Pitfalls -### Why the Configurations Are Layered -- **Default Config**: A built-in Pester configuration (in `Pester.Configuration.ps1` if provided) holds fallback defaults. -- **Repo Config**: Your repository may include a Pester config file that further tailors defaults. -- **Action Inputs**: Finally, everything can be overridden by GitHub Actions inputs. This layering is especially helpful if you want a single set of “global” defaults but occasionally need to tweak the test-run behavior (e.g., skipping slow tests in some branches). +- If your tests are in a subfolder and `Path` or `Run_Path` isn’t updated, you might discover zero tests. +- Code coverage can differ between breakpoint-based (default) and profiler-based methods—choose which suits your environment (`CodeCoverage_UseBreakpoints`). +- Containers are optional in Pester 5. If you rely on them but name them incorrectly, Pester might skip them. -### Potential Pitfalls -- If your code is in a subfolder and you forget to update `Path` or `Run_Path`, the tests might not be found. -- When code coverage is enabled, make sure the coverage tool you choose is compatible with your environment (e.g., breakpoints vs. profiler-based coverage). -- If you rely on containers but forgot to add them to your config or name them correctly, tests may be skipped (or discovered in an unintended way). +## Automation Notes -### Automation Notes -Because all the output is published as JSON, you can chain additional actions or scripts to automatically parse the results. For instance, you could: -- Use a script to compare `CoveragePercent` against a required threshold and automatically open an issue if coverage decreases. -- Parse `Failed` tests in a subsequent step to highlight them in your Slack or Teams notifications. -- Automatically tag or release a build only if `FailedCount` is zero. +- **Threshold Enforcement**: You can parse `CoveragePercent` from the outputs in a subsequent step and fail the build if coverage is below X%. +- **Automatic Notifications**: Use the published JSON outputs (e.g., `Failed`) to highlight failing tests in Slack or Teams. +- **Versioning & Releases**: If `FailedCount` is zero, you could trigger a deployment or release pipeline automatically. -Overall, the Action’s approach is meant to be flexible and extensible, giving you control via the Pester configuration system without making you rewrite existing test logic. ## Usage +Below is a typical usage example. (Subsequent sections list *all* available inputs and outputs.) + +```yaml +name: Pester Tests + +on: + push: + +jobs: + test-pester: + runs-on: ubuntu-latest + + steps: + - name: Check out + uses: actions/checkout@v4 + + - name: Run Pester Tests + uses: PSModule/Invoke-Pester@v1 + with: + Path: './tests' + CodeCoverage_Enabled: 'true' + TestResult_Enabled: 'true' + TestResult_TestSuiteName: 'IntegrationTests' + # Configure additional inputs, e.g. Run_Throw, Run_Exit, etc. + + # If coverage & results are enabled, the action automatically uploads them as artifacts. + # The step exit code will be non-zero if any tests fail, unless overridden. +``` + ### Inputs -Below is a comprehensive list of inputs pulled directly from `action.yml`. All are **optional** unless otherwise noted. +All are **optional** unless otherwise noted. | **Input** | **Description** | **Default** | |--------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------| @@ -166,56 +248,24 @@ After the test run completes, these outputs become available. They are all JSON- | `CodeCoverageEnabled` | `true`/`false` based on `CodeCoverage_Enabled`. | | `CodeCoverageOutputPath` | Where the coverage report was saved. | -### Example - -Below is a complete example of using this Action in a workflow. It: - -- Checks out the repo -- Runs Pester tests in the `tests` folder -- Produces coverage and test results -- Uploads each report as an artifact if applicable -```yaml -name: Pester Tests - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - test-pester: - runs-on: ubuntu-latest - - steps: - - name: Check out - uses: actions/checkout@v3 +### Tips & Notes - - name: Run Pester Tests - uses: PSModule/Invoke-Pester@v1 - with: - Path: './tests' - CodeCoverage_Enabled: 'true' - TestResult_Enabled: 'true' - TestResult_TestSuiteName: 'IntegrationTests' - Debug: 'false' +- To **skip coverage** or **test result uploads**, set `CodeCoverage_Enabled: false` or `TestResult_Enabled: false`. +- If you do **not** want a failing test to cause the step to fail, set `Run_Exit: false` and `Run_Throw: false`. +- For deeper debug info, set `Debug: 'true'` (which uses the [PSModule/Debug@v0](https://github.com/PSModule/Debug) action). +- If your tests require a **custom Pester config**, place it in your repo and point `Path` or `Run_Path` to it. The action merges that file with defaults. - # Note: The action already includes artifact uploads if coverage & results are enabled. - # The final pass/fail status is determined by the test results. If any test fails, - # the step exit code will be non-zero (assuming Run_Exit and/or Run_Throw is true). -``` +## Contributing -### Tips & Notes +1. Open a pull request with your proposed changes (bug fixes, improvements, new features). +2. Test your branch in a real or mock workflow if possible to confirm it behaves as intended. +3. We welcome any ideas for streamlining test runs, coverage generation, or other enhancements. -- If you want to **skip** the coverage or test results upload, set `TestResult_Enabled` or `CodeCoverage_Enabled` to `false`. -- If you prefer the step *never fails*, set `Run_Exit: false` and `Run_Throw: false`. (Not recommended, but possible.) -- The final test run’s pass/fail is also reflected in the step exit code by default if `Run_Exit` is `true`. -- Use `Debug: 'true'` to show extra logs from the action (via `PSModule/Debug@v0`). -- If your tests rely on a custom Pester configuration file, place that file in your repo (for example, `MyTests.Configuration.psd1`) and point `Path` or `Run_Path` to that. This action merges your config with the defaults. +## Conclusion -## Contributing +The **Invoke-Pester** GitHub Action streamlines automated PowerShell testing in CI/CD by merging multiple configuration layers, running Pester tests, +collecting coverage, generating artifacts, and neatly summarizing results. It helps maintain a robust CI environment for PowerShell projects of all +sizes. If you have questions or want to contribute, feel free to open an issue or pull request. -1. Open a pull request with your changes. -2. Ensure you’ve tested your updated action in a real or test workflow. -3. We welcome bug reports, feature requests, and suggestions for improvement. +Happy pestering! From 43047b462de5b54d9462488a78f575e8721e1530 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 16 Feb 2025 01:31:41 +0100 Subject: [PATCH 175/176] Update README to clarify configuration merging process and improve wording --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 23842250..6d0dc0a9 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This GitHub Action runs [Pester](https://pester.dev) tests in PowerShell, producing code coverage and test result artifacts. It automates many tasks to streamline continuous integration for PowerShell projects: - Installation and import of required modules (Pester, PSScriptAnalyzer). -- Automatic merging of default, repo-level, and direct inputs into a final Pester configuration. +- Automatic merging of default configuration, test suite configuration, and direct inputs into a final Pester configuration. - Optional uploading of test results and coverage reports. - Clear step summary in GitHub’s job logs. @@ -25,12 +25,12 @@ The action’s behavior is controlled by **layered configuration**: 1. **Default Config** Packaged with the action (in `Pester.Configuration.ps1` if provided). Sets base paths, coverage toggles, artifact names, etc. -2. **Repo-Level Config** - If your repository contains a Pester config file (e.g., `MyTests.Configuration.psd1` or `Pester.Configuration.ps1`), the action loads and merges those settings on top of the defaults. +2. **Test Suite Config** + If your test suite contains a Pester config file (e.g., `MyTests.Configuration.psd1` or `Pester.Configuration.ps1`), the action loads and merges those settings on top of the defaults. 3. **Direct Inputs** - Finally, any inputs specified under the `with:` clause in your GitHub Action workflow override both the default and repo-level config. - > *Example:* If you specify `CodeCoverage_Enabled: true` here, it will enable coverage even if the repo config says otherwise. + Finally, any inputs specified under the `with:` clause in your GitHub Action workflow override both the default and test suite config. + > *Example:* If you specify `CodeCoverage_Enabled: true` here, it will enable coverage even if the test suite config says otherwise. This **“last-write-wins”** strategy means you can set global defaults while retaining the flexibility to override them at the action level. @@ -191,7 +191,7 @@ All are **optional** unless otherwise noted. | `Debug_ShowFullErrors` | Show Pester internal stack on errors. (Deprecated – overrides `Output.StackTraceVerbosity` to `Full`). | *(none)* | | `Debug_WriteDebugMessages` | Write debug messages to screen. | *(none)* | | `Debug_WriteDebugMessagesFrom` | Filter debug messages by source. Wildcards allowed. | *(none)* | -| `Debug_ShowNavigationMarkers` | Write paths after every block/test for easy navigation in VSCode. | *(none)* | +| `Debug_ShowNavigationMarkers` | Write paths after every block/test for easy navigation in Visual Studio Code. | *(none)* | | `Debug_ReturnRawResultObject` | Returns an unfiltered result object, for development only. | *(none)* | | `Output_Verbosity` | Verbosity: `None`, `Normal`, `Detailed`, `Diagnostic`. | *(none)* | | `Output_StackTraceVerbosity` | Stacktrace detail: `None`, `FirstLine`, `Filtered`, `Full`. | *(none)* | @@ -254,11 +254,11 @@ After the test run completes, these outputs become available. They are all JSON- - To **skip coverage** or **test result uploads**, set `CodeCoverage_Enabled: false` or `TestResult_Enabled: false`. - If you do **not** want a failing test to cause the step to fail, set `Run_Exit: false` and `Run_Throw: false`. - For deeper debug info, set `Debug: 'true'` (which uses the [PSModule/Debug@v0](https://github.com/PSModule/Debug) action). -- If your tests require a **custom Pester config**, place it in your repo and point `Path` or `Run_Path` to it. The action merges that file with defaults. +- If your tests require a **custom Pester config**, place it in your repository and point `Path` or `Run_Path` to it. The action merges that file with defaults. ## Contributing -1. Open a pull request with your proposed changes (bug fixes, improvements, new features). +1. Open a pull request with your proposed changes (bugfixes, improvements, new features). 2. Test your branch in a real or mock workflow if possible to confirm it behaves as intended. 3. We welcome any ideas for streamlining test runs, coverage generation, or other enhancements. From 2ac835a2782b92f779688cb354a1147f7c404222 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 16 Feb 2025 01:33:42 +0100 Subject: [PATCH 176/176] --- README.md | 98 +++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 6d0dc0a9..05abdade 100644 --- a/README.md +++ b/README.md @@ -152,55 +152,55 @@ jobs: ### Inputs -All are **optional** unless otherwise noted. - -| **Input** | **Description** | **Default** | -|--------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------| -| `Path` | Path to where tests are located or a configuration file. | `${{ github.workspace }}/tests` | -| `Run_Path` | Directories/files to be searched for tests. | *(none)* | -| `Run_ExcludePath` | Directories/files to exclude from the run. | *(none)* | -| `Run_ScriptBlock` | ScriptBlocks containing tests to be executed. | *(none)* | -| `Run_Container` | ContainerInfo objects containing tests to be executed. See [pester.dev/docs/usage/containers](https://pester.dev/docs/usage/containers). | *(none)* | -| `Run_TestExtension` | Filter used to identify test files (e.g. `.Tests.ps1`). | *(none)* | -| `Run_Exit` | Whether to exit with a non-zero exit code on failure. | *(none)* | -| `Run_Throw` | Whether to throw an exception on test failure. | *(none)* | -| `Run_PassThru` | Return result object to pipeline after finishing the test run. | *(none)* | -| `Run_SkipRun` | Discovery only, skip actual test run. | *(none)* | -| `Run_SkipRemainingOnFailure` | Skips remaining tests after the first failure. Options: `None`, `Run`, `Container`, `Block`. | *(none)* | -| `Filter_Tag` | Tags of Describe/Context/It blocks to run. | *(none)* | -| `Filter_ExcludeTag` | Tags of Describe/Context/It blocks to exclude. | *(none)* | -| `Filter_Line` | Filter by file + scriptblock start line (e.g. `C:\tests\file1.Tests.ps1:37`). | *(none)* | -| `Filter_ExcludeLine` | Exclude by file + scriptblock start line. Precedence over `Filter_Line`. | *(none)* | -| `Filter_FullName` | Full name of a test with wildcards, joined by dot. E.g. `*.describe Get-Item.test1` | *(none)* | -| `CodeCoverage_Enabled` | Enable code coverage. | *(none)* | -| `CodeCoverage_OutputFormat` | Format for the coverage report. Possible values: `JaCoCo`, `CoverageGutters`, `Cobertura`. | *(none)* | -| `CodeCoverage_OutputPath` | Where to save the code coverage report (relative to the current dir). | *(none)* | -| `CodeCoverage_OutputEncoding` | Encoding of the coverage file. | *(none)* | -| `CodeCoverage_Path` | Files/directories to measure coverage on (by default, reuses `Path` from the general settings). | *(none)* | -| `CodeCoverage_ExcludeTests` | Exclude tests themselves from coverage. | *(none)* | -| `CodeCoverage_RecursePaths` | Recurse through coverage directories. | *(none)* | -| `CodeCoverage_CoveragePercentTarget` | Desired minimum coverage percentage. | *(none)* | -| `CodeCoverage_UseBreakpoints` | **Experimental**: When `false`, use a Profiler-based tracer instead of breakpoints. | *(none)* | -| `CodeCoverage_SingleHitBreakpoints` | Remove breakpoints after first hit. | *(none)* | -| `TestResult_Enabled` | Enable test-result output (e.g. NUnitXml, JUnitXml). | *(none)* | -| `TestResult_OutputFormat` | Possible values: `NUnitXml`, `NUnit2.5`, `NUnit3`, `JUnitXml`. | *(none)* | -| `TestResult_OutputPath` | Where to save the test-result report (relative path). | *(none)* | -| `TestResult_OutputEncoding` | Encoding of the test-result file. | *(none)* | -| `TestResult_TestSuiteName` | Name used for the root `test-suite` element in the result file. | *(none)* | -| `Should_ErrorAction` | Controls if `Should` throws on error. Use `Stop` to throw, or `Continue` to fail at the end. | *(none)* | -| `Debug_ShowFullErrors` | Show Pester internal stack on errors. (Deprecated – overrides `Output.StackTraceVerbosity` to `Full`). | *(none)* | -| `Debug_WriteDebugMessages` | Write debug messages to screen. | *(none)* | -| `Debug_WriteDebugMessagesFrom` | Filter debug messages by source. Wildcards allowed. | *(none)* | -| `Debug_ShowNavigationMarkers` | Write paths after every block/test for easy navigation in Visual Studio Code. | *(none)* | -| `Debug_ReturnRawResultObject` | Returns an unfiltered result object, for development only. | *(none)* | -| `Output_Verbosity` | Verbosity: `None`, `Normal`, `Detailed`, `Diagnostic`. | *(none)* | -| `Output_StackTraceVerbosity` | Stacktrace detail: `None`, `FirstLine`, `Filtered`, `Full`. | *(none)* | -| `Output_CIFormat` | CI format of error output: `None`, `Auto`, `AzureDevops`, `GithubActions`. | *(none)* | -| `Output_CILogLevel` | CI log level: `Error` or `Warning`. | *(none)* | -| `Output_RenderMode` | How to render console output: `Auto`, `Ansi`, `ConsoleColor`, `Plaintext`. | *(none)* | -| `TestDrive_Enabled` | Enable `TestDrive`. | *(none)* | -| `TestRegistry_Enabled` | Enable `TestRegistry`. | *(none)* | -| `Debug` | Enable debug mode (`true`/`false`). When `true`, uses `PSModule/Debug@v0`. | `false` | +All are **optional** unless otherwise noted. For more info on the configuration options, see the [Pester documentation](https://pester.dev/docs/usage/configuration). + +| **Input** | **Description** | **Default** | +|--------------------------------------|--------------------------------------------------------------------------------------------------------|---------------------------------| +| `Path` | Path to where tests are located or a configuration file. | `${{ github.workspace }}/tests` | +| `Run_Path` | Directories/files to be searched for tests. | *(none)* | +| `Run_ExcludePath` | Directories/files to exclude from the run. | *(none)* | +| `Run_ScriptBlock` | ScriptBlocks containing tests to be executed. | *(none)* | +| `Run_Container` | ContainerInfo objects containing tests to be executed. | *(none)* | +| `Run_TestExtension` | Filter used to identify test files (e.g. `.Tests.ps1`). | *(none)* | +| `Run_Exit` | Whether to exit with a non-zero exit code on failure. | *(none)* | +| `Run_Throw` | Whether to throw an exception on test failure. | *(none)* | +| `Run_PassThru` | Return result object to pipeline after finishing the test run. | *(none)* | +| `Run_SkipRun` | Discovery only, skip actual test run. | *(none)* | +| `Run_SkipRemainingOnFailure` | Skips remaining tests after the first failure. Options: `None`, `Run`, `Container`, `Block`. | *(none)* | +| `Filter_Tag` | Tags of Describe/Context/It blocks to run. | *(none)* | +| `Filter_ExcludeTag` | Tags of Describe/Context/It blocks to exclude. | *(none)* | +| `Filter_Line` | Filter by file + scriptblock start line (e.g. `C:\tests\file1.Tests.ps1:37`). | *(none)* | +| `Filter_ExcludeLine` | Exclude by file + scriptblock start line. Precedence over `Filter_Line`. | *(none)* | +| `Filter_FullName` | Full name of a test with wildcards, joined by dot. E.g. `*.describe Get-Item.test1` | *(none)* | +| `CodeCoverage_Enabled` | Enable code coverage. | *(none)* | +| `CodeCoverage_OutputFormat` | Format for the coverage report. Possible values: `JaCoCo`, `CoverageGutters`, `Cobertura`. | *(none)* | +| `CodeCoverage_OutputPath` | Where to save the code coverage report (relative to the current dir). | *(none)* | +| `CodeCoverage_OutputEncoding` | Encoding of the coverage file. | *(none)* | +| `CodeCoverage_Path` | Files/directories to measure coverage on (by default, reuses `Path` from the general settings). | *(none)* | +| `CodeCoverage_ExcludeTests` | Exclude tests themselves from coverage. | *(none)* | +| `CodeCoverage_RecursePaths` | Recurse through coverage directories. | *(none)* | +| `CodeCoverage_CoveragePercentTarget` | Desired minimum coverage percentage. | *(none)* | +| `CodeCoverage_UseBreakpoints` | **Experimental**: When `false`, use a Profiler-based tracer instead of breakpoints. | *(none)* | +| `CodeCoverage_SingleHitBreakpoints` | Remove breakpoints after first hit. | *(none)* | +| `TestResult_Enabled` | Enable test-result output (e.g. NUnitXml, JUnitXml). | *(none)* | +| `TestResult_OutputFormat` | Possible values: `NUnitXml`, `NUnit2.5`, `NUnit3`, `JUnitXml`. | *(none)* | +| `TestResult_OutputPath` | Where to save the test-result report (relative path). | *(none)* | +| `TestResult_OutputEncoding` | Encoding of the test-result file. | *(none)* | +| `TestResult_TestSuiteName` | Name used for the root `test-suite` element in the result file. | *(none)* | +| `Should_ErrorAction` | Controls if `Should` throws on error. Use `Stop` to throw, or `Continue` to fail at the end. | *(none)* | +| `Debug_ShowFullErrors` | Show Pester internal stack on errors. (Deprecated – overrides `Output.StackTraceVerbosity` to `Full`). | *(none)* | +| `Debug_WriteDebugMessages` | Write debug messages to screen. | *(none)* | +| `Debug_WriteDebugMessagesFrom` | Filter debug messages by source. Wildcards allowed. | *(none)* | +| `Debug_ShowNavigationMarkers` | Write paths after every block/test for easy navigation in Visual Studio Code. | *(none)* | +| `Debug_ReturnRawResultObject` | Returns an unfiltered result object, for development only. | *(none)* | +| `Output_Verbosity` | Verbosity: `None`, `Normal`, `Detailed`, `Diagnostic`. | *(none)* | +| `Output_StackTraceVerbosity` | Stacktrace detail: `None`, `FirstLine`, `Filtered`, `Full`. | *(none)* | +| `Output_CIFormat` | CI format of error output: `None`, `Auto`, `AzureDevops`, `GithubActions`. | *(none)* | +| `Output_CILogLevel` | CI log level: `Error` or `Warning`. | *(none)* | +| `Output_RenderMode` | How to render console output: `Auto`, `Ansi`, `ConsoleColor`, `Plaintext`. | *(none)* | +| `TestDrive_Enabled` | Enable `TestDrive`. | *(none)* | +| `TestRegistry_Enabled` | Enable `TestRegistry`. | *(none)* | +| `Debug` | Enable debug mode (`true`/`false`). When `true`, uses `PSModule/Debug@v0`. | `false` | No secrets are directly required by this Action.