The Pester Book Chapter Review (17)

Table of ContentsMocking the Unmockable

With this chapter, we’re right back into unit testing, mocking, and removing dependencies on which our code is reliant. Remember that our last chapter review was on infrastructure validation, which put us in position to ensure dependencies. But not so much today; today we’ll continue our previous, previous discussion on mocking. This time, however, we’re mocking the unmockable, or so they say.

What we learned from this chapter was the ways in which we can mock those times that we occasionally need to drop down and include .NET methods in our PowerShell functions. As Pester cannot yet test this — we hope it’s “yet” — modifications to how we test these things become necessary.

The ways in which we can do this include creating wrapper functions around the .NET method, creating a ScriptMethod — if you’ve never done that, you should try it to say you have; it’s neat — creating a stubbed command, and finally, asserting mocks transitively. This one was described as not being “for the faint of heart.” And the author may be right, as it became a multiple step process. Not terribly difficult in the example; however, it may become more involved in one’s own testing.

The point is clear though, stick to PowerShell at all costs, and only use these options where they are actually required. As the chapter wrapped up, it was indicated to use helper functions — our first of the four options. It’s the easiest of the options, and offered an interesting note. One purpose behind PowerShell was to give system administrators a consistent and usable shell and scripting language. The functions and cmdlets we use are all wrappers around .NET. That was the idea: simply access the features of .NET through PowerShell — a language a system administrator might be willing to use. Great chapter and I’ll definitely keep these options in mind, with a lean toward wrapper functions.

The Pester Book Chapter Review Sidebar

I’m working on the next chapter review of The Pester Book, and I had a thought. I was about to add the first, below paragraph to that review, but it ultimately just didn’t make sense to include it there. And so here we are: a sidebar of thought, I thought I would share.

I want to make mention of my project of writing chapter reviews for each chapter of The Pester Book. While I would recommend trying this yourself, sure, there’s an unspoken balance between sharing and not sharing, what I’ve read and what I’ve learned.

What I mean is this: The book is meant to be purchased, and therefore, the author would expect that while he’s given me permission to take on such an endeavor, he’s done it with what I’ll assume is the expectation that I won’t give away all the book’s secrets. Personally, I think I’ve done a great job in regard to this balance. If one review heavily shares content in the chapter, the next one won’t nearly as much. The purpose of these chapter reviews, like most things on my site, is most definitely dual purposed. On my site, I write for the reader, but I also write for myself, too. If I want to remember something well, and think it would be beneficial to the PowerShell community, then it’ll end up being discussed right here.

Same goes for this book. As I read these chapters, writing helps the reader potentially better understand a concept we’re reading together, for those reading along. For those that aren’t, then potentially, they’ll get themselves a copy and read along one day, and return here for a mostly comprehensive review. I’m also helping myself too. These concepts make more sense when I review them; when I force myself to document what I’ve read. And that’s what I’m doing here, reinforcing what I’ve learned for the beneficial purpose of both you, and me. Now back to that next chapter review.

The Pester Book Chapter Review (16)

Table of Contents – Infrastructure Validation

This chapter is the one I’ve been expecting all along, and that’s most likely due to it being a selling point of Pester, in my opinion. That’s infrastructure validation, or infrastructure testing, and I’ve seen it discussed in several blog posts prior to its chapter breakdown here. This testing had its hand in how I first used Pester, and I believe it’s one way to get people uninterested in Pester, interested in Pester.

When I started my chapter reviews on The Pester Book, I did so with a story of how I had previously used Pester. You can read it in my introduction post. It discusses the need to verify multiple settings on a work group server in AWS. As we didn’t have Active Directory, a good deal of settings required automation and instead of manually checking that my automation had done what it was supposed to do — which just seems weird anyway — I used Pester to verify my systems were built out as expected. It was a moment in which I was proud, and a part of ensuing that I would know Pester, as well as I can one day. The whole did-it-actually-do-what-it-was-expected-to-do mentality, is a bit of shift after the first 14 chapters.

This chapter does that same thing — automated checking and verification — but does so as it steps away from what we’ve been learning all along. We’re not worried about breaking external dependency, such as we do with unit testing, and instead we need to test that dependencies are actually in place. If we’re creating users in Active Directory, we need Active Directory. If we’re using a CSV file of users to create, we need a CSV. Even more, we need to know that the file contains the data we’re expecting. All these things, are the dependencies we require in order to create the users in the directory. This was in fact the example used by the book, and it was a helpful breakdown of this entire process.

What’s interesting, is that when I think thought infrastructure, I often considered hardware, or at least VMs. Like, real honest pieces of infrastructure. I didn’t actually think of users, and therefore, this chapter’s example was beneficial, as infrastructure can in fact be users. I can buy into that, especially in relation to infrastructure testing.

And now, moving along. We have a couple more chapters in this part of the book.

Update: I located an image of the Pester testing mentioned here and in my introduction post, as well. It’s been included below. It took only 950 milliseconds to completely check that my machine was built property. It checks for Registry entries, a certificate, PowerShell modules, and more. I couldn’t even do the first test manually — checking for a Registry subkey — in that amount of time. I’d be lucky if the Registry would even open in under a second.

The Pester Book Chapter Review (15)

Table of Contents – Working with Pester Output

After the length of the last chapter, this one, was much appreciated. That said, the last chapter may have been the best one thus far, so don’t skip it. I suspect I may head back and read it again, a time or two. In this chapter, however, we covered Pester output. Let’s review what we learned during this portion of The Pester Book.

The main goal of this chapter was to discuss some of the output options offered by Pester. There isn’t much. Hopefully you have something that’ll consume nUnit XML. When I was first searching for Pester output options, I had to do some work to get what I as after. I even wrote about it, and that was long before I started this book and these reviews.

So anyway, you have nUnit XML or this post. I didn’t know as much about Pester then, and I still don’t hate that post, so it may be worth something to you. See you after next chapter.

The Pester Book Chapter Review (14)

Table of ContentsAdding Tests – Again

If you haven’t yet read this chapter yet, then buckle up. It’s purposely long, as Adam indicates that he didn’t go into a good amount of detail in the last take-an-existing-function-and-add-tests-to-it example/chapter. With that, let’s discuss.

The first few sections we’re actually quite helpful. The whole thing was; don’t get me wrong. But these sections, more or less discussed something that’s important to me, and that’s using functions, and ensuring that they’re small and single purposed. It wasn’t word-for-word, but I’ve often said and written that I’d rather troubleshoot five 20 line functions, than one, one hundred line script. The book and I weren’t exact on words; however, we were on meaning. It’s much easier to handle things in small amounts. Think, checkbook registers — for those still using one — it’s much easier to enter things in small batches, as you spend your money, than to save up all your receipts until the end of the month, and then enter them. So seriously, let’s shoot for function writing only, and making them small and simple.

We also discussed the relation of the number of parameters to that of the number of tests. It makes sense to me, as each will add more ways in which the code will need to be tested. We covered using various types of parameter validation to limit the number of tests, as well, and then using helper functions to remove some of a function’s required, in-function work. We took one function and made three, and in doing so, made testing — and even supporting it — an easier thing to do. At first glance, I wasn’t sure there was that much we could alter; the function looked good to me, and yet we did remove some work from it, to be shared across helper functions — it was good to see.

Once we had our slimmed down function, we discussed flow, code paths, creating tests for the shortest code path, as well as other code paths, and saw some great examples of mocking. We’re still working with unit testing, and so you’ll appreciate the mocking examples in this chapter, if you’d like to see more. I did. Like the last one, this chapter helps make this book. While I enjoyed learning the basics from Part I, this has gotten much more interesting, to no surprise.

The Pester Book Chapter Review (13)

Table of ContentsAdding Tests for a Function

In this chapter, the overall idea was to take an existing function, such as you might have sitting around right now, and write tests for it. There are likely functions and tools that we already have that don’t have a tests, and with the help of this chapter can start thinking through the logic of writing tests. This chapter makes perfect sense, and for me, lines up well. That’s what’s I’ve been doing — writing tests for an existing function I’ve authored. That said, I can’t wait to start my next tool from the beginning and experiment with TDD, and getting those tests in place before I start writing my solutions to pass the tests.

In regard to writing tests, as that’s what we’re after here, I highlighted the below two sentences. It basically says this: “It’s okay if you don’t incorporate all the test possibilities right away. You can come back and add more later.” I really needed to hear this.

As we moved through the chapter, we walked and talked though various things we would test against Warren Frame‘s Invoke-Parallel function. I won’t spend anytime going over the tests, or the function, but I really did appreciate the walk though experimentation and out loud thinking of this chapter. I picked up a few hints, and I’ll share one before wrapping up. It’s okay to include more than a single Should comparison in the same It block, providing they make sense together. If including multiple assertions makes sense to your It block’s purpose, then do so freely. Good to know, and great chapter.

The Pester Book Chapter Review (12)

Table of ContentsDesign Practices

Well, we’ve started Part II; it’s official.

The Design Practices chapter of The Pester Book went a little bit of everywhere, and no surprise really, when you consider the topic. Design practices are going to be a consideration at all points of your Pester authoring. This chapter began with the discussion of tests, and how they are forever. Testing isn’t something we do once, before a final release. It’s something we do before every release. We’ve likely all been troubled by code changes before that ended up doing more harm than good, as a new fix or feature broke previous fixes and features. By continually testing, we can ensure our code modifications only add to the tools we create, as we ensure that previous tests continue to pass.

We learned about being certain, beyond a doubt, that we’re testing the proper script or function, when it’s quite possible that we have more than one version of a script, or module, or function, on the same system. I pretty much read this as, always include the code necessary to ensure you’re working the correct code. It makes sense to me that everyone just simply get into this habit now.

We also got to look at the below three lines of code; it seems like I see them everywhere. They are a product of the New-Fixture Pester function. They are included in the .Tests. file created by this function; a function that produces a script file, and test file for the script file that includes a failing test. Remember, we write our tests first, ensure that each fails, and then start coding our solution, which in turn corrects our tests.

$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
. "$here\$sut"

While I didn’t find it in the book first — although, I did determine it is included — I stumbled across the meaning of $sut earlier yesterday. It stands for system under test. The next thing we covered was how to modify our tests files when working with modules. The code included in the book was substantially different from the code above. I’m certainly glad I don’t have to figure that one out myself — thanks, Adam.

The chapter continues on to discuss the Input/Execution/Output pattern — I can kind of seeing myself use this pattern. The best part after the chapter opening, however, was the discussions on Describe blocks, naming conventions, and tagging. It was nice to see the preferences of someone else. For me, I cannot seem to stop adding colons after the Name parameter values for the Describe, Context, and It blocks. They should just be there by default… to me, at least.

Describe -Name 'Advanced Function Template 2.3.4:' {
    Context -Name 'Tests without including parameters:' {
        It -Name 'Testing empty Advanced Function Template:' {
            ___-_________ | Should -Be $null
        } # End It.
    } # End Context.
} # End Describe.

Describing Advanced Function Template 2.3.4:

  Context Tests without including parameters:
    [+] Testing empty Advanced Function Template: 242ms

Off to the next chapter.

The Pester Book Chapter Review (11)

Table of Contents – The TestDrive Drive

Today we’re going to discuss the final chapter in Part I of The Pester Book. It’s time to discuss the TestDrive. But before doing that, let me point out that you may want to go back and review the Mocks chapter. While it’s not directly tied to the TestDrive, that entire chapter covered a good deal of information — know that stuff. Those last few sections were intense! And after that sentence, I would like to mention that I rarely use exclamation points.

Okay, so moving on. Remember that in unit tests, we want to be dependent of all entities outside of our tests. This includes databases, Active Directory, and anything else that has to be in place for a function to properly execute. This includes the file system, too. If it has to be there, and it’s separate from our test and the code that we’re testing, then it needs to removed mocked.

We don’t really want to actually modify the file system of the system on which our tests are running. Again, we don’t want to require any dependence on our system; it’s an important distinction of unit tests. We have a “drive” we can use in our testing without any real disturbance to the underlying operating system.

See the book for some solid examples of how the TestDrive is scoped. As many things in Pester do, the TestDrive works differently here and there, and it’s best to learn it now, instead of later, in that stuffing some of this in your mind now, might save time when you’re having to revisit this alone. A couple pointers I do want to write down myself, however: One, tests cannot access a TestDrive in a different Describe block, other than the one in which they are executing. Two, Files created directly in a Describe block can be accessed by Context blocks contained in that same Describe block. I think I got it right.

Oh yeah, there’s also a variable created that you can use. Take a look at that, as well as what values are displayed when I return all my FileSystem PSDrives, from within a test (yes, using Write-Host).

Clear-Host
Describe 'TestDrive system location:' {
    Write-Host $TestDrive
    Write-Host (Get-PSDrive -PSProvider FileSystem)
}

Describing TestDrive system location:
C:\Users\tommymaynard\AppData\Local\Temp\b41d3954-dece-3a2c-9b14-e0206a3a5d63
C D S TestDrive X

Time to start Part II. See you then.

The Pester Book Chapter Review (10)

Table of ContentsMocks

The Mocks chapter of The Pester Book has several sections. The final paragraph, of the final page in the final section says, “Mocks are by far the hardest concept in Pester to wrap your head around but are critical in creating good unit tests.” Now, jumping back to the beginning of the chapter, and we have this quote: “Mocks are one of the most important concepts in Pester yet also the least understood.”

Another way to say all this, would have been, “pay attention — it’s about to get good, and if you don’t pay attention, you might as well put the book down.” Well, that didn’t happen for me. Let’s review.

This chapter gives us our first real example of using Mocks. Remember from a few chapters and days back that the first type of test we want to write is a unit test. It’s the smallest test. But, that’s not the most significant part — the most significant part is that it’s a standalone test, that needs all it’s dependencies removed. What’s the mean? This is chapter opens with a walk through where we create a function that reads from a CSV file, and uses the username obtained from the document inside a call to Get-ADUser. If we remove dependence, then we remove this need for a CSV file, and an Active Directory environment. Think about that. Or rather, think about the PowerShell you’ve written in the past. Your testing probably needed all those things. Didn’t it? Yeah…, we know.

You’ll enjoy the opening to this chapter. I did. There’s something exciting about watching a successful test that requires a CSV file and AD, suddenly not need either one.

The chapter closes with a few small sections: Mocking Specific Object Types, Mock Scope, Module-Level Mocks, Parameter Filters, Mock Assertions, and Asserting A Single Mock, just before the chapter’s Wrap Up. Every one of these was important, and vital, to the complete Mocking topic. Read them; they are all very important to fully comprehend!

The Pester Book Chapter Review (9)

Table of ContentsTest Cases

It’s a chapter like this, if you didn’t know it before, that you suddenly realize how much more powerful Pester is than you may have first thought. Test cases allow us to reuse an It block multiple times. Each time we use it, we can pass in different values that we want our parameter(s) to have, and record what happens when each of those are used. This might be confusing in text alone, so let me show you an example that I came up with.

Clear-Host
Describe -Name 'add two numbers:' {
    $TestCases = @(
        @{Number1 = 1; Number2 = 1; Total = 2; TestName = '1 + 1'}
        @{Number1 = 2; Number2 = 2; Total = 4; TestName = '2 + 2'}
        @{Number1 = 3; Number2 = 3; Total = 6; TestName = '3 + 3'}
        @{Number1 = 4; Number2 = 4; Total = 8; TestName = '4 + 4'}
        @{Number1 = 5; Number2 = 5; Total = 10; TestName = '5 + 5'}
    )
 
    It -Name 'Testing addition of two numbers <TestName>:' -TestCases $TestCases {
        Param ($Number1,$Number2,$Total)
        $Number1 + $Number2 | Should -Be $Total 
    } # End It.
} # End Describe.

I’ll quickly point out a few things we learned in this chapter: We’re now using a new It parameter called TestCases. This parameter accepts an array of hash tables, Yes, you read that correctly, and each one is tested against the It block. In our example, two of the hash table’s key-value pairs serve as the values to the Param block. The TestName value, however, ends up being stuffed into the It block’s Name parameter, allowing us to differentiate between which test is which.

Here’s the results the above code produces.

Describing add two numbers:
  [+] Testing addition of two numbers '1 + 1': 52ms
  [+] Testing addition of two numbers '2 + 2': 10ms
  [+] Testing addition of two numbers '3 + 3': 25ms
  [+] Testing addition of two numbers '4 + 4': 28ms
  [+] Testing addition of two numbers '5 + 5': 32ms

It is a chapter such as this, and even Pester on its own, that make you realize that you have to have some sort of grounding in PowerShell function writing to be successful. And maybe not function writing, maybe script writing as well, providing you understand how to include parameters in your code. It’s important you’re comfortable with PowerShell long before you tackle Pester — just putting that out there.

Next is Mocks; can’t wait!

Update: I made a slight change to the above code. While it produces the same results, what I did was this. Instead of calculating the Total inside the It block, we send in what the total should be as the Total parameter value. This ensures that if the Number1 or Number2 parameter values are changed, that the test actually fails. When the total is calculated in the It block, it’s always going to pass, and I didn’t want that to be the case.