-
-
Notifications
You must be signed in to change notification settings - Fork 808
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tests - use new Test-Config instead of constants.ps1 (#9524)
- Loading branch information
1 parent
d615e36
commit c0feb7a
Showing
716 changed files
with
5,272 additions
and
5,133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
function Get-TestConfig { | ||
param( | ||
[string]$LocalConfigPath = "$script:PSModuleRoot/tests/constants.local.ps1" | ||
) | ||
$config = [ordered]@{} | ||
|
||
if (Test-Path $LocalConfigPath) { | ||
Write-Host "Tests will use local constants file: tests\constants.local.ps1." -ForegroundColor Cyan | ||
. $LocalConfigPath | ||
# Note: Local constants are sourced but not explicitly added to $config | ||
} elseif ($env:CODESPACES -and ($env:TERM_PROGRAM -eq 'vscode' -and $env:REMOTE_CONTAINERS)) { | ||
$config['Instance1'] = "dbatools1" | ||
$config['Instance2'] = "dbatools2" | ||
$config['Instance3'] = "dbatools3" | ||
$config['Instances'] = @($config['Instance1'], $config['Instance2']) | ||
|
||
$config['SqlCred'] = [PSCredential]::new('sa', (ConvertTo-SecureString $env:SA_PASSWORD -AsPlainText -Force)) | ||
$config['PSDefaultParameterValues'] = @{ | ||
"*:SqlCredential" = $config['SqlCred'] | ||
} | ||
} elseif ($env:GITHUB_WORKSPACE) { | ||
$config['DbaToolsCi_Computer'] = "localhost" | ||
$config['Instance1'] = "localhost" | ||
$config['Instance2'] = "localhost:14333" | ||
$config['Instance2SQLUserName'] = $null # placeholders for -SqlCredential testing | ||
$config['Instance2SQLPassword'] = $null | ||
$config['Instance3'] = "localhost" | ||
$config['Instance2_Detailed'] = "localhost,14333" # Just to make sure things parse a port properly | ||
$config['AppveyorLabRepo'] = "/tmp/appveyor-lab" | ||
$config['Instances'] = @($config['Instance1'], $config['Instance2']) | ||
$config['SsisServer'] = "localhost\sql2016" | ||
$config['AzureBlob'] = "https://dbatools.blob.core.windows.net/sql" | ||
$config['AzureBlobAccount'] = "dbatools" | ||
$config['AzureServer'] = 'psdbatools.database.windows.net' | ||
$config['AzureSqlDbLogin'] = "[email protected]" | ||
} else { | ||
$config['DbaToolsCi_Computer'] = "localhost" | ||
$config['Instance1'] = "localhost\sql2008r2sp2" | ||
$config['Instance2'] = "localhost\sql2016" | ||
$config['Instance2SQLUserName'] = $null # placeholders for -SqlCredential testing | ||
$config['Instance2SQLPassword'] = $null | ||
$config['Instance3'] = "localhost\sql2017" | ||
$config['Instance2_Detailed'] = "localhost,14333\sql2016" # Just to make sure things parse a port properly | ||
$config['AppveyorLabRepo'] = "C:\github\appveyor-lab" | ||
$config['Instances'] = @($config['Instance1'], $config['Instance2']) | ||
$config['SsisServer'] = "localhost\sql2016" | ||
$config['AzureBlob'] = "https://dbatools.blob.core.windows.net/sql" | ||
$config['AzureBlobAccount'] = "dbatools" | ||
$config['AzureServer'] = 'psdbatools.database.windows.net' | ||
$config['AzureSqlDbLogin'] = "[email protected]" | ||
$config['BigDatabaseBackup'] = 'C:\github\StackOverflowMini.bak' | ||
$config['BigDatabaseBackupSourceUrl'] = 'https://github.com/BrentOzarULTD/Stack-Overflow-Database/releases/download/20230114/StackOverflowMini.bak' | ||
} | ||
|
||
if ($env:appveyor) { | ||
$config['PSDefaultParameterValues'] = @{ | ||
'*:WarningAction' = 'SilentlyContinue' | ||
} | ||
} | ||
|
||
[pscustomobject]$config | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
function Invoke-ManualPester { | ||
<# | ||
.SYNOPSIS | ||
Runs dbatools tests. | ||
.DESCRIPTION | ||
This is an helper to automate running tests locally | ||
.PARAMETER Path | ||
The Path to the test files to run. It accepts multiple test file paths passed in (e.g. .\Find-DbaOrphanedFile.Tests.ps1) as well | ||
as simple strings (e.g. "orphaned" will run all files matching .\*orphaned*.Tests.ps1) | ||
.PARAMETER Show | ||
Gets passed down to Pester's -Show parameter (useful if you want to reduce verbosity) | ||
.PARAMETER PassThru | ||
Gets passed down to Pester's -PassThru parameter (useful if you want to return an object to analyze) | ||
.PARAMETER TestIntegration | ||
dbatools's suite has unittests and integrationtests. This switch enables IntegrationTests, which need live instances | ||
see constants.ps1 for customizations | ||
.PARAMETER Coverage | ||
Enables measuring code coverage on the tested function | ||
.PARAMETER DependencyCoverage | ||
Enables measuring code coverage also of "lower level" (i.e. called) functions | ||
.PARAMETER ScriptAnalyzer | ||
Enables checking the called function's code with Invoke-ScriptAnalyzer, with dbatools's profile | ||
.EXAMPLE | ||
Invoke-ManualPester -Path Find-DbaOrphanedFile.Tests.ps1 -TestIntegration -Coverage -DependencyCoverage -ScriptAnalyzer | ||
The most complete number of checks: | ||
- Runs both unittests and integrationtests | ||
- Gathers and shows code coverage measurement for Find-DbaOrphanedFile and all its dependencies | ||
- Checks Find-DbaOrphanedFile with Invoke-ScriptAnalyzer | ||
.EXAMPLE | ||
Invoke-ManualPester -Path Find-DbaOrphanedFile.Tests.ps1 | ||
Runs unittests stored in Find-DbaOrphanedFile.Tests.ps1 | ||
.EXAMPLE | ||
Invoke-ManualPester -Path Find-DbaOrphanedFile.Tests.ps1 -PassThru | ||
Runs unittests stored in Find-DbaOrphanedFile.Tests.ps1 and returns an object that can be analyzed | ||
.EXAMPLE | ||
Invoke-ManualPester -Path orphan | ||
Runs unittests for all tests matching in `*orphan*.Tests.ps1 | ||
.EXAMPLE | ||
Invoke-ManualPester -Path Find-DbaOrphanedFile.Tests.ps1 -Show Default | ||
Runs unittests stored in Find-DbaOrphanedFile.Tests.ps1, with reduced verbosity | ||
.EXAMPLE | ||
Invoke-ManualPester -Path Find-DbaOrphanedFile.Tests.ps1 -TestIntegration | ||
Runs both unittests and integrationtests stored in Find-DbaOrphanedFile.Tests.ps1 | ||
.EXAMPLE | ||
Invoke-ManualPester -Path Find-DbaOrphanedFile.Tests.ps1 -TestIntegration -Coverage | ||
Gathers and shows code coverage measurement for Find-DbaOrphanedFile | ||
.EXAMPLE | ||
Invoke-ManualPester -Path Find-DbaOrphanedFile.Tests.ps1 -TestIntegration -Coverage -DependencyCoverage | ||
Gathers and shows code coverage measurement for Find-DbaOrphanedFile and all its dependencies | ||
#> | ||
|
||
[CmdletBinding()] | ||
param ( | ||
[Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)] | ||
[Alias('FullName')] | ||
[string[]]$Path, | ||
[ValidateSet('None', 'Default', 'Passed', 'Failed', 'Pending', 'Skipped', 'Inconclusive', 'Describe', 'Context', 'Summary', 'Header', 'All', 'Fails')] | ||
[string]$Show = "All", | ||
[switch]$PassThru, | ||
[switch]$TestIntegration, | ||
[switch]$Coverage, | ||
[switch]$DependencyCoverage, | ||
[switch]$ScriptAnalyzer | ||
) | ||
|
||
<# | ||
Remove-Module -Name Pester | ||
Import-Module -name Pester -MaximumVersion 4.* | ||
#> | ||
|
||
$invokeFormatterVersion = (Get-Command Invoke-Formatter -ErrorAction SilentlyContinue).Version | ||
$HasScriptAnalyzer = $null -ne $invokeFormatterVersion | ||
$MinimumPesterVersion = [Version] '3.4.5.0' # Because this is when -Show was introduced | ||
$MaximumPesterVersion = [Version] '5.0.0.0' # Because our tests (and runners) are only compatible with 4.* | ||
$PesterVersion = (Get-Command Invoke-Pester -ErrorAction SilentlyContinue).Version | ||
$HasPester = $null -ne $PesterVersion | ||
$ScriptAnalyzerCorrectVersion = '1.18.2' | ||
|
||
if (!($HasScriptAnalyzer)) { | ||
Write-Warning "Please install PSScriptAnalyzer" | ||
Write-Warning " Install-Module -Name PSScriptAnalyzer -RequiredVersion '$ScriptAnalyzerCorrectVersion'" | ||
Write-Warning " or go to https://github.com/PowerShell/PSScriptAnalyzer" | ||
} else { | ||
if ($invokeFormatterVersion -ne $ScriptAnalyzerCorrectVersion) { | ||
Remove-Module PSScriptAnalyzer | ||
try { | ||
Import-Module PSScriptAnalyzer -RequiredVersion $ScriptAnalyzerCorrectVersion -ErrorAction Stop | ||
} catch { | ||
Write-Warning "Please install PSScriptAnalyzer $ScriptAnalyzerCorrectVersion" | ||
Write-Warning " Install-Module -Name PSScriptAnalyzer -RequiredVersion '$ScriptAnalyzerCorrectVersion'" | ||
} | ||
} | ||
} | ||
if (!($HasPester)) { | ||
Write-Warning "Please install Pester" | ||
Write-Warning " Install-Module -Name Pester -Force -SkipPublisherCheck" | ||
Write-Warning " or go to https://github.com/pester/Pester" | ||
} | ||
if ($PesterVersion -lt $MinimumPesterVersion) { | ||
Write-Warning "Please update Pester to at least 3.4.5" | ||
Write-Warning " Install-Module -Name Pester -MaximumVersion '4.10' -Force -SkipPublisherCheck" | ||
Write-Warning " or go to https://github.com/pester/Pester" | ||
} | ||
if ($PesterVersion -gt $MaximumPesterVersion) { | ||
Write-Warning "Please get Pester to the 4.* release" | ||
Write-Warning " Install-Module -Name Pester -MaximumVersion '4.10' -Force -SkipPublisherCheck" | ||
Write-Warning " or go to https://github.com/pester/Pester" | ||
} | ||
|
||
if (($HasPester -and $HasScriptAnalyzer -and ($PesterVersion -ge $MinimumPesterVersion) -and ($PesterVersion -lt $MaximumPesterVersion) -and ($invokeFormatterVersion -eq $ScriptAnalyzerCorrectVersion)) -eq $false) { | ||
Write-Warning "Exiting..." | ||
return | ||
} | ||
|
||
$ModuleBase = Split-Path -Path $PSScriptRoot -Parent | ||
|
||
if (-not(Test-Path "$ModuleBase\.git" -Type Container)) { | ||
New-Item -Type Container -Path "$ModuleBase\.git" -Force | ||
} | ||
|
||
#removes previously imported dbatools, if any | ||
# No need the force will do it | ||
# Remove-Module dbatools -ErrorAction Ignore | ||
#imports the module making sure DLL is loaded ok | ||
Import-Module "$ModuleBase\dbatools.psd1" -DisableNameChecking -Force | ||
#imports the psm1 to be able to use internal functions in tests | ||
Import-Module "$ModuleBase\dbatools.psm1" -DisableNameChecking -Force | ||
|
||
$ScriptAnalyzerRulesExclude = @('PSUseOutputTypeCorrectly', 'PSAvoidUsingPlainTextForPassword', 'PSUseBOMForUnicodeEncodedFile') | ||
|
||
$testInt = $false | ||
if ($config_TestIntegration) { | ||
$testInt = $true | ||
} | ||
if ($TestIntegration) { | ||
$testInt = $true | ||
} | ||
|
||
function Get-CoverageIndications($Path, $ModuleBase) { | ||
# takes a test file path and figures out what to analyze for coverage (i.e. dependencies) | ||
$CBHRex = [regex]'(?smi)<#(.*)#>' | ||
$everything = (Get-Module dbatools).ExportedCommands.Values | ||
$everyfunction = $everything.Name | ||
$funcs = @() | ||
$leaf = Split-Path $path -Leaf | ||
# assuming Get-DbaFoo.Tests.ps1 wants coverage for "Get-DbaFoo" | ||
# but allowing also Get-DbaFoo.one.Tests.ps1 and Get-DbaFoo.two.Tests.ps1 | ||
$func_name += ($leaf -replace '^([^.]+)(.+)?.Tests.ps1', '$1') | ||
if ($func_name -in $everyfunction) { | ||
$funcs += $func_name | ||
$f = $everything | Where-Object Name -eq $func_name | ||
$source = $f.Definition | ||
$CBH = $CBHRex.match($source).Value | ||
$cmdonly = $source.Replace($CBH, '') | ||
foreach ($e in $everyfunction) { | ||
# hacky, I know, but every occurrence of any function plus a space kinda denotes usage !? | ||
$searchme = "$e " | ||
if ($cmdonly.contains($searchme)) { | ||
$funcs += $e | ||
} | ||
} | ||
} | ||
$testpaths = @() | ||
$allfiles = Get-ChildItem -File -Path "$ModuleBase\private\functions", "$ModuleBase\public" -Filter '*.ps1' | ||
foreach ($f in $funcs) { | ||
# exclude always used functions ?! | ||
if ($f -in ('Connect-DbaInstance', 'Select-DefaultView', 'Stop-Function', 'Write-Message')) { continue } | ||
# can I find a correspondence to a physical file (again, on the convenience of having Get-DbaFoo.ps1 actually defining Get-DbaFoo)? | ||
$res = $allfiles | Where-Object { $_.Name.Replace('.ps1', '') -eq $f } | ||
if ($res.count -gt 0) { | ||
$testpaths += $res.FullName | ||
} | ||
} | ||
return @() + ($testpaths | Select-Object -Unique) | ||
} | ||
|
||
$files = @() | ||
|
||
if ($Path) { | ||
foreach ($item in $path) { | ||
if (Test-Path $item) { | ||
$files += Get-ChildItem -Path $item | ||
} else { | ||
$files += Get-ChildItem -Path "$ModuleBase\tests\*$item*.Tests.ps1" | ||
} | ||
} | ||
} | ||
|
||
if ($files.Length -eq 0) { | ||
Write-Warning "No tests to be run" | ||
} | ||
|
||
$AllTestsWithinScenario = $files | ||
|
||
foreach ($f in $AllTestsWithinScenario) { | ||
$PesterSplat = @{ | ||
'Script' = $f.FullName | ||
'Show' = $show | ||
'PassThru' = $passThru | ||
} | ||
#opt-in | ||
$HeadFunctionPath = $f.FullName | ||
|
||
if ($Coverage -or $ScriptAnalyzer) { | ||
$CoverFiles = Get-CoverageIndications -Path $f -ModuleBase $ModuleBase | ||
$HeadFunctionPath = $CoverFiles | Select-Object -First 1 | ||
} | ||
if ($Coverage) { | ||
if ($DependencyCoverage) { | ||
$CoverFilesPester = $CoverFiles | ||
} else { | ||
$CoverFilesPester = $HeadFunctionPath | ||
} | ||
$PesterSplat['CodeCoverage'] = $CoverFilesPester | ||
} | ||
if (!($testInt)) { | ||
$PesterSplat['ExcludeTag'] = "IntegrationTests" | ||
} | ||
Invoke-Pester @PesterSplat | ||
if ($ScriptAnalyzer) { | ||
if ($Show -ne "None") { | ||
Write-Host -ForegroundColor green -Object "ScriptAnalyzer check for $HeadFunctionPath" | ||
} | ||
Invoke-ScriptAnalyzer -Path $HeadFunctionPath -ExcludeRule $ScriptAnalyzerRulesExclude | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.