Files
2026-05-26 09:21:14 -04:00

123 lines
4.1 KiB
PowerShell

<#
.SYNOPSIS
Runs the ZDEW unit test suite. Used by both CI workflows and local invocation.
.DESCRIPTION
Runs `dotnet test` against each test project in the repo. Exits non-zero on
any failure. Designed to be cheap, fast, and identical between local runs
and GitHub Actions -- the workflow just calls this script.
.PARAMETER Configuration
Build configuration to test. Defaults to Debug. CI uses Debug too; there is
no Release-only test logic worth exercising.
.PARAMETER Filter
Optional dotnet test --filter expression. Examples:
.\scripts\run-tests.ps1 -Filter 'FullyQualifiedName~MaintenanceWindow'
.\scripts\run-tests.ps1 -Filter 'FullyQualifiedName~Preset_CJIS'
.PARAMETER NoLogo
Suppress dotnet's startup banner for cleaner CI logs.
.EXAMPLE
# Run all tests locally
.\scripts\run-tests.ps1
.EXAMPLE
# Run only cadence math
.\scripts\run-tests.ps1 -Filter 'FullyQualifiedName~MaintenanceWindow'
#>
param(
[string] $Configuration = 'Debug',
[string] $Filter = '',
[switch] $NoLogo,
# CI mode adds the standard CI-skip filter (SignedFilesTest tests fail in
# environments without the developer's local installer output / refreshed
# signed artifacts). Combined with -Filter if both are supplied.
[switch] $CiMode
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$repoRoot = Split-Path -Parent $PSScriptRoot
# Restore NuGet packages for the .NET Framework projects (ZitiDesktopEdge.Client,
# ZitiUpdateService, etc.) before invoking `dotnet test`. Those projects use
# packages.config with HintPaths into ..\packages\, and `dotnet test`'s implicit
# restore only covers PackageReference-style deps -- without this step the test
# build errors with "could not find Newtonsoft" / "could not find NLog". Idempotent
# (no-op once packages are present). Skipped with a warning if nuget.exe is not on
# PATH so a dev who already has packages restored can run the script without
# installing nuget.
$nuget = Get-Command nuget -ErrorAction SilentlyContinue
if ($null -eq $nuget) {
Write-Warning "nuget.exe not found on PATH; skipping package restore. If the test build fails with missing Newtonsoft.Json or NLog references, install nuget and re-run."
} else {
Write-Host "Restoring NuGet packages..."
& nuget restore (Join-Path $repoRoot 'ZitiDesktopEdge.sln') | Out-Host
if ($LASTEXITCODE -ne 0) {
Write-Error "nuget restore failed (exit $LASTEXITCODE)"
exit 1
}
}
# Discover all test projects. Convention: any csproj with name ending in `.Tests.csproj`
# under the repo root. Add new test projects without touching this script.
$testProjects = Get-ChildItem -Path $repoRoot -Filter '*.Tests.csproj' -Recurse -File |
Where-Object { $_.FullName -notmatch '\\(bin|obj)\\' }
if (-not $testProjects) {
Write-Host "No *.Tests.csproj projects found under $repoRoot"
exit 0
}
Write-Host ('=' * 70)
Write-Host "ZDEW test runner -- $($testProjects.Count) project(s)"
Write-Host ('=' * 70)
foreach ($p in $testProjects) {
$rel = $p.FullName.Substring($repoRoot.Length + 1)
Write-Host " - $rel"
}
Write-Host ''
$failed = @()
foreach ($p in $testProjects) {
$rel = $p.FullName.Substring($repoRoot.Length + 1)
Write-Host ('-' * 70)
Write-Host "Running: $rel"
Write-Host ('-' * 70)
$dotnetArgs = @('test', $p.FullName, '--configuration', $Configuration)
# Combine user-supplied filter with CI's standard skip list.
$ciSkip = 'FullyQualifiedName!~SignedFilesTest'
$effectiveFilter = if ($CiMode -and $Filter) {
"($Filter)&($ciSkip)"
} elseif ($CiMode) {
$ciSkip
} elseif ($Filter) {
$Filter
} else {
''
}
if ($effectiveFilter) { $dotnetArgs += @('--filter', $effectiveFilter) }
if ($NoLogo) { $dotnetArgs += '--nologo' }
& dotnet @dotnetArgs
if ($LASTEXITCODE -ne 0) {
$failed += $rel
}
}
Write-Host ''
Write-Host ('=' * 70)
if ($failed.Count -eq 0) {
Write-Host "All test projects passed."
exit 0
} else {
Write-Host "FAILED: $($failed.Count) test project(s):"
foreach ($f in $failed) { Write-Host " - $f" }
exit 1
}