From c98163eb451298efae83023656d64ddcbe7863cc Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL HE/HIM) (from Dev Box)" Date: Wed, 7 Oct 2026 17:42:55 -0700 Subject: [PATCH 1/2] Scope tests to selected projects Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- build.ps1 | 7 +++++ helpers.build.psm1 | 16 +++++++--- tests/helpers.build.pester.tests.ps1 | 46 ++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 tests/helpers.build.pester.tests.ps1 diff --git a/build.ps1 b/build.ps1 index a3adf7890..52f30f22b 100755 --- a/build.ps1 +++ b/build.ps1 @@ -44,6 +44,10 @@ using module ./helpers.build.psm1 .PARAMETER Test Determines whether to run Rust and Pester tests for the project. + .PARAMETER Project + Specifies the projects to build. When used with `-Test`, only tests for the selected projects + are run. + .PARAMETER CodeCoverage Enables code coverage instrumentation using cargo-llvm-cov. When specified, the build and tests run with coverage instrumentation enabled and an LCOV report is generated at the path @@ -366,6 +370,9 @@ process { $pesterParams = @{ UsingADO = $usingADO } + if ($Project.Count -ge 1) { + $pesterParams.Project = $BuildData.Projects + } if ($null -ne $PesterTestGroup) { $pesterParams.Group = $PesterTestGroup } diff --git a/helpers.build.psm1 b/helpers.build.psm1 index f8e907701..76c68327c 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -2882,15 +2882,21 @@ function Test-ProjectWithPester { Write-Verbose "Updated Pester module location:`n`t$((Get-Module -Name Pester -ListAvailable).Path)" } $pesterParams = @{ - Output = 'Detailed' + Output = 'Detailed' ErrorAction = 'Stop' } if ($Project) { - $pesterParams.ExcludePath = $Project.RelativePath | Where-Object -FilterScript { - $_.Name -notin $Project.Name + $projectPath = $Project.RelativePath + if ($Group) { + $projectPath = $projectPath | Where-Object -FilterScript { + ($_ -split '[/\\]', 2)[0] -in $Group + } } - } - if ($Group) { + if ($projectPath.Count -eq 0) { + throw 'None of the selected projects are in the specified Pester test groups.' + } + $pesterParams.Path = $projectPath + } elseif ($Group) { $pesterParams.Path = $Group } } diff --git a/tests/helpers.build.pester.tests.ps1 b/tests/helpers.build.pester.tests.ps1 new file mode 100644 index 000000000..135279cd1 --- /dev/null +++ b/tests/helpers.build.pester.tests.ps1 @@ -0,0 +1,46 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +Describe 'Test-ProjectWithPester' { + BeforeAll { + Import-Module (Join-Path $PSScriptRoot '..' 'helpers.build.psm1') -Force + $buildData = Import-DscBuildData -RefreshProjects + $dscProject = $buildData.Projects | Where-Object -Property Name -EQ 'dsc' + $fileContentProject = $buildData.Projects | Where-Object -Property Name -EQ 'filecontent' + } + + BeforeEach { + $originalPSModulePath = $env:PSModulePath + Mock Invoke-Pester -ModuleName helpers.build + } + + AfterEach { + $env:PSModulePath = $originalPSModulePath + } + + It 'Runs tests only from the selected project paths' { + Test-ProjectWithPester -Project @($dscProject, $fileContentProject) + + Should -Invoke Invoke-Pester -ModuleName helpers.build -Exactly 1 -ParameterFilter { + $Path.Count -eq 2 -and + $Path -contains 'dsc' -and + $Path -contains 'resources/filecontent' + } + } + + It 'Intersects selected projects with Pester test groups' { + Test-ProjectWithPester -Project @($dscProject, $fileContentProject) -Group 'resources' + + Should -Invoke Invoke-Pester -ModuleName helpers.build -Exactly 1 -ParameterFilter { + $Path.Count -eq 1 -and $Path -contains 'resources/filecontent' + } + } + + It 'Fails when selected projects do not belong to a Pester test group' { + { + Test-ProjectWithPester -Project $dscProject -Group 'resources' + } | Should -Throw 'None of the selected projects are in the specified Pester test groups.' + + Should -Invoke Invoke-Pester -ModuleName helpers.build -Exactly 0 + } +} From 3e0fbc241ef146f9c6ab93f85608180006d53b87 Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL HE/HIM) (from Dev Box)" Date: Wed, 7 Oct 2026 17:50:02 -0700 Subject: [PATCH 2/2] Handle project test filter edge cases Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- build.ps1 | 3 +++ helpers.build.psm1 | 23 +++++++++++++++++++---- tests/helpers.build.pester.tests.ps1 | 21 +++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/build.ps1 b/build.ps1 index 52f30f22b..2ee850d14 100755 --- a/build.ps1 +++ b/build.ps1 @@ -182,6 +182,9 @@ begin { $BuildData.Projects = $BuildData.Projects | Where-Object -FilterScript { $_.Name -in $Project } + if ($BuildData.Projects.Count -eq 0) { + throw "No projects matched the specified project names: $($Project -join ', ')" + } } $VerboseParam = @{} if ($VerbosePreference -eq 'Continue' -and -not $Quiet) { diff --git a/helpers.build.psm1 b/helpers.build.psm1 index 76c68327c..8a3c92fd2 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -2886,11 +2886,26 @@ function Test-ProjectWithPester { ErrorAction = 'Stop' } if ($Project) { - $projectPath = $Project.RelativePath + $projectPath = @($Project.RelativePath) if ($Group) { - $projectPath = $projectPath | Where-Object -FilterScript { - ($_ -split '[/\\]', 2)[0] -in $Group - } + $projectPath = @( + foreach ($path in $projectPath) { + $normalizedPath = $path -replace '\\', '/' + foreach ($testGroup in $Group) { + if ($normalizedPath -eq '.') { + $testGroup + } elseif ( + $normalizedPath -eq $testGroup -or + $normalizedPath.StartsWith("$testGroup/") + ) { + $normalizedPath + } elseif ($testGroup.StartsWith("$normalizedPath/")) { + $testGroup + } + } + } + ) | Select-Object -Unique + $projectPath = @($projectPath) } if ($projectPath.Count -eq 0) { throw 'None of the selected projects are in the specified Pester test groups.' diff --git a/tests/helpers.build.pester.tests.ps1 b/tests/helpers.build.pester.tests.ps1 index 135279cd1..42a7f5728 100644 --- a/tests/helpers.build.pester.tests.ps1 +++ b/tests/helpers.build.pester.tests.ps1 @@ -28,6 +28,17 @@ Describe 'Test-ProjectWithPester' { } } + Describe 'build.ps1 project selection' { + It 'Fails when no projects match the requested names' { + $pwsh = (Get-Process -Id $PID).Path + $output = & $pwsh -NoProfile -File (Join-Path $PSScriptRoot '..' 'build.ps1') ` + -SkipBuild -Test -ExcludeRustTests -ExcludePesterTests -Project 'does-not-exist' 2>&1 + + $LASTEXITCODE | Should -Not -Be 0 + $output -join "`n" | Should -Match 'No projects matched the specified project names: does-not-exist' + } + } + It 'Intersects selected projects with Pester test groups' { Test-ProjectWithPester -Project @($dscProject, $fileContentProject) -Group 'resources' @@ -36,6 +47,16 @@ Describe 'Test-ProjectWithPester' { } } + It 'Uses the narrower test group when the root project is selected' { + $rootProject = $buildData.Projects | Where-Object -Property Name -EQ 'root' + + Test-ProjectWithPester -Project $rootProject -Group 'resources' + + Should -Invoke Invoke-Pester -ModuleName helpers.build -Exactly 1 -ParameterFilter { + $Path.Count -eq 1 -and $Path -contains 'resources' + } + } + It 'Fails when selected projects do not belong to a Pester test group' { { Test-ProjectWithPester -Project $dscProject -Group 'resources'