Exercise: The Playlist Tools

Turn four rough functions for a homework playlist into tools that behave like PowerShell's own commands, with verb-noun names, objects for output, checked input, pipeline input, -WhatIf and help, while a Pester check tries each one on its own copy of the playlist.

Journeyman · PowerShell · Updated

A study playlist is one of those small things that makes homework easier: music without words, long enough for a chapter, the same every evening. This exercise's study mix comes with four tools that someone wrote in a hurry. They work, more or less, but none of them behaves like a real command: one has a name nobody could guess and prints sentences, one writes whatever you type into the playlist, one is empty, and one deletes without a rehearsal. Your job is to turn them into the kind of tools this chapter built, ones a friend could pick up and use with Get-Help, Tab and -WhatIf. A Pester check tries each tool on its own copy of the playlist and tells you which jobs are done.

Get the exercise code

Open this lesson's GitHub repository, github.com/ask-codey/exercise-powershell-the-playlist-tools, 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:

  • PlaylistTools.ps1: the four tools, for you to finish.
  • study-mix.csv: the playlist, eight tracks with a Title, Artist, Minutes and Genre (Lofi, Jazz or Piano).
  • reset-mix.ps1: puts the eight tracks back whenever trying Add-Track or Remove-Track has changed the file.
  • Check.Tests.ps1: the check. You don't need to change it.

What to do

Open PowerShell in the exercise folder, the one with study-mix.csv in it, and open it in VS Code with code .. Load the tools and try the first one:

. .\PlaylistTools.ps1
tracks -Genre Jazz
(tracks -Genre Jazz | Measure-Object).Count
Coffee Ring - The Footnotes (6 min)
Snow Day - The Footnotes (4 min)
Highlighter Blues - The Footnotes (7 min)
Coffee Ring - The Footnotes (6 min)
Snow Day - The Footnotes (4 min)
Highlighter Blues - The Footnotes (7 min)
0

The tracks print, but the count is 0: Write-Host's sentences never reach the pipeline. Load the file again with . .\PlaylistTools.ps1 after every change. Then, one job at a time (the README in the folder has every detail):

  1. Get-Track. Rename tracks to Get-Track, and make it output the track objects instead of sentences, keeping -Genre and -Path.
  2. Advanced functions. Give all four tools [CmdletBinding()], and Get-Track a Write-Verbose line that names the file it reads.
  3. Add-Track checks its input. Title, Minutes and Genre are Mandatory; Minutes is a whole number from 1 to 20; Genre is only Lofi, Jazz or Piano, so Tab fills it in; an empty Artist is turned away. It outputs the track it added.
  4. Measure-Playlist. Takes tracks from the pipeline with a -Track parameter and outputs their total minutes, once.
  5. Remove-Track rehearses. Takes tracks from the pipeline and supports -WhatIf and -Confirm, writing the file once at the end.
  6. Help for Get-Track. A help block with a synopsis, an explanation of -Genre and an example.

Check your work

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

Install-PSResource Pester

Then, from the exercise folder:

Invoke-Pester

At first most tests fail. That's expected: each job you finish turns its tests green. A failing test names the job and says what to look at, for example Expected 1, because Add-Track should output the one track it added, but got 0. The check gives every test its own copy of the study mix in a throwaway folder and passes it with -Path, so it never touches study-mix.csv.

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 Invoke-Pester again.

Hints

  • Objects, not sentences. A bare $tracks on its own line outputs every track. That's what Get-Song does in Functions: Naming a Job.
  • A function that ignores a misspelled parameter isn't advanced yet: Advanced Functions: [CmdletBinding()].
  • The checks go on the lines above each parameter, in the order of Checking Input: Validation Attributes. Remember the type, [int], on Minutes.
  • Measure-Playlist sees only the last track? It has no process block (Taking Pipeline Input). Start the total in begin, not in process.
  • Remove-Track removes for real with -WhatIf? The change must sit inside if ($PSCmdlet.ShouldProcess($Track.Title, 'Remove track')), as in -WhatIf in Your Own Tools. Run .\reset-mix.ps1 to get the tracks back.
  • Get-Help shows only NAME and SYNTAX? A keyword is misspelled, or the block isn't the first thing in the function (Help for Your Tool).

When you're done

Every test is green, and Pester's last line says:

Tests Passed: 15, Failed: 0, Skipped: 0, Inconclusive: 0, NotRun: 0

Load the tools again, and they work like PowerShell's own commands:

. .\PlaylistTools.ps1
Get-Track -Genre Jazz | Measure-Playlist
Get-Track -Genre Jazz | Remove-Track -WhatIf
17
What if: Performing the operation "Remove track" on target "Coffee Ring".
What if: Performing the operation "Remove track" on target "Snow Day".
What if: Performing the operation "Remove track" on target "Highlighter Blues".

Then try them the way a friend would, with nothing but Tab and Get-Help: Add-Track -Genre, a space and Tab, Get-Help Get-Track -Examples, a song that's 45 minutes long. Do your tools explain themselves?

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-the-playlist-tools), 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:

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

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

    git remote set-url origin https://github.com/your-name/exercise-powershell-the-playlist-tools.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-the-playlist-tools, 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

The same four jobs, written as real tools, are something you can hand to anyone: they say what they are, check what they're given, rehearse what they change and explain themselves. That's the difference between a script and a tool.

Key terms

Related