microsoft/hve-core

Public

mirrored fromhttps://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
e69486a5f809ede45c63c0a31358c12912bd5168

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

scripts/tests/Get-ChangedTestFiles.Tests.ps1

315lines · modecode

1#Requires -Modules Pester
2# Copyright (c) Microsoft Corporation.
3# SPDX-License-Identifier: MIT
4<#
5.SYNOPSIS
6 Pester tests for Get-ChangedTestFiles.ps1 script
7.DESCRIPTION
8 Tests for changed PowerShell file detection and test path resolution:
9 - Empty diff returns no changes
10 - Source file with matching test resolves correctly
11 - Source file without matching test returns empty
12 - Directly changed test files are included
13 - Skill directory discovery at depth 1 and 2
14 - No skills directory handles gracefully
15 - Deduplication of discovered test paths
16 - Git diff failure returns no changes
17#>
18
19BeforeAll {
20 $script:ScriptPath = Join-Path $PSScriptRoot 'Get-ChangedTestFiles.ps1'
21 $script:CIHelpersPath = Join-Path $PSScriptRoot '../lib/Modules/CIHelpers.psm1'
22
23 # Import modules for mocking
24 Import-Module $script:CIHelpersPath -Force
25
26 # Dot-source the script to access Get-ChangedTestFilesCore
27 . $script:ScriptPath
28}
29
30AfterAll {
31 Remove-Module CIHelpers -Force -ErrorAction SilentlyContinue
32}
33
34Describe 'Get-ChangedTestFiles' -Tag 'Unit' {
35
36 Context 'Empty diff returns no changes' {
37 BeforeEach {
38 Mock git {
39 $global:LASTEXITCODE = 0
40 return @()
41 } -ParameterFilter { $args[0] -eq 'diff' }
42 }
43
44 It 'Returns HasChanges as false' {
45 $result = Get-ChangedTestFilesCore -BaseBranch 'main'
46 $result.HasChanges | Should -BeFalse
47 }
48
49 It 'Returns empty TestPaths' {
50 $result = Get-ChangedTestFilesCore -BaseBranch 'main'
51 $result.TestPaths | Should -BeNullOrEmpty
52 }
53
54 It 'Returns empty ChangedFiles' {
55 $result = Get-ChangedTestFilesCore -BaseBranch 'main'
56 $result.ChangedFiles | Should -BeNullOrEmpty
57 }
58 }
59
60 Context 'Source file with matching test' {
61 BeforeEach {
62 $script:TempDir = Join-Path ([System.IO.Path]::GetTempPath()) "pester-$([Guid]::NewGuid().ToString('N').Substring(0,8))"
63 $testDir = Join-Path $script:TempDir 'scripts/tests'
64 New-Item -ItemType Directory -Path $testDir -Force | Out-Null
65 New-Item -ItemType File -Path (Join-Path $testDir 'MyScript.Tests.ps1') -Force | Out-Null
66
67 Mock git {
68 $global:LASTEXITCODE = 0
69 return @('scripts/linting/MyScript.ps1')
70 } -ParameterFilter { $args[0] -eq 'diff' }
71 }
72
73 AfterEach {
74 Remove-Item -Path $script:TempDir -Recurse -Force -ErrorAction SilentlyContinue
75 }
76
77 It 'Resolves matching test file path' {
78 $result = Get-ChangedTestFilesCore -BaseBranch 'main' -TestRoot (Join-Path $script:TempDir 'scripts/tests')
79 $result.TestPaths | Should -HaveCount 1
80 $result.TestPaths[0] | Should -BeLike '*MyScript.Tests.ps1'
81 }
82
83 It 'Sets HasChanges to true' {
84 $result = Get-ChangedTestFilesCore -BaseBranch 'main' -TestRoot (Join-Path $script:TempDir 'scripts/tests')
85 $result.HasChanges | Should -BeTrue
86 }
87 }
88
89 Context 'Source file without matching test' {
90 BeforeEach {
91 $script:TempDir = Join-Path ([System.IO.Path]::GetTempPath()) "pester-$([Guid]::NewGuid().ToString('N').Substring(0,8))"
92 $testDir = Join-Path $script:TempDir 'scripts/tests'
93 New-Item -ItemType Directory -Path $testDir -Force | Out-Null
94
95 Mock git {
96 $global:LASTEXITCODE = 0
97 return @('scripts/linting/NoTestScript.ps1')
98 } -ParameterFilter { $args[0] -eq 'diff' }
99 }
100
101 AfterEach {
102 Remove-Item -Path $script:TempDir -Recurse -Force -ErrorAction SilentlyContinue
103 }
104
105 It 'Returns HasChanges as false when no test found' {
106 $result = Get-ChangedTestFilesCore -BaseBranch 'main' -TestRoot (Join-Path $script:TempDir 'scripts/tests')
107 $result.HasChanges | Should -BeFalse
108 }
109
110 It 'Returns empty TestPaths' {
111 $result = Get-ChangedTestFilesCore -BaseBranch 'main' -TestRoot (Join-Path $script:TempDir 'scripts/tests')
112 $result.TestPaths | Should -BeNullOrEmpty
113 }
114 }
115
116 Context 'Directly changed test file included' {
117 BeforeEach {
118 $script:TempDir = Join-Path ([System.IO.Path]::GetTempPath()) "pester-$([Guid]::NewGuid().ToString('N').Substring(0,8))"
119 $testDir = Join-Path $script:TempDir 'scripts/tests'
120 New-Item -ItemType Directory -Path $testDir -Force | Out-Null
121 New-Item -ItemType File -Path (Join-Path $testDir 'SomeScript.Tests.ps1') -Force | Out-Null
122
123 Mock git {
124 $global:LASTEXITCODE = 0
125 return @('scripts/tests/SomeScript.Tests.ps1')
126 } -ParameterFilter { $args[0] -eq 'diff' }
127 }
128
129 AfterEach {
130 Remove-Item -Path $script:TempDir -Recurse -Force -ErrorAction SilentlyContinue
131 }
132
133 It 'Includes directly changed test files' {
134 Push-Location $script:TempDir
135 try {
136 $result = Get-ChangedTestFilesCore -BaseBranch 'main' -TestRoot (Join-Path $script:TempDir 'scripts/tests')
137 $result.TestPaths | Should -HaveCount 1
138 $result.TestPaths[0] | Should -BeLike '*SomeScript.Tests.ps1'
139 }
140 finally {
141 Pop-Location
142 }
143 }
144 }
145
146 Context 'Skill directory discovery at depth 1' {
147 BeforeEach {
148 $script:TempDir = Join-Path ([System.IO.Path]::GetTempPath()) "pester-$([Guid]::NewGuid().ToString('N').Substring(0,8))"
149
150 $testRoot = Join-Path $script:TempDir 'scripts/tests'
151 New-Item -ItemType Directory -Path $testRoot -Force | Out-Null
152
153 $skillDir = Join-Path $script:TempDir '.github/skills/collection1'
154 New-Item -ItemType Directory -Path (Join-Path $skillDir 'tests') -Force | Out-Null
155 New-Item -ItemType Directory -Path (Join-Path $skillDir 'scripts') -Force | Out-Null
156 New-Item -ItemType File -Path (Join-Path $skillDir 'tests/SkillScript.Tests.ps1') -Force | Out-Null
157
158 Mock git {
159 $global:LASTEXITCODE = 0
160 return @('.github/skills/collection1/scripts/SkillScript.ps1')
161 } -ParameterFilter { $args[0] -eq 'diff' }
162 }
163
164 AfterEach {
165 Remove-Item -Path $script:TempDir -Recurse -Force -ErrorAction SilentlyContinue
166 }
167
168 It 'Discovers test files in skill directories at depth 1' {
169 $result = Get-ChangedTestFilesCore -BaseBranch 'main' `
170 -TestRoot (Join-Path $script:TempDir 'scripts/tests') `
171 -SkillsRoot (Join-Path $script:TempDir '.github/skills')
172 $result.HasChanges | Should -BeTrue
173 $result.TestPaths | Should -HaveCount 1
174 $result.TestPaths[0] | Should -BeLike '*SkillScript.Tests.ps1'
175 }
176 }
177
178 Context 'Skill directory discovery at depth 2' {
179 BeforeEach {
180 $script:TempDir = Join-Path ([System.IO.Path]::GetTempPath()) "pester-$([Guid]::NewGuid().ToString('N').Substring(0,8))"
181
182 $testRoot = Join-Path $script:TempDir 'scripts/tests'
183 New-Item -ItemType Directory -Path $testRoot -Force | Out-Null
184
185 $skillDir = Join-Path $script:TempDir '.github/skills/collection1/skill1'
186 New-Item -ItemType Directory -Path (Join-Path $skillDir 'tests') -Force | Out-Null
187 New-Item -ItemType Directory -Path (Join-Path $skillDir 'scripts') -Force | Out-Null
188 New-Item -ItemType File -Path (Join-Path $skillDir 'tests/DeepSkillScript.Tests.ps1') -Force | Out-Null
189
190 Mock git {
191 $global:LASTEXITCODE = 0
192 return @('.github/skills/collection1/skill1/scripts/DeepSkillScript.ps1')
193 } -ParameterFilter { $args[0] -eq 'diff' }
194 }
195
196 AfterEach {
197 Remove-Item -Path $script:TempDir -Recurse -Force -ErrorAction SilentlyContinue
198 }
199
200 It 'Discovers test files in skill directories at depth 2' {
201 $result = Get-ChangedTestFilesCore -BaseBranch 'main' `
202 -TestRoot (Join-Path $script:TempDir 'scripts/tests') `
203 -SkillsRoot (Join-Path $script:TempDir '.github/skills')
204 $result.HasChanges | Should -BeTrue
205 $result.TestPaths | Should -HaveCount 1
206 $result.TestPaths[0] | Should -BeLike '*DeepSkillScript.Tests.ps1'
207 }
208 }
209
210 Context 'No skills directory handles gracefully' {
211 BeforeEach {
212 $script:TempDir = Join-Path ([System.IO.Path]::GetTempPath()) "pester-$([Guid]::NewGuid().ToString('N').Substring(0,8))"
213 $testDir = Join-Path $script:TempDir 'scripts/tests'
214 New-Item -ItemType Directory -Path $testDir -Force | Out-Null
215 New-Item -ItemType File -Path (Join-Path $testDir 'MyScript.Tests.ps1') -Force | Out-Null
216
217 Mock git {
218 $global:LASTEXITCODE = 0
219 return @('scripts/linting/MyScript.ps1')
220 } -ParameterFilter { $args[0] -eq 'diff' }
221 }
222
223 AfterEach {
224 Remove-Item -Path $script:TempDir -Recurse -Force -ErrorAction SilentlyContinue
225 }
226
227 It 'Works when skills directory does not exist' {
228 $result = Get-ChangedTestFilesCore -BaseBranch 'main' `
229 -TestRoot (Join-Path $script:TempDir 'scripts/tests') `
230 -SkillsRoot (Join-Path $script:TempDir 'nonexistent/skills')
231 $result.HasChanges | Should -BeTrue
232 $result.TestPaths | Should -HaveCount 1
233 }
234 }
235
236 Context 'Deduplication of discovered test paths' {
237 BeforeEach {
238 $script:TempDir = Join-Path ([System.IO.Path]::GetTempPath()) "pester-$([Guid]::NewGuid().ToString('N').Substring(0,8))"
239 $testDir = Join-Path $script:TempDir 'scripts/tests'
240 New-Item -ItemType Directory -Path $testDir -Force | Out-Null
241 New-Item -ItemType File -Path (Join-Path $testDir 'Shared.Tests.ps1') -Force | Out-Null
242
243 Mock git {
244 $global:LASTEXITCODE = 0
245 return @('scripts/linting/Shared.ps1', 'scripts/extension/Shared.ps1')
246 } -ParameterFilter { $args[0] -eq 'diff' }
247 }
248
249 AfterEach {
250 Remove-Item -Path $script:TempDir -Recurse -Force -ErrorAction SilentlyContinue
251 }
252
253 It 'Returns unique test paths only' {
254 $result = Get-ChangedTestFilesCore -BaseBranch 'main' -TestRoot (Join-Path $script:TempDir 'scripts/tests') -SkillsRoot (Join-Path $script:TempDir 'nonexistent/skills')
255 $result.TestPaths | Should -HaveCount 1
256 }
257 }
258
259 Context 'Git diff failure' {
260 BeforeEach {
261 Mock git {
262 $global:LASTEXITCODE = 128
263 return 'fatal: bad object'
264 } -ParameterFilter { $args[0] -eq 'diff' }
265 }
266
267 It 'Returns no changes when git diff fails' {
268 $result = Get-ChangedTestFilesCore -BaseBranch 'main'
269 $result.HasChanges | Should -BeFalse
270 $result.TestPaths | Should -BeNullOrEmpty
271 }
272 }
273
274 Context 'Script guard execution' {
275 BeforeEach {
276 $script:TempDir = Join-Path ([System.IO.Path]::GetTempPath()) "pester-$([Guid]::NewGuid().ToString('N').Substring(0,8))"
277 $testDir = Join-Path $script:TempDir 'scripts/tests'
278 New-Item -ItemType Directory -Path $testDir -Force | Out-Null
279 New-Item -ItemType File -Path (Join-Path $testDir 'MyScript.Tests.ps1') -Force | Out-Null
280
281 $script:EnvFile = Join-Path $script:TempDir 'github_env'
282 New-Item -ItemType File -Path $script:EnvFile -Force | Out-Null
283 $env:GITHUB_ENV = $script:EnvFile
284 $env:GITHUB_ACTIONS = 'true'
285
286 Mock git {
287 $global:LASTEXITCODE = 0
288 return @('scripts/linting/MyScript.ps1')
289 } -ParameterFilter { $args[0] -eq 'diff' }
290 }
291
292 AfterEach {
293 $env:GITHUB_ENV = $null
294 $env:GITHUB_ACTIONS = $null
295 Remove-Item -Path $script:TempDir -Recurse -Force -ErrorAction SilentlyContinue
296 }
297
298 It 'Throws when BaseBranch is not provided' {
299 { & $script:ScriptPath } | Should -Throw '*BaseBranch*'
300 }
301
302 It 'Writes HAS_CHANGES to GITHUB_ENV' {
303 & $script:ScriptPath -BaseBranch 'main' -TestRoot (Join-Path $script:TempDir 'scripts/tests') -SkillsRoot (Join-Path $script:TempDir 'nonexistent')
304 $content = Get-Content $script:EnvFile -Raw
305 $content | Should -Match 'HAS_CHANGES'
306 $content | Should -Match 'True'
307 }
308
309 It 'Writes TEST_PATHS to GITHUB_ENV' {
310 & $script:ScriptPath -BaseBranch 'main' -TestRoot (Join-Path $script:TempDir 'scripts/tests') -SkillsRoot (Join-Path $script:TempDir 'nonexistent')
311 $content = Get-Content $script:EnvFile -Raw
312 $content | Should -Match 'TEST_PATHS'
313 }
314 }
315}
316