# Exercise: Test Your Tool

Give the RecipeBox module a manifest with New-ModuleManifest, then write five Pester tests that work on a copy of the recipes in TestDrive:, and a check proves they're good enough by breaking RecipeBox five ways and expecting a test to fail each time.

Freelancer · PowerShell · Updated November 10, 2026

A tool you use every week will change: a new category, a faster search, a fix for a bug someone found. Every change can quietly break something that used to work, and the recipe box is no different. In this exercise, `RecipeBox` becomes a proper module, with a manifest, and gets the tests that will catch those breaks for you from now on. How do you know your tests are any good? The check finds out the way testers do: it breaks RecipeBox on purpose, five different ways, and expects one of your tests to fail each time.

## Get the exercise code

Open this lesson's GitHub repository, [github.com/ask-codey/exercise-powershell-test-your-tool](https://github.com/ask-codey/exercise-powershell-test-your-tool), also linked from the **Exercise** box beside the lesson. Click **Code**, then **Download ZIP**, and unzip it into your `terminal-practice` folder. Or clone it with Git.

The folder holds:

- `RecipeBox\RecipeBox.psm1`: the recipe box from *Exercise: A Recipe Box Module*, grown a little. `Remove-Recipe` is new, with `-WhatIf`, and every command takes `-Path`, so a test can point it at a copy of the box instead of your real one. Don't change it.
- `test-data\recipes.json`: five test recipes, two of them Baking, and Lemon Garlic Pasta, which takes exactly 30 minutes.
- `RecipeBox.Tests.ps1`: your tests, with one example written.
- `Check.Tests.ps1`: the check. You don't need to change it.

## What to do

Open PowerShell 7 in the exercise folder, the one with `RecipeBox.Tests.ps1` in it.

1. **Make the manifest.** Use `New-ModuleManifest` to make `RecipeBox\RecipeBox.psd1`, beside `RecipeBox.psm1`, as in *Your Own Module*. Give it `-RootModule RecipeBox.psm1`, a version and a description, and `-FunctionsToExport` with `Get-Recipe`, `Add-Recipe` and `Remove-Recipe`, leaving out the two helpers. Check it with `Test-ModuleManifest`.
2. **Run the example.** `Invoke-Pester .\RecipeBox.Tests.ps1 -Output Detailed` shows one passing test. Here's how the file starts; every test gets a fresh copy of the five recipes in `TestDrive:`, in `$box`:

   ```powershell
   Describe 'RecipeBox' {
       BeforeEach {
           $box = Join-Path $TestDrive 'recipes.json'
           Copy-Item -Path "$PSScriptRoot\test-data\recipes.json" -Destination $box
       }

       It 'Get-Recipe returns every recipe in the box' {
           Get-Recipe -Path $box | Should -HaveCount 5
       }
   ```

3. **Write five more tests**, one `It` for each:
   - `Get-Recipe -Category Baking` returns only the baking recipes.
   - `Get-Recipe -MaxMinutes 30` includes a recipe that takes exactly 30 minutes.
   - `Add-Recipe` saves the new recipe, so `Get-Recipe` finds it afterwards.
   - `Add-Recipe` refuses a name that's already in the box.
   - `Remove-Recipe -WhatIf` leaves the recipe in the box.

Give every RecipeBox command `-Path $box`, so your tests never touch your real recipe box.

## Check your work

The check uses Pester. If you haven't installed it yet, install it once:

```powershell
Install-PSResource Pester
```

Then, from the exercise folder, run your own tests, then the check:

```powershell
Invoke-Pester .\RecipeBox.Tests.ps1 -Output Detailed
Invoke-Pester .\Check.Tests.ps1
```

At first most of the check's tests fail. That's expected: the manifest turns the first three green. Then the check runs your tests on RecipeBox as it is, where all of them must pass, and on five broken copies, where at least one must fail. A failing check names the break your tests missed and gives a hint, for example *in this copy, Add-Recipe returns the new recipe but never saves it, and no test noticed. After Add-Recipe, look for the recipe with Get-Recipe*. It starts a fresh PowerShell for each run, so give it up to half a minute.

If PowerShell says the check can't be loaded because it is not digitally signed, Windows has marked the downloaded files as coming from the internet: from the exercise folder, run `Get-ChildItem -Recurse | Unblock-File` once, then try again.

## Hints

- **Try it at the prompt first.** `Import-Module .\RecipeBox\RecipeBox.psd1 -Force`, then `Get-Recipe -Category Baking -Path .\test-data\recipes.json`: see the answer, then write the `Should` that expects it. (Only `Get-Recipe` is safe on the test data itself; the others change it.)
- **Check the right thing.** `(Get-Recipe -Category Baking -Path $box).Name` gives the names of the recipes it found, and `Should -Be 'Apple Crumble', 'Banana Bread'` checks the whole list.
- **The edge matters.** "Exactly 30 minutes" is where `-le` and `-lt` differ: `Should -Contain 'Lemon Garlic Pasta'`.
- **A command that should fail** goes in braces: `{ Add-Recipe ... } | Should -Throw` (*Testing with Pester*).
- **A rehearsal changes nothing.** After `Remove-Recipe -WhatIf`, `Get-Recipe -Name` should still find exactly one.

## When you're done

Your own tests are all green:

```text
Tests Passed: 6, Failed: 0, Skipped: 0, Inconclusive: 0, NotRun: 0
```

And so is the check:

```text
Tests Passed: 11, Failed: 0, Skipped: 0, Inconclusive: 0, NotRun: 0
```

Now run `Invoke-ScriptAnalyzer -Path .\RecipeBox -Recurse`, as in *PSScriptAnalyzer: A Second Pair of Eyes*. What does it say about the manifest, and how would you fix it?

## Submit your exercise

The exercise is how you finish this lesson. When your work is done, put it on GitHub in a repo of your own, then submit that repo's address here.

1. On GitHub, click **+**, then **New repository**. Name it (for example `exercise-powershell-test-your-tool`), choose **Public**, and click **Create repository**. Leave out the README: your folder already has one.
2. In a terminal in your exercise folder (PowerShell works), send your work to your new repo. If you downloaded the ZIP:

   ```powershell
   git init -b main
   git add .
   git commit -m "My solution"
   git remote add origin https://github.com/your-name/exercise-powershell-test-your-tool.git
   git push -u origin main
   ```

   If you cloned the starter instead, point your copy at your own repo, then commit and push:

   ```powershell
   git remote set-url origin https://github.com/your-name/exercise-powershell-test-your-tool.git
   git add .
   git commit -m "My solution"
   git push -u origin main
   ```

3. Paste your repo's address, such as `https://github.com/your-name/exercise-powershell-test-your-tool`, into **Submit your exercise** on this page. The site checks that the repo is public and holds your commits, and then the lesson is complete.

Changed something after you submitted? Push it, and submit again: your latest submission is the one that counts.

## So what

Your recipe box now has a label and a safety net: change it whenever you like, and six green checks tell you in seconds that it still does its job.

## Key terms

- [Pester](https://www.ask-codey.com/glossary/pester)
- [Module](https://www.ask-codey.com/glossary/module-powershell)
- [Module Manifest](https://www.ask-codey.com/glossary/module-manifest)
- [TestDrive](https://www.ask-codey.com/glossary/testdrive)
- [Should](https://www.ask-codey.com/glossary/should)

## Related

- [Your Own Module](https://www.ask-codey.com/lessons/powershell-modules)
- [Testing with Pester](https://www.ask-codey.com/lessons/powershell-pester)
- [PSScriptAnalyzer: A Second Pair of Eyes](https://www.ask-codey.com/lessons/powershell-script-analyzer)
- [Exercise: A Recipe Box Module](https://www.ask-codey.com/lessons/exercise-powershell-a-recipe-box-module)

Source: https://www.ask-codey.com/lessons/exercise-powershell-test-your-tool
