Contributing¶
Thanks for taking an interest in improving FogApi! This page covers how the branching/release flow works and how the Pester test suite is organized, so you know what to expect from a PR.
Git flow¶
- Always branch from
dev, notmaster. - Feature/fix branches target
devin their pull requests. devgets merged intomastervia PR, and that merge is what triggerstag-and-release.yml- it bumps the module version, rebuilds the docs, and publishes to the PowerShell Gallery and Chocolatey. Onlydevis allowed to merge intomaster- a PR intomasterfrom anywhere else fails theenforce-dev-to-mastercheck inbuild-test.yml.- Every pull request into
masterordevrunsbuild-test.yml, which builds the module as a smoke test and runs the Pester suite described below. This only validates (build succeeds, tests pass) - it has no publish/release side effects, those only happen viatag-and-release.ymlon a merge tomaster.
How the tests work¶
There's no separate suite of hand-written test files to keep in sync with the code - the Pester tests are generated directly from the same .EXAMPLE blocks in each function's comment-based help that already back the command docs on this site. A function's example can carry an Expected output: marker in its remarks (the descriptive text after the example command, not the command itself):
.EXAMPLE
Get-FogHost -hostName MeowMachine
This would return the fog details of a host named MeowMachine in your fog instance
Expected output:
{ "name": "MeowMachine", "id": 42 }
The Expected output: payload is plain JSON, not a PowerShell object literal - that's on purpose, so the test runner can parse it with ConvertFrom-Json instead of evaluating arbitrary code. It's read via PowerShell's native Get-Help -Full, not the generated markdown, so it isn't affected by PlatyPS's limitation that example code has to stay on a single line - only the code line has that restriction; the remarks underneath it (including the Expected output: block) can be as many lines as you like.
At test time, each annotated example is actually run, with the module's one HTTP seam (Invoke-FogApi) mocked using small fixture files under Tests/Fixtures/, and the real result is checked against the documented Expected output: - as a subset match, so a documented example only needs to call out the fields that matter, not every property a Fog host object happens to have.
The standing goal: one annotated example per parameter set¶
The target this suite is working towards is one annotated example for every parameter set of every function - not just one example per function. A function like Get-FogHost has three parameter sets (searchTerm, byID, serialNumber); ideally each of those has its own example demonstrating it, with an Expected output: block. This is a standing, evolving goal - as functions or parameter sets are added, coverage should grow to match.
To help track it, every test run produces an informational coverage report (TestResults/coverage-report.md locally, uploaded as the parameter-set-coverage-report artifact in CI) that reflects on each function's real parameter sets and cross-references them against the examples that exist, flagging which sets have no example at all versus which have an example that just isn't annotated yet. This report is purely informational - it never fails a build or blocks a PR. Outside contributors aren't expected to add .EXAMPLE/Expected output: annotations themselves; maintainers use the report to find and backfill gaps after the fact.
Running the tests locally¶
# fast, mocked - no Fog server needed
.\Invoke-FogApiTests.ps1
# scope to specific functions while you're working on them
.\Invoke-FogApiTests.ps1 -Function Get-FogHost, New-FogHost
# run the same examples unmocked against a real, already-configured Fog server
# (note: this will really create/modify/message objects on that server)
.\Invoke-FogApiTests.ps1 -RealServer
See Tests/FogApi.TestHelpers.psm1 for the parsing/mocking helpers if you want to extend the suite - Get-FogExampleCase, Get-FogMockResponse, Test-FogExpectedSubset, and the coverage-reporting functions are all documented there.