diff --git a/tutorial/2-testing-a-module/3-public-functions.mdx b/tutorial/2-testing-a-module/3-public-functions.mdx index 9858009..65d903d 100644 --- a/tutorial/2-testing-a-module/3-public-functions.mdx +++ b/tutorial/2-testing-a-module/3-public-functions.mdx @@ -133,7 +133,15 @@ function Get-PlanetDistance { } ``` -This is where importing the module pays off. `Get-PlanetDistance` calls two functions that live in other files. Dot-sourcing `Get-PlanetDistance.ps1` on its own would fail immediately with `The term 'Test-PlanetName' is not recognized`. Importing the module loads everything together, exactly as it runs in production. +This is where importing the module pays off. `Get-PlanetDistance` calls two functions that live in other files. Dot-sourcing `Get-PlanetDistance.ps1` on its own loads the function without complaint, and then every call fails, once per command it cannot find: + +``` +The term 'Test-PlanetName' is not recognized ... +The term 'Get-Planet' is not recognized ... +The term 'ConvertTo-AstronomicalUnit' is not recognized ... +``` + +Importing the module loads everything together, exactly as it runs in production. ## Testing it diff --git a/tutorial/3-organising-tests/1-grouping-tests.mdx b/tutorial/3-organising-tests/1-grouping-tests.mdx index f989778..c6188a6 100644 --- a/tutorial/3-organising-tests/1-grouping-tests.mdx +++ b/tutorial/3-organising-tests/1-grouping-tests.mdx @@ -84,7 +84,13 @@ You have been using `BeforeAll` since the first test. It has three siblings, and All four can go in a `Describe` or a `Context`, and they apply to everything nested inside. That is why the single `BeforeAll` at the top of your file — importing the module — is still doing its job for tests that now live two levels deep. -The ordering is easiest to believe when you watch it. Drop this in a scratch file and run it: +The ordering is easiest to believe when you watch it. Make a folder for the demonstration: + +```powershell +New-Item -Path ./scratch -ItemType Directory -Force +``` + +Then drop this in it and run it: ```powershell title="scratch/Ordering.Tests.ps1" Describe 'Ordering' { @@ -118,7 +124,7 @@ AfterAll The `[+]` lines look out of place — each appears *after* its own `AfterEach` rather than between the two. That is a reporting artifact, not an ordering one: Pester prints a test's result line only once the test is completely finished, and `AfterEach` is part of finishing. -Delete that file once you have seen it — it is a demonstration, not part of the suite. +Delete the `scratch` folder once you have seen it — it is a demonstration, not part of the suite. :::tip Which one to reach for Use `BeforeAll` for anything expensive or read-only — importing a module, loading fixture data. Use `BeforeEach` when a test would otherwise inherit state from the test before it. @@ -128,17 +134,21 @@ Planetarium never ends up needing `BeforeEach` — every test builds what it nee ## Explaining a failure with -Because -Every `Should-*` assertion takes a `-Because` parameter. The text is folded into the failure message: +Every `Should-*` assertion takes a `-Because` parameter. Add it to the first test in `Get-Planet.Tests.ps1`: ```powershell (Get-Planet).Count | Should-Be 8 -Because 'the solar system has eight planets' ``` +That passes, so to see what `-Because` does you have to break it. Change the `8` to a `9` and run the suite: + ``` [-] Returns all eight planets 77ms - Expected [int] 8, because the solar system has eight planets, but got [int] 9. + Expected [int] 9, because the solar system has eight planets, but got [int] 8. ``` +The text is folded into the failure message. Put the `8` back once you have seen it. + It earns its place when the expected value is a magic number whose origin is not obvious from the test. `Should-Be 8` says what; `-Because 'the solar system has eight planets'` says why, to whoever is troubleshooting the error in the future. It is noise on an assertion that already explains itself, so use it sparingly rather than everywhere. diff --git a/tutorial/4-mocking/2-your-first-mock.mdx b/tutorial/4-mocking/2-your-first-mock.mdx index 2e340f6..f72b98d 100644 --- a/tutorial/4-mocking/2-your-first-mock.mdx +++ b/tutorial/4-mocking/2-your-first-mock.mdx @@ -53,8 +53,18 @@ This is the detail that costs people the most time. `-ModuleName Planetarium` injects the mock into the module's scope, where the call actually resolves. -:::warning A mock without `-ModuleName` fails silently -Nothing errors. The mock is simply never used, and the real command runs instead. If a mock appears to have no effect, this is the first thing to check. +:::warning A mock without `-ModuleName` does not reach into the module +What you get depends on where else the command is visible. + +For a command that also exists outside the module, like `Import-Csv`, nothing errors. The mock is simply never used, the real command runs, and the test passes or fails for reasons that have nothing to do with the mock you thought you installed. + +For a command that only exists inside the module, like the private `Get-PlanetData`, `Mock` cannot find it at all: + +``` +CommandNotFoundException: Could not find Command Get-PlanetData +``` + +If a mock appears to have no effect, or `Mock` cannot find a command you know is there, `-ModuleName` is the first thing to check. ::: Note also what you did *not* have to do: no `InModuleScope` wrapper. `-ModuleName` reaches the private `Get-PlanetData` without dragging your whole test inside the module — which is exactly the preference the [modules guide](../../docs/usage/modules) recommends over `InModuleScope`. diff --git a/tutorial/7-ci/2-github-actions.mdx b/tutorial/7-ci/2-github-actions.mdx index f619d8c..d2e1961 100644 --- a/tutorial/7-ci/2-github-actions.mdx +++ b/tutorial/7-ci/2-github-actions.mdx @@ -144,7 +144,7 @@ The workflow above is a complete, working setup. Natural next steps, in rough or Starting from an empty folder, you have built a PowerShell module with a manifest, a loader, public and private functions, an external data file and a function that writes reports — and tested all of it: -- 26 tests across six test files +- 26 tests across seven test files - Public functions tested through the module's real front door, which proves they are exported - Private helpers reached with `InModuleScope`, sparingly - A data source replaced by mocks so tests own their data