Skip to content

Commit 80af904

Browse files
Invoke-ManualPester - Check the test file and the repository style gate (#10518)
1 parent d428777 commit 80af904

11 files changed

Lines changed: 774 additions & 153 deletions

.github/CONTRIBUTING-TESTING.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,16 +329,33 @@ Invoke-ManualPester -Path Get-DbaDatabase -TestIntegration -Coverage
329329
# Run with full coverage including dependencies
330330
Invoke-ManualPester -Path Get-DbaDatabase -TestIntegration -Coverage -DependencyCoverage
331331
332-
# Run with script analyzer check
332+
# Run with script analyzer check on the test file and the command
333333
Invoke-ManualPester -Path Get-DbaDatabase -TestIntegration -ScriptAnalyzer
334334
335+
# Run the repository wide style checks that CI enforces
336+
Invoke-ManualPester -Path Get-DbaDatabase -TestIntegration -Compliance
337+
335338
# Run multiple tests matching a pattern
336339
Invoke-ManualPester -Path "*Backup*" -TestIntegration
337340
338341
# Show less output
339342
Invoke-ManualPester -Path Get-DbaDatabase -TestIntegration -Show None
340343
```
341344

345+
### Before opening a pull request
346+
347+
`Invoke-ManualPester -Path <command>` runs only that command's test file. Two of the checks CI runs
348+
belong to no command's test file at all, so a green run of it says nothing about them:
349+
350+
| Switch | What it adds |
351+
|---|---|
352+
| `-ScriptAnalyzer` | Checks the test file and the command under test against [tests/PSScriptAnalyzerRules.psd1](../tests/PSScriptAnalyzerRules.psd1), the repository style profile. |
353+
| `-Compliance` | Runs the `Compliance` tagged tests from [tests/dbatools.Tests.ps1](../tests/dbatools.Tests.ps1) over the whole repository: no UTF-8 BOM, no tabs, no trailing spaces, no ScriptAnalyzer errors. Takes about half a minute. |
354+
355+
```powershell
356+
Invoke-ManualPester -Path Get-DbaDatabase -TestIntegration -ScriptAnalyzer -Compliance
357+
```
358+
342359
### Method 2: Direct Pester Invocation
343360

344361
```powershell
@@ -568,6 +585,7 @@ Invoke-ManualPester -Path "*Backup*" -TestIntegration
568585
| [tests/constants.local.ps1.example](../tests/constants.local.ps1.example) | Template for local config |
569586
| [private/testing/Get-TestConfig.ps1](../private/testing/Get-TestConfig.ps1) | Loads test configuration |
570587
| [private/testing/Invoke-ManualPester.ps1](../private/testing/Invoke-ManualPester.ps1) | Local test runner helper |
588+
| [private/testing/Get-TestInstanceUsage.ps1](../private/testing/Get-TestInstanceUsage.ps1) | Reports which `$TestConfig` instances a test file uses, and therefore which CI lane it runs in |
571589
| [tests/pester.groups.ps1](../tests/pester.groups.ps1) | Scenario definitions |
572590
| [tests/appveyor.common.ps1](../tests/appveyor.common.ps1) | CI test discovery logic |
573591
| [tests/CLAUDE.md](../tests/CLAUDE.md) | Ongoing test policy and Pester 6 standards |

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
- [ ] Bug fix (non-breaking change, fixes #<!--issue number--> )
55
- [ ] New feature (non-breaking change, adds functionality, fixes #<!--issue number--> )
66
- [ ] Breaking change (affects multiple commands or functionality, fixes #<!--issue number--> )
7-
- [ ] Ran manual Pester test and has passed (`Invoke-ManualPester`)
7+
- [ ] Ran manual Pester test and has passed (`Invoke-ManualPester -Path <command> -ScriptAnalyzer -Compliance`)
88
- [ ] Adding code coverage to existing functionality
99
- [ ] Pester test is included
1010
- [ ] If new file reference added for test, has is been added to github.com/dataplat/appveyor-lab ?
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
function Get-TestInstanceUsage {
2+
<#
3+
.SYNOPSIS
4+
Reports which $TestConfig instances each test file uses.
5+
6+
.DESCRIPTION
7+
tests\pester.groups.ps1 assigns a test file to a CI scenario by autodetecting which
8+
$TestConfig.Instance* variable the file references, so this is what decides which lane a test
9+
runs in - and the lanes are not equally available. Only InstanceSingle, InstanceMulti1 and
10+
InstanceMulti2 exist on GitHub Actions; a test written against InstanceCopy, InstanceHadr or
11+
InstanceRestart runs on the Azure runners only.
12+
13+
Use it to see which lane a change lands in before writing the test, or to find every test that
14+
a given instance would affect.
15+
16+
Commented out code is ignored, so a reference left behind in a comment does not move a file
17+
into a scenario it does not belong to.
18+
19+
.PARAMETER Path
20+
The folder holding the test files. Defaults to the tests folder of this working copy.
21+
22+
.PARAMETER Command
23+
Only report the test files of these commands. Wildcards are supported. Defaults to all of them.
24+
25+
.EXAMPLE
26+
Get-TestInstanceUsage
27+
28+
Reports the instances used by every test file.
29+
30+
.EXAMPLE
31+
Get-TestInstanceUsage -Command Get-DbaDb*
32+
33+
Reports the instances used by the test files of every command starting with Get-DbaDb.
34+
35+
.EXAMPLE
36+
Get-TestInstanceUsage | Group-Object -Property InstanceList -NoElement | Sort-Object -Property Count -Descending
37+
38+
Shows how many test files use each combination of instances.
39+
40+
.EXAMPLE
41+
Get-TestInstanceUsage | Where-Object Instances -contains "Hadr"
42+
43+
Lists every test that needs the availability group instance, which only the Azure runners have.
44+
#>
45+
[CmdletBinding()]
46+
param (
47+
[string]$Path = (Join-Path (Split-Path -Path $PSScriptRoot -Parent | Split-Path -Parent) "tests"),
48+
[string[]]$Command = "*"
49+
)
50+
51+
foreach ($commandName in $Command) {
52+
$testFiles = Get-ChildItem -Path "$Path\$commandName.Tests.ps1" -ErrorAction SilentlyContinue | Sort-Object -Property Name
53+
if (-not $testFiles) {
54+
Write-Warning -Message "No test file found for [$commandName]"
55+
continue
56+
}
57+
58+
foreach ($testFile in $testFiles) {
59+
$content = Get-Content -Path $testFile.FullName
60+
# This matches the current names ($TestConfig.InstanceSingle, $TestConfig.InstanceMulti1
61+
# and so on) as well as the legacy $TestConfig.instance1, because both spellings still
62+
# appear in the autodetection in pester.groups.ps1.
63+
$instanceNames = foreach ($line in $content) {
64+
$code = $line -replace "#.*$", ""
65+
[regex]::Matches($code, "\`$TestConfig\.Instance(\w+)", [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) |
66+
ForEach-Object { $PSItem.Groups[1].Value }
67+
}
68+
$instanceNames = @($instanceNames | Sort-Object -Unique)
69+
70+
[PSCustomObject]@{
71+
Command = $testFile.Name -replace "\.Tests\.ps1$", ""
72+
TestFileName = $testFile.Name
73+
Instances = $instanceNames
74+
# A single string as well, so that the result can be grouped on it directly
75+
InstanceList = $instanceNames -join " "
76+
}
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)