Tag Archives: Pester

The Pester Book Chapter Review (5)

Table of Contents – Describe Blocks

And, here we go. It’s time, to start testing with Pester. Or rather, it’s time to really start making our way toward that end goal. We’re going to start that with Describe blocks, also known as, “…the outer container for a group of tests.” It’s how this whole testing thing begins, and it looks like this:

Describe {

}

As stated, we need to think of a Describe block as a single shared scope for everything it contains. This means that the TestDrive PSDrive is available to all the tests within the Describe block. But what’s the TestDrive, right? I think it may have been mentioned previously, but it’s a drive — a PSDrive — that exists while the Describe block is executing. It’s a place to safely create folders and files during testing without the fear of making any mistakes against actual files and folders. There was also a mention of Mocks only existing while the Describe was running; I suspect we’ll get to these in time.

This chapter also touched on a few other valuable concepts that we’re going to be grateful we’ve learned. These included tagging. The Describe keyword actually has a Tag parameter that can be used to help separate whether, or not, a Describe block will run when using the Invoke-Pester function — don’t think we’ve talked about that one yet. Do keep in mind that if you don’t include a tag for a Describe block, that it’s always going to execute when the test is run.

This chapter also clued us in to upcoming topics, which included the Context block, It blocks, and BeforeAll, BeforeEach, AfterAll, and AfterEach. Keep reading; I’m about to do the same.

The Pester Book Chapter Review (4)

Table of Contents – Designing for Testing

In this chapter, we learned that Pester is going to make some assumptions about the code that we write. Therefore, in my mind, it’s going to be best if we learn what Pester is expecting and do that — well, those of us reading The Pester Book, at least.

This means we need to work with .ps1 files and functions, send our function output to the pipeline — good info — and that the results of our functions are consistent. Makes sense, right? If we’re testing that the value should be 5, then it’s not helpful if our code sometimes produces a random 6 (and there’s no test for that). This was actually better stated by Adam, when he wrote, “…for a given input, you get the same output.” His further elaborations were quite good, as well. As someone that uses iBooks and the ePub version, I highlighted a decent amount of the additional explanation.

Moving on, the book discussed that Pester would prefer that input be via parameters. If you’re not there yet, then get there, and stop settling for hard coded values, Read-Host prompts, or a function’s ability to read from the global scope when it can’t find what it wants in its current scope. If you’re not writing in functions — and this is really what this is about — then get there too. I spent a few posts before I started The Pester Book reviews trying to provide reasons why someone would want to do this (outside the community saying you should). It really does make your PowerShell life easier.

The chapter continues on by discussing output (think objects), that actions aren’t output (it makes sense when you read it), and finally, to keep commands as scoped as possible, as they’re easiest to test that way. This can be tough to teach, because people think whole project when they should be thinking task. But seriously, write in functions only, and keep them to a single purpose. Next, we’ll be back with a chapter on Describe Blocks.

This is getting good… I’ve done some Pester authoring previously, but I’ve never been taught it, so I’m looking forward to all those things I’m doing wrong, or didn’t know, because I didn’t give myself a complete training. Well, that’s the purpose of the book. Again, Describe blocks in our next review.

The Pester Book Chapter Review (3)

Table of Contents – Pester Concepts

As of this post, I’ve marched head first into Part I of The Pester Book.

It was a short chapter, as it included brief explanations of some Pester Concepts we’ll likely be spending more time with in our future. It explained Tests, as the basic unit of work within Pester. Remember, we’re on our way to learn how to test our PowerShell code with Pester. It also briefly touched on Mocks. This concept allows us to fake dependencies. The example used Get-Content. Instead of needing files from which we’d actually get the content, we can use mocking and have it appear as though we’ve returned the results we want, with the Get-Content cmdlet.

The chapter also included a brief discussion on assertions. It indicated that assertions are a core component of Pester (making a mental note of that). Assertions allow us to compare what should happen, and what does happen, when a specific part of our PowerShell executes.

Next, The Pester Book discussed scaffolding, and TestDrive. Scaffolding is referred to as a starting point for your tests. What it really seemed to be getting at, was the TDD philosophy. That’s the Test-Driven Development philosophy where you write (failing) tests first, then write the code to correct the tests. Without code in which to run your tests against, they’re going to fail, until you write the code that make those tests pass.

TestDrive is awesome. Or at first glance, it sounds like it will be. The TestDrive, drive is a FileSystem drive (like the C:\, D:\, etc.) that becomes available when a Pester test is running. This allows us to have a place to create file system objects while a Pester test is running, without worrying about negatively impacting a true filesystem where we don’t want to make changes.

This is getting good. Back soon.

The Pester Book Chapter Review (2)

Table of Contents – Introduction

As a reminder, as this is only the second post in this series, we’re about to begin a chapter review on The Pester Book. I would encourage you to get yourself a copy, if you haven’t already. Read your copy along with me and mine, and then head back here for chapter reviews. As mentioned once thus far, I’m not out to teach you Pester per se. That’s what the book is intended to do. Instead, I’m going emphasize the main points of each of the chapters. I’m going to write as though we’re reading the same thing at the same time. I have no idea if it’ll work, but I was confident enough. If you’re not reading along now, then use it when you are, or use it motivate yourself to do it at some time. Just don’t waste too much time, telling yourself you’ll eventually learn it.

I recently finished reading the Table of Contents through the Introduction and the introduction’s various parts. This means that I’ve covered the up front information — the about the author stuff, the foreword, how annoying code samples can be in “print,” and how to provide feedback. I’m actually appreciative that Adam’s willing to hear from the community about typos, code problems, and the like. As this is forever book, or living document, if you will, we can each be a part of ensuring its accuracy.

As you’ve seen, if you’re reading along, the book is broken down into five parts. These include Meet Pester, Using Pester, Using Gherkin with Pester, Code Coverage, and Pester Cookbook. Each part has anywhere from a single included chapter to several. These are pieces we’ll cover together, no matter how simple and short, or involved. I’m very grateful for the upfront, hey-let-me-introduce-you-to-Pester section. I get the feeling, the book isn’t out to make any assumptions that anyone of us already knows a portion of this content, even if we might.

I also get that same feeling from those introduction sections. The book briefly discusses the differences between unit tests, integration tests, regression tests, and the occasional acceptance test. Right off the bat, we’re getting a break down of the testing structure and type, and their logical order. It’s enough to get you excited to continuing reading; it was me, anyway. Now, it’s just me putting it to memory: unit, integration, regression, and acceptance.

As mentioned, testing isn’t new, but it may be to (some of) us. The whole Windows administrator turned scripting experts is still somewhat new on the Windows end. For me, I loved VBScript, back before PowerShell was even a thing. Back then, things were different though. You didn’t have to know VBScript to be a Windows system administrator. But now, you really should know PowerShell, and if you’re going to have to learn it and write it, then let’s learn to test it, too. Pester is going to be one of those things, that in time, people will assume you know, if you know PowerShell. That’s my prediction, anyway.

Before I wrap up here, I do want to mention the four paragraphs about testing that were included toward the end of the introduction. Those were highlighted as Testing as Institutional Memory, Testing Drives Better Modularization, Tests as Functional Specifications, and Test in Automated Build Pipelines. All very simple and short, yet important and relatable. See you again next time.

The Pester Book Chapter Review (1)

Table of ContentsMy Introduction

Pester. Have you heard about it? I should hope you’ve at least, heard of it.

I know the exact moment I realized that I needed Pester, and decided I would learn it backwards and forwards, once for all. You’ll realize the moment too, if you haven’t already. Before that, providing it hasn’t happened, you need to know a little about what Pester is and what it does, so that when the day comes, you’ll have enough introductory information to now know that it’s a requirement in your life. It happens.

I was working an AWS Windows project that hadn’t yet included Active Directory. In this project and its sub projects, I was essentially creating and configuring Windows workgroup computers. If you consider that the project required a good deal of security and that we didn’t have an Active Directory environment to leverage, you can imagine that I had several settings to edit, in order to secure our machines.

The environments were built using AWS CloudFormation and a couple PowerShell modules that often included several functions. For each sub project, I built a new stack and waited for my instances and other resources to become available. When my instances were completed, I’d jump on them via Remote Desktop and start poking around. Were my users created? Was my SSL certificate for Remote Desktop in place? Were my PowerShell modules in place? Were my software installers in place? Were all the Registry settings applied? I was doing a “quick” and manual visual spot check to make sure my systems were configured correctly. Me, someone that’s dedicated to automation, was doing these things manually. I’d literally remotely connect to an instance, open the PowerShell ConsoleHost, and enter a string of commands that looked like this:

PS > regedit; certlm.msc; compmgmt.msc; ii 'c:\Program Files\WindowsPowerShell\Modules'

The above commands would open up the different graphical utilities that I needed, in order to ensure my automation had run successfully. I could check my registry settings, I could check to see if my certificate was imported, I could check to see if my users were created, and I could check to see if my PowerShell modules were in place. I was doing this manually, even when I knew there was a better way.

I repeatedly thought, I should write a function to do these checks for me. But why write another function? Why not use what’s already been built-in to test my system? Why not improve my project and get more experience with Pester at the same time?

Well, I did. After all those manual checks on my instances, I was just thrilled to see all those green lines produced by Pester, taking milliseconds of time, to remind me of all the time I had already wasted. But I’m okay with it now, as this project presented me an opportunity to really begin to appreciate and utilize Pester. And in that, the time and effort of Adam Bertram.

Follow along as I read Adam’s The Pester Book published on Leanpub.com. I’m not going to teach you Pester per se, but I’m going to write about as though we’re reading the same book together — Adam’s book — and share my thoughts as I do. You ought to get a copy and follow long; we’ll learn this better together. For the foreseeable future, let’s make this blog a weekly review of what we’ve read, so you and I can potentially get more out of our reading. Maybe we’ll do more than a single chapter per week — we’ll see. I’ll be back soon with the first installment; therefore, you should get your copy of The Pester Book today!

Comfortably Save a Pester Test

I’ve spent some time with Pester this week. While exploring the OutputFile parameter, it quickly became clear that the best I seemed to be able to output was some form of XML, and honestly, that wasn’t good enough for me in my moment of discovery. While I intend to make myself a Pester expert in the coming year (2018), there’s somethings I don’t know 100% yet, and so I understand it’s possible that I sound like an idiot, as I may not know about x in regard to Pester.

While working with Invoke-Pester, I came across the -PassThru parameter. Its purpose in life, in relation to the Invoke-Pester command, is to create a PSCustomObject. Now that’s, something I can work with. The idea here is to invoke Pester against an AWS instance, export my object (to an XML standard I can deal with [thank you Export-Clixml]), and write it to S3. Then, I can download the file to a computer that’s not my newly configured AWS instance, and check for what tests passed and failed. This, without the need to RDP (Remote Desktop), to the instance, and visually and manually check to see what did and didn’t work from there. We’re getting closer and closer to RDP being a security incident.

My example is not going to include an actual Pester run, so instead we’ll jump directly to the Invoke-Pester command and what we’ll do after that command has executed. This first example is a fairly standard way of invoking Pester (with parameters) and creating an output file. Again, this isn’t the output I’m after.

PS > Invoke-Pester -Script @{Path = 'C:\WkDir\HostAcceptance.Tests.ps1'; Parameters = @{Project = 'trailking'; Environment = 'tst'}} -OutputFile 'C:\WkDir\PesterOutputXml.xml'

Instead we’re going to include some other parameters, to include PassThru, Show, and OutVariable. PassThru will provide us an object that contains all of the Pester results, Show with the None value will hide the Pester test results, and OutVariable will get that object (that again, contains all of the Pester results) into the PesterResults variable.

PS > Invoke-Pester -Script @{Path = 'C:\WkDir\HostAcceptance.Tests.ps1'; Parameters = @{Project = 'trailking'; Environment = 'tst'}} -PassThru -Show None -OutVariable PesterResults

I was mainly okay with the above command; however, it was still writing my object to the host program, and I wanted nothing to be displayed, at all. It’s too bad that option isn’t in there by default, but I’m okay with improvisation. Again, I know PowerShell better than Pester, so there is the possibility I just don’t know enough at the immediate moment to not have done this a potentially better way. Anyway, the below example removes all the output to the host, but still stuffs my results into the PesterResults variable.

PS > [System.Void](Invoke-Pester -Script @{Path = 'C:\WkDir\HostAcceptance.Tests.ps1'; Parameters = @{Project = 'trailking'; Environment = 'tst'}} -PassThru -Show None -OutVariable PesterResults)

Okay, now what? Everything I need and more is now in the $PesterResults variable. Next, we’ll export it into an XML format I (as in Import-Clixml), can deal with.

PS > $PesterResults | Export-Clixml -Path 'C:\WkDir\PesterExport.xml'

Now that it’s in a usable format, I’m going to read it back in. You can go ahead and pretend that I’ve moved my exported XML file from the computer on which it was created, and now I’m about to read it in on a different computer. This visualization is as though it was uploaded to AWS S3, and downloaded from S3 on a different device. We’ll say it’s on my Desktop.

$PesterResults = Import-Clixml -Path 'C:\Users\tommymaynard\Desktop\PesterStuff\PesterExport.xml'
Foreach ($Result in $PesterResults.TestResult) {
    [System.Array]$Object += [PSCustomObject]@{
        Describe = $Result.Describe.TrimEnd(':')
        Context = $Result.Context.TrimEnd(':')
        It = $Result.Name.TrimEnd(':')
        Should = $Result.Result
        Time = $Result.Time
    }
} 

$Object
# $Object | Format-Table -Autosize
# $Object | Export-Csv -Path 'C:\Users\tommymaynard\Desktop\PesterStuff\PesterExport.xml' -NoTypeInformation

In the above example, we do a few things. We import the file we created out in AWS into a variable on my local computer, and then begin to iterate through its contents. For each entry, we add other object to my Object variable. Each object will contain a Describe, Context, It, Should, and Time property which is all obtained from the TestResult property of my PesterResults variable.

The last three lines are a few ways to handle the output (2 and 3 are commented out): (1) display it in the host, (2) display it in the host in an easier to read format, and (3) write the objects to CSV. Neat, right. As I continue to better learn Pester… I might just be back here. I can’t be 100% that this is the best way to save off and deal with the results of the Pester tests, but we’ll see!

Parse Net.exe Accounts (for Pester)

In a recent Pester test, I needed to verify that three settings in net.exe accounts were properly set. These included Lockout threshold, Lockout duration (minutes), and Lockout observation window (minutes). Well, now that I have my answer, I thought I would document it here. Before I show you how I handled this task, based on varying versions of PowerShell, I’ll show you the default output that I needed to parse.

PS > net.exe accounts
Force user logoff how long after time expires?:       Never
Minimum password age (days):                          0
Maximum password age (days):                          42
Minimum password length:                              0
Length of password history maintained:                None
Lockout threshold:                                    3
Lockout duration (minutes):                           30
Lockout observation window (minutes):                 30
Computer role:                                        SERVER
The command completed successfully.

I needed the above output to be parsed, and when that was done, I only needed the values of the three previously mentioned Lockout settings to be displayed. The below code indicates that if PowerShell is a version greater than 4.0 the ConvertFrom-String cmdlet can be used. It’s not necessary, but it was good to practice using a cmdlet I hardly every use. If the PowerShell version isn’t greater than 4.0, we’ll use a temporary variable and do the parsing ourselves. In the end and regardless of version, we’ll get our results. I’m using [PSCustomObject], but I am confident this test will never run with a version of PowerShell less than that of 3.0. This is happening in AWS with a Server 2012 R2 AMI and as we know, 2012 R2 includes PowerShell 4.0 by default.

If ($PSVersionTable.PSVersion.Major -gt 4) {
    $AcctSettings = net.exe accounts | ForEach-Object {
        ConvertFrom-String -InputObject $_ -Delimiter ': +' -PropertyNames Setting,Value
    }
} Else {
    $AcctSettings = net.exe accounts | ForEach-Object {
        $TempVar = $_ -split ': +'
        [PSCustomObject]@{Setting = $TempVar[0]; Value = $TempVar[1]}
    }
}
($AcctSettings | Where-Object {$_.Setting -eq 'Lockout threshold'}).Value
($AcctSettings | Where-Object {$_.Setting -eq 'Lockout duration (minutes)'}).Value
($AcctSettings | Where-Object {$_.Setting -eq 'Lockout observation window (minutes)'}).Value
3
30
30

This task was being done for Pester, so while we’re here, let me show it to you inside the Pester It Block.

# Account lockout policies.
It 'Checking the account lockout threshold, duration, observation window settings:' {
    If ($PSVersionTable.PSVersion.Major -gt 4) {
        $AcctSettings = net.exe accounts | ForEach-Object {
            ConvertFrom-String -InputObject $_ -Delimiter ': +' -PropertyNames Setting,Value
        }
    } Else {
        $AcctSettings = net.exe accounts | ForEach-Object {
            $TempVar = $_ -split ': +'
            [PSCustomObject]@{Setting = $TempVar[0]; Value = $TempVar[1]}
        }
    }
    ($AcctSettings | Where-Object {$_.Setting -eq 'Lockout threshold'}).Value | Should -Be 3
    ($AcctSettings | Where-Object {$_.Setting -eq 'Lockout duration (minutes)'}).Value | Should -Be 30
    ($AcctSettings | Where-Object {$_.Setting -eq 'Lockout observation window (minutes)'}).Value | Should -Be 30
} # End It.

That’s it! Now you can parse net.exe accounts, too!!