{"id":1895,"date":"2014-11-03T00:00:00","date_gmt":"2014-11-04T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/practical-powershell-unit-testing-getting-started\/"},"modified":"2016-11-08T13:53:59","modified_gmt":"2016-11-08T13:53:59","slug":"practical-powershell-unit-testing-getting-started","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/powershell\/practical-powershell-unit-testing-getting-started\/","title":{"rendered":"Practical PowerShell Unit-Testing: Getting Started"},"content":{"rendered":"<div id=\"pretty\">\n<ul class=\"list--bare\">\n<li>PowerShell Unit-Testing: Getting Started\n<\/li>\n<li>\n<a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/practical-powershell-unit-testing-mock-objects\/\">Practical PowerShell Unit-Testing: Mock Objects<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/www.simple-talk.com\/sysadmin\/powershell\/practical-powershell-unit-testing-checking-program-flow\/\">Practical PowerShell Unit-Testing: Checking program flow<\/a>\n<\/li>\n<\/ul>\n<h2 id=\"first\">Contents<\/h2>\n<ul>\n<li><a href=\"#second\">Hello, World, Pester-Style<\/a><\/li>\n<li><a href=\"#third\">Executing Tests<\/a>\n<ul>\n<li><a href=\"#fourth\">Installing Pester<\/a><\/li>\n<li><a href=\"#fifth\">Running Pester<\/a><\/li>\n<li><a href=\"#sixth\">Continuous Integration <\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#seventh\">Writing Unit Tests<\/a>\n<ul>\n<li><a href=\"#eighth\">Naming your Test File Name<\/a><\/li>\n<li><a href=\"#ninth\">Making your Test File Aware of Your Source File<\/a><\/li>\n<li><a href=\"#tenth\">Making your Test File Aware of Helper Files<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#eleventh\">Test Anatomy<\/a>\n<ul>\n<li><a href=\"#twelveth\">File Preamble<\/a><\/li>\n<li><a href=\"#thirteenth\">InModuleScope <em>(New for 3.0!)<\/em><\/a><\/li>\n<li><a href=\"#fourteenth\">Module Preamble<\/a><\/li>\n<li><a href=\"#fifteenth\">Describe<\/a><\/li>\n<li><a href=\"#sixteenth\">Describe Setup and Teardown <em>(New for 3.0!)<\/em><\/a><\/li>\n<li><a href=\"#seventeenth\">Context<\/a><\/li>\n<li><a href=\"#eighteenth\">Context Setup and Teardown <em>(New for 3.0!)<\/em><\/a><\/li>\n<li><a href=\"#nineteenth\">It<\/a><\/li>\n<li><a href=\"#twentieth\">Syntax Alert<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#twentyfirst\">Pester Command Summary<\/a><\/li>\n<li><a href=\"#twentysecond\">Conclusion\u00a0<\/a><\/li>\n<\/ul>\n<p class=\"start\">PowerShell has grown up. In its recent versions, there are few things that PowerShell\u00a0 applications aren&#8217;t capable of doing just as easily as a more traditional language, plus a myriad of tasks that it can do better. It particularly shines at automating routine tasks. And even for these, there is a lot of sense in being able to do automated unit testing when developing and modifying scripts. This isn&#8217;t just a developer obsession: anyone who is writing scripts that must be reliable can do it faster, and with less tedium, by putting in place a safety net of unit tests. Unit tests provide <i>maintainability <\/i>(allowing you to make changes knowing that you have not broken anything), <i>documentation<\/i> (the tests show you and your colleagues how to use your scripts), and <i>robustness<\/i> (writing test cases is a good way to find holes in your logic) \u00a0. And with the recent advent of unit testing frameworks now available for PowerShell, it is easier than ever to get started. When I\u00a0 needed to\u00a0 do this, I \u00a0looked around at the handful of nascent unit testing frameworks available and quickly settled on <a href=\"https:\/\/github.com\/pester\/Pester\/wiki\">Pester<\/a>, the subject of this article.<\/p>\n<p>It is important to have a good grasp of the mechanics of unit tests in PowerShell. \u00a0As with many developer tools, frameworks, etc., you have some reference material provided with the product, and you have some usage examples, but what it lacks is a practical, no-nonsense description of <i>how to use the thing<\/i>. So, what you will find herein is what I like to call &#8220;tips from the trenches&#8221;: a collection of user tips, techniques, and tools accumulated and developed through hard-fought battles, which I can relate to you here so that you do not have to struggle with the same issues. I&#8217;m hoping that this will significantly reduce the Pester learning curve for you.<\/p>\n<p>Pester has, to be fair, made my task slightly less urgent. Pester 3.0 was just released; besides , by adding some new functionality they also fixed a couple of issues \u00a0that I now no longer need workarounds for: Pester, for example, \u00a0now <a href=\"https:\/\/github.com\/pester\/Pester\/issues\/182\">supports PowerShell&#8217;s &#8216;strict&#8217; mode<\/a>), so I definitely recommend\u00a0 the 3.0 release.<\/p>\n<h2 id=\"second\">Hello, World, Pester-Style<\/h2>\n<p>Before getting into the details, though, let&#8217;s take a look at how to write a unit test with Pester. Almost everything in this section is explored in more detail throughout the remainder of this series, but let&#8217;s \u00a0start with the canonical &#8220;Hello, World&#8221;. See the next section <i>Executing Tests<\/i> for instructions on installing and importing the Pester library, but if you have PSGet installed, it is as simple as \u00a0typing <code>Install-Module Pester<\/code> to download and install the pester package and then <code>Import-Module Pester<\/code> at the start of the script to load it into the current session.<\/p>\n<p>Step 1: Create a subdirectory for your PowerShell program.<\/p>\n<p>The next step, that of creating a file to hold your source code (HelloWorld.ps1) and a file to hold your test code (HelloWorld.Tests.ps1), is done automatically \u00a0by executing\u00a0 the following &#8211;<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\tPS&gt; New-Fixture -Name HelloWorld<\/pre>\n<p>You will see that Pester has checked to see if the files exist and, as they have \u00a0not, has created these two\u00a0 files, HelloWorld.ps1 and HelloWorld.Tests.ps1 for you, and put in sufficient skeletal code to run the unit test, so let&#8217;s just invoke Pester to test the empty function:<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\tPS&gt; invoke-pester\r\n\t\u00a0\r\n\tExecuting all tests in 'C:\\usr\\tmp'\r\n\tDescribing HelloWorld\r\n\t\u00a0[-] does something useful 1.13s\r\n\t\u00a0\u00a0 Expected: {False}\r\n\t\u00a0\u00a0 But was:\u00a0 {True}\r\n\t\u00a0\u00a0 at line: 7 in C:\\usr\\tmp\\HelloWorld.Tests.ps1\r\n\tTests completed in 1.13s\r\n\tPassed: 0 Failed: 1  \r\n<\/pre>\n<p>The first test was expecting to see <code>false<\/code> but saw <code>true<\/code>, so the test failed. If you open the test file <code>HelloWorld.Tests.ps1,<\/code> you will see what I call the file preamble, which I will ignore for now (described later under <i>Test Anatomy<\/i>), followed by the actual test which should be this:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\tDescribe \"HelloWorld\" {\r\n\t\u00a0\u00a0\u00a0 It \"does something useful\" {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $true | Should Be $false\r\n\t\u00a0\u00a0\u00a0 }\r\n\t}  \r\n\t<\/pre>\n<p>In a nutshell, the <code>Describe<\/code> command specifies the name of the function under test and the <code>It<\/code> command specifies a single test. The content of that test is the single line of code shown that maps to this syntax:<\/p>\n<p><code>actual-value | Should Be expected-value<\/code><\/p>\n<p>Want to see what a passing test looks like? Change the actual value to <code>$false<\/code> (or the expected value to <code>$true<\/code>), then run it again.<\/p>\n<p>Now let&#8217;s write some real code, something that actually invokes the function in the source file. Open the source file and you will find an empty function:<\/p>\n<pre>\tfunction HelloWorld {\r\n\t\u00a0\r\n\t}\r\n\t<\/pre>\n<p>Let&#8217;s change it to simply return a phrase:<\/p>\n<pre>\tfunction HelloWorld {\r\n\t\u00a0\u00a0\u00a0 return \"Hello from Pester\"\r\n\t}\r\n\t<\/pre>\n<p>And now let&#8217;s write a test that confirms that return value; I am just going to add this as a second test so you can see how a <code>Describe<\/code> block may contain several \u00a0tests. \u00a0We leave the preamble in place<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\tDescribe \"HelloWorld\" {\r\n\t\u00a0\u00a0\u00a0 It \"does something useful\" {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $true | Should Be $true\r\n\t\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0 It \"returns a canonical phrase\" {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HelloWorld | Should Be \"Hello from Pester\"\r\n\t\u00a0\u00a0\u00a0 }\r\n\t}\r\n\t\u00a0\r\n<\/pre>\n<p>Notice also that I changed the original dummy test expect <code>$true<\/code>, so both tests should pass when you execute <code>invoke-pester<\/code>:<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\tPS&gt; invoke-pester\r\n\tExecuting all tests in 'C:\\usr\\tmp'\r\n\tDescribing HelloWorld\r\n\t\u00a0[+] does something useful 58ms\r\n\t\u00a0[+] returns a canonical phrase 31ms\r\n\tTests completed in 89ms\r\n\tPassed: 2 Failed: 0  \r\n\t<\/pre>\n<p>What if we want a more elaborate &#8216;HelloWorld&#8217; routine that says &#8216;hello&#8217; to whatever name that you specify?\u00a0 To do this, we need to introduce a parameter to our <code>HelloWorld<\/code> function: we will pass in a name, if no name is given we default to &#8220;Pester&#8221; as we did above; and this time let&#8217;s even write the tests first in the H<code>elloWorld.Tests.ps1<\/code> file:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\tDescribe \"HelloWorld\" {\r\n\t\u00a0\u00a0\u00a0 It \"does something useful\" {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $true | Should Be $true\r\n\t\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0 It \"with no input returns a canonical phrase\" {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HelloWorld | Should Be \"Hello from Pester\"\r\n\t\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0 It \"with a name returns the standard phrase with that name\" {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HelloWorld \"Venus\" | Should Be \"Hello from Venus\"\r\n\t\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0 It \"with a name returns something that ends with name\" {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HelloWorld \"Mars\" | Should Match \".*Mars\"\r\n\t\u00a0\u00a0\u00a0 }\r\n\t}\r\n\t<\/pre>\n<p>I have revised the description of the second test and added two new tests. The second test passes no parameter, so we expect it to use the default &#8220;Pester&#8221;. The new tests pass a name so we expect that to be in the returned value. Just to give you a hint at the flexibility of the <code>Should<\/code> command, I am showing two versions, one with <code>Be<\/code> and one with <code>Match<\/code> that compares an expected value to an actual value with a regular expression.<\/p>\n<p>If you run the test file now, the new tests will fail, because we have not written any code to support them. So, finally, modify the source file with an eye to make those tests pass:<\/p>\n<pre>\tfunction HelloWorld($name='Pester') {\r\n\t\u00a0\u00a0\u00a0 return \"Hello from $name\"\r\n\t}\r\n\t<\/pre>\n<p>Running Pester confirms success:<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\tPS&gt; invoke-pester\r\n\tExecuting all tests in 'C:\\usr\\tmp'\r\n\tDescribing HelloWorld\r\n\t\u00a0[+] does something useful 65ms\r\n\t\u00a0[+] with no input returns a canonical phrase 26ms\r\n\t\u00a0[+] with a name returns the standard phrase with that name 5ms\r\n\t\u00a0[+] with a name returns something with that name 9ms\r\n\tTests completed in 106ms\r\n\tPassed: 4 Failed: 0  \r\n<\/pre>\n<h2 id=\"third\">Executing Tests<\/h2>\n<p>First just a brief description of running tests; then on to the main agenda of creating tests.<\/p>\n<h3 id=\"fourth\">Installing Pester<\/h3>\n<p>To install, simply copy the entire Pester distribution folder into your standard modules folder (i.e. <code>$env:USERPROFILE\\Documents\\WindowsPowerShell\\Modules<\/code>).<\/p>\n<p>Run this from the command-line (or add to your profile) to enable pester in your PowerShell session:<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\tPS&gt; Import-Module Pester<\/pre>\n<h3 id=\"fifth\">Running Pester<\/h3>\n<p>Use the Invoke-Pester command to run your unit tests. A test file is identified merely by its name; any file matching <code>*.Tests.ps1<\/code> qualifies. There are several ways to run your unit tests with Pester.<\/p>\n<dl>\n<dt>(1)<\/dt>\n<dd>With no arguments, <code>Invoke-Pester<\/code> examines the tree of files rooted in your current directory and executes all test files it finds: So you can just change directory (<code>Set-Location<\/code>) to the appropriate place and run with no arguments.<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\tPS&gt; Invoke-Pester<\/pre>\n<\/dd>\n<dt>(2)<\/dt>\n<dd>Specify a path and <code>Invoke-Pester<\/code> examines the tree rooted at that specified location.<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\tPS&gt; Invoke-Pester -Path tests\\MyProject\\ScriptCmdlets <\/pre>\n<\/dd>\n<dt>(3)<\/dt>\n<dd>Run one or more specific tests by naming them (wildcards allowed). The <code>TestName<\/code> parameter corresponds to Pester&#8217;s <i><code>Describe<\/code> <\/i>block<i>,<\/i> which is a container for a logical group of tests. Thus, this will run tests whose <code>Describe<\/code> blocks are named <code>GetFilesMany<\/code>, <code>GetFiles<\/code>, or <code>GetFilesLackingProjectName<\/code>, for example:<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\tPS&gt; Invoke-Pester -TestName 'GetFiles*' <\/pre>\n<\/dd>\n<\/dl>\n<div class=\"theory\"><img decoding=\"async\" class=\"float-left\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2084-pencil.jpg\" alt=\"2084-pencil.jpg\" \/><\/p>\n<p><em>If you do <\/em> <code>not<\/code><em> use the -Path parameter, Pester uses the current directory.<\/em><\/p>\n<\/div>\n<h3 id=\"sixth\">Continuous Integration<\/h3>\n<p>There are two useful options to <code>Invoke-Pester<\/code> for continuous integration purposes:<\/p>\n<p>You can ask Pester to exit with a return code equal to the number of failed tests with the <code>-EnableExit<\/code> parameter. Without this flag your tests will, for all intents and purposes, always be passing!<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\tPS&gt; Invoke-Pester -EnableExit<\/pre>\n<p>But watch out: you do <i>not<\/i> want to use <code>-EnableExit<\/code> when running interactively! Yes, it returns an exit code <i>but it terminates the current shell as well<\/i>. When used judiciously, that is fine running a build in batch mode. But interactively it will close your current window.<\/p>\n<p>You can ask Pester to output an NUnit-compatible result file with the <code>-OutputXml<\/code> parameter.<\/p>\n<pre class=\"lang:ps theme:powershell-output\">\tPS&gt; Invoke-Pester -OutputXml 'logs\\mylogfile.xml' <\/pre>\n<div class=\"theory\"><img decoding=\"async\" class=\"float-left\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2084-pencil.jpg\" alt=\"2084-pencil.jpg\" \/><\/p>\n<p><i>You can use the -EnableExit flag in a continuous build, but don&#8217;t try to use it when running Invoke-Pester interactively.<\/i><\/p>\n<\/div>\n<h2 id=\"seventh\">Writing Unit Tests<\/h2>\n<h3 id=\"eighth\">Naming your Test File Name<\/h3>\n<p>Typically, you create a single test file corresponding to a single source code file. The canonical name of this test file simply adds &#8220;.Tests&#8221; before the &#8220;.ps1&#8221; in the name of the file under test.\u00a0 So for this code file&#8230;<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \\src\\MyProject\\ScriptCmdlets\\GetStuff.ps1<\/p>\n<p>&#8230;this Pester file contains the tests:<\/p>\n<pre>\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \\tests\\MyProject.Test\\ScriptCmdlets\\GetStuff.Tests.ps1<\/pre>\n<p>There are different schemes for where to put your test files. For scripting languages, some people put a test file in the same directory as the source file; but compiled languages tend to separate the source file tree from the test file tree, and I see no reason to dismiss that clean separation just because PowerShell is a scripting language. Nonetheless, pick the style you prefer and stick with it; it is significant in the next section. (By the way, Pester&#8217;s <code>New-Fixture<\/code> command can streamline creating the file for you.)<\/p>\n<h3 id=\"ninth\">Making your Test File Aware of Your Source File<\/h3>\n<p>Each test file must begin with a preamble that specifies the source file upon which to operate. \u00a0The default preamble will serve most purposes, but if you have a special requirement then you can alter the preamble to accommodate it.<\/p>\n<p><code>If you are testing a single .ps1 script file...<\/code><\/p>\n<p>&#8230; then you simply need to dot-source that file. With the source and test file given just above the top of your test file should point to the source file with a command similar to this-note the important dot and space at the start of the line:<\/p>\n<p>\u00a0\u00a0\u00a0 . &#8216;..\\..\\..\\src\\MyProject\\ScriptCmdlets\\GetStuff.ps1&#8217;<\/p>\n<p>While that will certainly work, it is fragile: if you rename or move the source file or test file it will break. This two-line sequence is more robust; you may wish to tweak it to your own conventions, but this one works for the convention I specified above, namely with a source file <i>file<\/i><code>.ps1<\/code> in a project named <i>Project<\/i> in the <code>src<\/code> tree then the corresponding test file is <i>file<\/i><code>.Tests.ps1<\/code> in a project named <i>Project<\/i><code>.Test<\/code> in the <code>tests<\/code> tree:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t\u00a0\u00a0\u00a0 $srcFile = $MyInvocation.MyCommand.Path `\r\n\t\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0-replace 'MySolution\\\\tests\\\\(.*?)\\.Test\\\\(.*?)\\.Tests\\.ps1', `\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0'MySolution \\src\\$1\\$2.ps1' \r\n\t\u00a0\u00a0\u00a0 . $srcFile\r\n\t\u00a0\r\n<\/pre>\n<p><code>If you are testing a function within a module...<\/code><\/p>\n<p>&#8230; then you just import the module as you normally would with the <code>Import-Module<\/code> cmdlet. If the module is installed in a standard PowerShell location (i.e. in the search path pointed to by <code>$env:PSModulePath<\/code>), the module name will suffice, e.g.<\/p>\n<p>\u00a0\u00a0\u00a0 Import-Module MyModule<\/p>\n<p>\u00a0If, on the other hand, your module is in an arbitrary location in your source files in your source tree, then provide the path name. I would again recommend leveraging your own conventions to divine the source module, e.g. perhaps something like this:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t\u00a0\u00a0\u00a0 $srcModule = $MyInvocation.MyCommand.Path `\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 -replace 'MySolution\\\\tests\\\\(.*?)\\.Test\\\\(.*?)\\.Tests\\.ps1', `\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0'MySolution \\src\\$1\\$2.psd1'\r\n\t\u00a0\u00a0\u00a0 Import-Module $srcModule\r\n\t\u00a0\r\n<\/pre>\n<p><\/p>\n<div class=\"theory\"><img decoding=\"async\" class=\"float-left\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2084-pencil.jpg\" alt=\"2084-pencil.jpg\" \/><\/p>\n<p><i>Your test must bring into scope your script or module under test.<\/i><\/p>\n<\/div>\n<h3 id=\"tenth\">Making your Test File Aware of Helper Files<\/h3>\n<p>It is likely that you will want to \u00a0develop some testing support functions as you build out your unit tests, functions that help you streamline your test code.\u00a0 I keep these helper functions in a separate subdirectory just below my test scripts folder. Thus, my test file also includes this in the preamble:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t\u00a0\u00a0\u00a0 $helperDir = \"$PSScriptRoot\\TestHelpers\" \r\n\t\u00a0\u00a0\u00a0 Resolve-Path $helperDir\\*.ps1 | % { . $_.ProviderPath }\r\n<\/pre>\n<p>That sequence will bring into the current scope all of the helper functions in my <code>TestHelpers<\/code> directory. By using <code>Resolve-Path<\/code> and the wildcard on the file name, any new functions that I might develop simply have to be placed in that directory and they are automatically brought into the current scope on the next run.<\/p>\n<h2 id=\"eleventh\">Test Anatomy<\/h2>\n<p>The prior discussion focused on some key details to keep in mind when creating tests; now let&#8217;s take a look at the anatomy of a test file itself. In the introduction, you saw about the simplest possible test, using a <code>Describe <\/code>command to identify the function under test and an <code>It<\/code> command to specify an individual test. The <code>New-Fixture<\/code> command that created the test template for you also included what I call the <i>&#8216;file preamble&#8217;<\/i>, which I told you to just ignore at that point. But to build your real unit tests, you must inevitably get a good grounding in the whole syntax. This section tackles that, before taking you further into tips and techniques for getting the most from Pester.<\/p>\n<p>Take a look at the code skeleton below; it shows a composite view including all optional and enumerable components; once you are familiar with all the pieces this will not look so daunting. It can be immediately helpful with what you have learned so far. Right at the top you can see the<code> &lt;file-preamble&gt;<\/code>. A couple lines lower you see the <code>Describe<\/code>. If you are dealing with PowerShell modules, you will need the <code>InModuleScope<\/code> but our earlier test was not using modules, which is why we went straight to the <code>Describe<\/code> command. Skip a few more levels and you will find the <code>It<\/code> command; the stuff in-between the <code>Describe<\/code> and the <code>It<\/code> was not needed in the simple test but each has a crucial role to play. So for an introductory look at this, do not worry about memorizing it; just come back to it as you learn new pieces to see where they fit. Just after the skeleton, I describe each element to help you understand how the pieces fit together.<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t&lt;file-preamble&gt;\r\n\tInModuleScope &lt;module-name&gt; {\r\n\t\u00a0\u00a0\u00a0 &lt;module-preamble&gt;\r\n\t\u00a0\u00a0\u00a0 Describe &lt;test-name&gt; {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;one-time-describe-initialization&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 BeforeEach {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;per-test-initialization&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 AfterEach {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;per-test-cleanup&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0Context &lt;context-description&gt; {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;one-time-context-initialization&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 It &lt;test-description&gt; {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;test-code&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 . . .\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 It &lt;test-description&gt; {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;test-code&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 BeforeEach {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;per-test-initialization&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 AfterEach {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;per-test-cleanup&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 . . .\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Context &lt;context-description&gt; {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 It &lt;test-description&gt; {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;test-code&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0 . . .\r\n\t\u00a0\u00a0\u00a0 Describe &lt;test-name&gt; {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Context &lt;context-description&gt; {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 It &lt;test-description&gt; {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;test-code&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0 }\r\n\t}\r\n\t\u00a0\r\n<\/pre>\n<p>\u00a0Here is a breakdown of each component:<\/p>\n<h3 id=\"twelveth\">File Preamble<\/h3>\n<p>For testing a <code>script<\/code> (.ps1), the file preamble includes dot-sourcing the source file <i>and<\/i> dot-sourcing any helper files. For testing a <code>module<\/code> (.psd1), the file preamble should <i>only<\/i> dot-source the module; helper files must be in the module preamble.<\/p>\n<h3 id=\"thirteenth\">InModuleScope <i>(New for 3.0!)<\/i><\/h3>\n<p>This is a new command introduced with Pester 3.0. It allows you to unit test your <i>private<\/i> functions within a module, i.e. those functions that you have <i>not<\/i> exported for public consumption. Very handy, indeed, for getting at that &#8220;hard to reach&#8221; code so you have better test coverage. (Of course, there is the flipside of the argument that says you should only be testing what is publicly exposed so as not to make your tests too fragile&#8230;). The argument to <code>InModuleScope<\/code> is the name of the module that you just imported in the file preamble with<code> Import-Module<\/code>. (Regardless of whether you used <code>Import-Module<\/code> with a module name or a file path, <code>InModuleScope<\/code> requires just the module name.)<\/p>\n<h3 id=\"fourteenth\">Module Preamble<\/h3>\n<p>I scratched my head for a while until I realized the need for this important component. If you are testing a module and have used <code>InModuleScope<\/code>, then Pester creates a new scope: any initialization code <i>before<\/i> <code>InModuleScope<\/code> is <i>not<\/i> available inside <code>InModuleScope<\/code>. (This works just like any other script block in PowerShell.) Remember the helper functions discussed above. Those need to be here in the module preamble rather than the file preamble; otherwise, you will get an error when you attempt to use one of your helper functions saying it is not defined.<code><\/code><\/p>\n<h3 id=\"fifteenth\">Describe<\/h3>\n<p>A logical container for a set of tests; this block may contain any number of <code>Context<\/code> and <code>It<\/code> blocks. The command-line &#8211;<code>TestName<\/code> parameter operates on the names of <code>Describe<\/code> blocks.<\/p>\n<h3 id=\"sixteenth\">Describe Setup and Teardown <i>(New for 3.0!)<\/i><\/h3>\n<p>As shown in the code skeleton, a <code>Describe<\/code> block may contain some direct code in <code>the one-time-describe-initialization<\/code> component. This is executed just once. But Pester 3.0 now provides the <code>BeforeEach<\/code> setup command, which executes at the beginning of each <code>It<\/code> block contained within the <code>Describe<\/code> block. Similarly, the <code>AfterEach<\/code> command provides a teardown mechanism executed at the end of each <code>It<\/code> block.<\/p>\n<h3 id=\"seventeenth\">Context<\/h3>\n<p>A second level logical container for a set of tests; this block may contain any number of <code>It<\/code> blocks.<\/p>\n<h3 id=\"eighteenth\">Context Setup and Teardown <i>(New for 3.0!)<\/i><\/h3>\n<p>Just like the <code>Describe<\/code> block, the <code>Context<\/code> block may optionally contain a <code>one-time-context-initialization<\/code> component, and it may optionally provide a <code>BeforeEach<\/code> block for setup or an <code>AfterEach<\/code> block for teardown. If both the <code>Describe<\/code> and <code>Context<\/code> blocks contain a <code>BeforeEach<\/code>, the <code>BeforeEach<\/code> in the <code>Describe <\/code>executes first, then the <code>BeforeEach<\/code> in the <code>Context<\/code>. The <code>AfterEach<\/code> works the other way: <code>AfterEach<\/code> in the <code>Context<\/code> then <code>AfterEach<\/code> in the <code>Describe<\/code>.<\/p>\n<p>One unique feature for both <code>BeforeEach<\/code> and <code>AfterEach<\/code>: they will execute as just described regardless of where they physically appear within a <code>Describe<\/code> or a <code>Context<\/code> block. Thus, in the code skeleton, you will observe that I put them at the top of a <code>Describe<\/code> block and at the bottom of a <code>Context<\/code> block, just as a visual mnemonic of this.<\/p>\n<h3 id=\"nineteenth\">It<\/h3>\n<p>A unit test. This block may appear within either a <code>Context<\/code> block or a <code>Describe<\/code> block.<\/p>\n<h3 id=\"twentieth\">Syntax Alert<\/h3>\n<p>It is a syntactic requirement of PowerShell that each opening brace you see in the code skeleton above be on the same line as the command with which it is associated. If you really prefer having your braces match by indent (and some people do, I understand!) you must use a back tick to signal line continuation, like this:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">\t\u00a0\u00a0\u00a0 Describe &lt;test-name&gt; `\r\n\t\u00a0\u00a0\u00a0 {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Context &lt;context-description&gt; `\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 It &lt;test-description&gt; `\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;test-code&gt;\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\t\u00a0\u00a0\u00a0 }\r\n\t<\/pre>\n<p><\/p>\n<div class=\"theory\"><img decoding=\"async\" class=\"float-left\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2084-pencil.jpg\" alt=\"2084-pencil.jpg\" \/><\/p>\n<p><i>Every script block attached to a Pester command must <code>start<\/code> on the same line as the command unless you escape the line break.<\/i><\/p>\n<\/div>\n<h2 id=\"twentyfirst\">Pester Command Summary<\/h2>\n<p>For completeness, here is a list of all Pester commands showing parameters for each. Almost all of these will be touched upon in this series. For further details on any command, though, you can use PowerShell&#8217;s own <code>Get-Help<\/code>, but typically, you will get better information from the official Pester API documentation at <a href=\"https:\/\/github.com\/pester\/Pester\/wiki\">https:\/\/github.com\/pester\/Pester\/wiki<\/a>.<\/p>\n<p>(At the time of writing, though, you will not find the syntax for the <code>Should<\/code> command shown below anywhere else!)<\/p>\n<table>\n<tbody>\n<tr>\n<td valign=\"top\">\n<p>InModuleScope [-ModuleName] &lt;String&gt; [-ScriptBlock] &lt;ScriptBlock&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Describe [-Name] &lt;String&gt; [-Tags &lt;Object&gt;] [[-Fixture] &lt;ScriptBlock&gt;]<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Context [-Name] &lt;String&gt; [[-Fixture] &lt;ScriptBlock&gt;]<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>It [-name] &lt;String&gt; [[-test] &lt;ScriptBlock&gt;]<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>BeforeEach &lt;ScriptBlock&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>AfterEach &lt;ScriptBlock&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Mock [[-CommandName] &lt;String&gt;] [[-MockWith] &lt;ScriptBlock&gt;] [-Verifiable]<br \/>\n\u00a0\u00a0\u00a0\u00a0 [[-ParameterFilter] &lt;ScriptBlock&gt;] [[-ModuleName] &lt;String&gt;]<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Assert-MockCalled [[-CommandName] &lt;String&gt;] [-Exactly] [[-Times] &lt;Int32&gt;]<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0 [[-ParameterFilter] &lt;ScriptBlock&gt;] [[-ModuleName] &lt;String&gt;] [[-Scope] &lt;String&gt;]<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Assert-VerifiableMocks<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Should [ Not ] &lt;Operator&gt; [ Argument ]<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>In [[-path] &lt;Object&gt;] [[-execute] &lt;ScriptBlock&gt;]<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>New-Fixture [[-Path] &lt;String&gt;] [-Name] &lt;String&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Invoke-Pester [[-Path] &lt;String&gt;] [[-TestName] &lt;String&gt;] [[-EnableExit]]<\/p>\n<p>\u00a0\u00a0\u00a0 [[-OutputXml] &lt;String&gt;] [[-Tag] &lt;String&gt;] [-PassThru] [-CodeCoverage &lt;Object[]&gt;]<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"twentysecond\">Conclusion<\/h2>\n<p>Congratulations! If you made it this far I surmise you see the promise of unit testing in the PowerShell realm. Pester, as you saw at the very beginning, makes it quite simple and painless to unit test a function. But as with any technology you have not previously been exposed to, there is that little bit of learning curve to climb. You have surmounted the first hill by slogging through the section on test anatomy and are well on your way to conquering Pester&#8217;s secrets.<\/p>\n<p>As you will see in parts 2 and 3, Pester&#8217;s learning curve is particularly modest. There you will learn about how Pester can easily validate simple data (scalars) but needs just a bit of help when dealing with arrays. Also, you will see how straightforward Pester&#8217;s mocking capability is. (<i>Mocking<\/i> allows you to make tests much simpler by focusing on the one function you want to test and faking out all the rest, even if they are built-in PowerShell cmdlets!) Another important one is how to parameterize a test. (<i>Parameterized tests<\/i> save you from writing essentially the same test over and over with just a different input value.)<\/p>\n<p>By the time you are through parts 2 and 3 you will have a thorough understanding of how to use Pester&#8217;s full capabilities to make your PowerShell scripting more useful and more productive!<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>By the time you&#8217;re using PowerShell to automate an increasing amount of the system administration, database maintenance, or application-lifecycle  work, you&#8217;ll probably need to automate the unit-testing of the PowerShell scripts themselves.  Michael Sorens introduces you to Pester,  the leading test framework for PowerShell, and shows how it can make it easier to produce reliable scripts&hellip;<\/p>\n","protected":false},"author":221868,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[35],"tags":[4168,4635,4871],"coauthors":[6802],"class_list":["post-1895","post","type-post","status-publish","format-standard","hentry","category-powershell","tag-database","tag-powershell","tag-sysadmin"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1895","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221868"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1895"}],"version-history":[{"count":9,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1895\/revisions"}],"predecessor-version":[{"id":68983,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1895\/revisions\/68983"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1895"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1895"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1895"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1895"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}