A test script that fails the build
test.ps1 has been growing since the output module: it runs the suite, prints detailed results and writes both artifacts. It needs one more line before a pipeline can rely on it — the one that makes it fail.
The missing line
$config = New-PesterConfiguration
$config.Run.Path = './Planetarium'
$config.Run.Exit = $true
$config.Output.Verbosity = 'Detailed'
$config.TestResult.Enabled = $true
$config.TestResult.OutputPath = './testResults.xml'
$config.CodeCoverage.Enabled = $true
$config.CodeCoverage.Path = './Planetarium'
$config.CodeCoverage.OutputPath = './coverage.xml'
Invoke-Pester -Configuration $config
That is the finished script: run the tests, write both artifacts, exit non-zero if anything failed.
Why the exit code is the important line
A failing Pester test does not, by itself, fail your build.
By default Invoke-Pester reports failures and returns normally. Some CI systems notice the failure anyway; many do not. Whether your build goes red would depend on how the script happens to be invoked — a horrible thing to leave to chance.
Run.Exit = $true removes the guesswork: the script itself exits non-zero when tests fail, which every CI system understands. Prove both directions rather than trusting it:
pwsh -NoProfile -File ./test.ps1
$LASTEXITCODE
Tests Passed: 26, Failed: 0, Skipped: 0, Inconclusive: 0, NotRun: 0
0
Now break something on purpose — change a Should-Be 8 to Should-Be 9 — and run it again:
Tests Passed: 25, Failed: 1, Skipped: 0, Inconclusive: 0, NotRun: 0
1
Exit code 1. That is what makes CI red. Put the 8 back.
The code is in fact the number of failures — one failing test exits with 1, five with 5. Handy at a glance, though the results file is where the detail lives.
Invoke-Pester -CI is the shorthand — but not for thisPester has a -CI switch that sets exactly two things:
TestResult.Enabled = $true
Run.Exit = $true
It does not enable code coverage. Since this script wants coverage too — along with control over the output paths and verbosity — it sets those options directly instead. If you only need test results and a correct exit code, Invoke-Pester -Path ./Planetarium -CI is the one-liner version of most of this page.
It still works locally
You have been running this script since the output module, and adding Run.Exit does not change that:
./test.ps1
$LASTEXITCODE
Run.Exit is safe interactively. It ends the script rather than your session, and leaves $LASTEXITCODE behind so you can check the result.
Running the identical script locally and in CI removes an entire genre of problem — the one where a build fails remotely and cannot be reproduced because CI was doing something subtly different.
Artifacts
Two files come out of every run:
testResults.xml— NUnit format, per-test resultscoverage.xml— JaCoCo format, coverage data
Both are build output, so keep them out of version control:
testResults.xml
coverage.xml
They exist for the machine that runs the build, not for you. The next page hands them to GitHub.
Before you move on
0/6Next: setting up your CI pipeline to run our test automatically.