Processed with VSCO with j2 preset

In the previous post we saw how methods i.e. functions can be implemented with PowerShell. Functions are not only a great way to structure code for reuse but also allow to create larger scripts. Whenever writing code that ends up in production it is always a must to ensure that the code runs as expected. When the Script is small or does not invoke any long running services we can do this quite simply by executing the script. However the more complex a script becomes or is integrated into long running processes the harder it becomes to ensure that the script is still running as intended after changes.

This is where automated Testing allows to ensure functional correctness without demanding any great user interaction to execute multiple test scenarios.

Writing automated Tests

PowerShell comes with it’s own testing framework called Pester. Which is the de facto standard PowerShell testing framework and comes with every installation of Windows 10. Pester follows a Behavior Driven Development (BDD) test-development style. I’ll leave it up to you to follow up on the difference between Test Driven Development (TDD) and BDD, for a framework it usually shows in a more human friendly description of the tests.
Let’s get started by having a look at what we want to do in a C# context.

For the C# samples we will be using the xUnit.net framework which follows the xUnit pattern. Let’s assume we have the following class we would like to test:

We could verify the functionality with the following test:

For PowerShell the same function could look like this:

And the corresponding test function looks like this:

From the structure there is a lot in common.

Note that Pester strongly nudges the developer to go along with a certain naming pattern for files. When a function is in a file called Something.ps1, the corresponding tests should be in the file Something.Tests.ps1.

When we execute the PowerShell test from the PowerShell IDE console pane we get the following result in the PowerShell Window.

Showing console output of the testrunner (executed in VS Code)

There are multiple assertions you can use within pester as one can see in the following overview:

  • Should Be
  • Should BeExactly
  • Should BeNullOrEmpty
  • Should Match
  • Should MatchExactly
  • Should Exist
  • Should Contain
  • Should ContainExactly
  • Should Throw

Mocking external dependencies

When writing automated tests one topic quickly arises and that is how to manage dependencies to the outside world. When writing automated tests we can separate them into different categories:

Unit TestsTesting the core logic of code. Tests that logic has been implemented according to specs and ensures that the core building blocks are working correctly. No dependencies to other code e.g. Modules in PowerShell. Should make up the majority of automated tests in a project.
Integration TestsTest a part of an application i.e. Script. Ensuring that the tested parts work together which may involve calling services outside of the script itself.
These tests are usually the easiest to implement but are more fragile than unit tests. An error might be caused by an other system or a logic error in the script. In large projects you should have more Unit Tests than Integration Tests.
System TestsTest entire use case scenarios end to end. These tests should run scenarios of the script e.g. “Setup new Web Server Instance”, “Setup new DB instance”. They usually take a long time to run and may require upfront work regarding infrastructure i.e. a staging/testing environment.
In general you should only test your core scenarios with System Tests. They usually take a lot of upfront investment to create the environments and also require a lot of maintenance since they have to be adapted once a change to the system is made.

Since PowerShell was mainly created for automating infrastructure tasks, most of the code you would write is interacting with one or multiple systems in one kind or the other. As long as our scripts are only reading we might not feel the need for mocking our services i.e. as long as they are not overly slow. But when we start writing to production systems we surely do want to be certain that our scripts run as intended. And this is where mocking comes in. Under C# there are multiple libraries for mocking external dependencies of a class. A very popular one (and my personal favorite) is Moq.

So let’s assume we want to mock an external dependency which returns us all the entries in a directory. We would write it something like this in C# (a bit lenthy I know...):

Now in PowerShell we would implment the function as follows:

And Pester provides a handy mocking functionality:

Not only is this a great way to test our code without having to actually be on the filesystem but it also shows how we could mock other dependencies such as a system clock (midnight testing anyone?), network calls etc. which for one will ensure that the script does not actually invoke any external sources. Another benefit you will most probably see is a speed up in execution time. Since everything is running from in memory (aka fast Winking smile) there is no network or disk delay. For further information and options on mocking check out the official documentation of Pester.

Executing the Tests

We can also execute the test from the command line with the following command:


The command can be extended with parameters described here. While skimming through the parameters you may notice that they would provide the means to enable Continuous Integration (CI) for PowerShell Scripts. This is the case, we could add a Step to a Visual Studio Team Service (VSTS) or Team Foundation Server (TFS) build configuration by adding a PowerShell step with the following parameters:

If you already have a build server setup (you can get VSTS for free within minutes….), it is easy to setup a CI job for your scripts. And CI can be a real cure to sleep problems – so if I can have it this cheap the answer is yes please Smile


In this post we went through how to write tests with PowerShell and execute them. Further we saw how we can mock dependencies. We further looked at how tests can not only be executed during development but also how we can execute the tests in an automated build process i.e. Continuous Integration (CI) environment.


Check out my previous posts on how to get started with PowerShell for the C# developer:

You can find more detailed information about Pester on their Project Page.

External References


In the first part of the series we covered the development environment setup on how to get started with PowerShell. Now lets dive into some code. PowerShell can be used as a dynamic language. For a C# developer this can be one of the most frustrating points. In this post we will look at the following points:

  • Variables
  • If/else
  • Loops and Piping
  • Methods
  • File handling

So let’s get going Smile


When we look at a simple program of C# it might look something like this.

using System;
namespace ConsoleApplication
public class Program
public static void Main(string[] args)
string name = "Harvey Specter";
int number = 42;
Console.WriteLine($"Hello{name}, your number is{number}");
view raw Program.cs hosted with ❤ by GitHub

Now in comparison here is the equivalent PowerShell code.

Note that we do not need any Class or Method to get started. Simply start writing your script. Now variables are interesting under PowerShell. Lets add some more info to our PowerShell code to retrieve the type of the variables. The variable is assigned a type when a value is assigned. Since PowerShell is not compiled there are some potential pot holes a typical C# developer might into. For starters this is a totally valid statement.

Resulting in the following output:

Variable is first of Type Int32 after assignment of a string has the type String.

We can be more strict in PowerShell by defining the type of the variable which will make the second assignment illegal. But this requires some additional effort on your end.

If we would run the strict assignment we would be greeted by an error message which is more of what a C# developer would be used to.

And one more thing. Even though the variable $neverDefined never got defined. Well we can still access it’s value without an exception or error being raised.

PowerShell output showing that the variable $neverDefined simply shows an empty string

Keep this in mind while developing since they might just come around and bight you in the foot later on.

Conditional Operators

When writing conditional code in C#, the standard choice is using if and else or for multiple options a switch/case. So a possible option would be to use them as follows:

Apologizing to all the readers who have to work shifts Winking smile Lets look at how the same code would be implement in PowerShell:

No huge changes or surprises So no surprises here. The major difference is the equality sign in the if check. Here is a small translation table of the equality signs you find in C# and PowerShell:







Not Equal



Greater Then



Less Then



Greater or Equal



Less or Eual



Loops and Piping

There are many different constructs for looping in C#: for, while, do while and ForEach. So if we look at all the different types of loops in C#:

In PowerShell the equivalent can be  implemented like so:

Now the ForEach loop is really great when having to iterate over a list of items. This is often what we end up doing e.g. “Iterating over a list of people to get the count by city” or a bit more PowerShelly “Iterate over number of host information to ensure that everything is okay and no action is needed”. While we could write that with the above for loop, there is a PowerShell called piping. Piping allows us to Take a collection and forward it to the next operation. We could rewrite the ForEach sample as follows:

Pretty cool no? Smile We can even use the ForEach construct to loop over every item being forwarded:

Note that $_ is always the current item we are going over in the ForEach Loop. The equal construct in C# is achieved with Extension Methods. Piping can be great to enhance readability since one can see the flow. But it also can make the code harder to debug, so be sure to keep the balance here.

Note: Even though foreach is an alias for ForEach-Object they behave differently. When using foreach the operation is paused until all elements are to be processed are present, in case of ForEach-Object it will process the items as they come in. This may lead to some unexpected side effects…


In this Blogpost we saw the basic programming structures in PowerShell compared to how they would be implemented in C#. Keep in mind that PowerShell is more dynamic and forgiving at runtime than C# which might lead to some unwanted side effects. In the next Post we will look at how we can implement Methods and work with Parameters which are not only handy for methods but also for Command Line Interface parameters.


There is more in this blog post series:


Screenshot of a Windows Powershell from WikiPedia

Lately I have been doing some work with PowerShell. PowerShell is a well known in the Windows IT Pro space when it comes to the automation of tasks. In todays fast paced world the idea of automating mundane tasks is an attractive idea. PowerShell brings forward the basic toolset to automate, not just mundane tasks, but set up entire environments. Since I do most of my day work in C# I wanted to share some of my insights into developing with PowerShell. Which should just be enough to get into trouble Winking smile


The development environments

PowerShell comes right out of the box on Windows 7 or higher machines and even comes with it’s own editor the PowerShell Integrated Scripting Environment (PowerShell ISE). PowerShell ISE allows you to edit PowerShell files which includes code highlighting and IntelliSense and run them in Debug mode (F5) or running the selected code parts (F8). It is even possible to set breakpoints (F9) which should make C# developers feel right at home.


An interactive PowerShell displays the output of the running script. The shell also comes in handy while debugging your code. At a given breakpoint you can inspect the variable by typing it's name into the console. There only rant I have about the PowerShell ISE is that the console not be reset. The only way this can be achieved is by restarting the editor and having to open (all) the files again.

Visual Studio

As a C# developer the daily driver usually is Visual Studio. If you can’t bear the thought of using a different Editor. Well you are covered. The experience is much like with the PowerShell ISE. So if you have any Visual Studio Plugins such as VsVim you do not want to miss this may be your preferred route.


If you haven’t installed PowerShell during the initial installation of Visual Studio. You can add PowerShell by modifying your Visual Studio installation. Open Programs and Features, choose Visual Studio and then select Change. In the dialog select Modify and choose PowerShell Tools for Visual Studio. Finally select Next.You might want to get a cup of your favourite beverage while the installation is taking place.

Visual Studio will create it’s usual Solution and Project files. This will result in some extra clutter that your average PowerShell developer might not recognise. Keep this in mind when you check those files into your repo.

Beyond Windows

PowerShell is usually run on top of the .Net Framework. As of lately PowerShell also supports running on .Net Core. This means your PowerShell scripts are not limited to Windows. You can write them also for Apple and Linux machines. One of the PowerShell editors of choice for Linux and Mac, would be Visual Studio Code and the PowerShell Plugin for it.


You can see an extensive description on how to use PowerShell with Visual Studio Code on the msdn website.

Why choose PowerShell over C# or CScript

reactions why ryan reynolds but why

Since PowerShell runs on the .Net Framework, why should we use PowerShell in the first place? Wouldn't it be easier to just write the code with C# in the first place? One of the best arguments in my opinion comes from the reason why PowerShell came to be. It is designed from it's roots up to automate IT tasks. There are many hooks in the OS or other major Services. Active Directory, IIS, Exchange and many more provide interfaces that can be consumed with PowerShell. So if your task is to automate a Windows environment, PowerShell will be able to consume and interact with many existing APIs. Making the task easier and less time consuming.

A fun fact is that the UI for configuring IIS actually performs PowerShell commands in the background. The identical commands are used when invoking them through a PowerShell script.

Since we are writing infrastructure code there is a good chance that an Ops person will end up maintaining it. There is a good chance that this person has an interest in putting in the effort of learning PowerShell. Since it is their day job and PowerShell is sought out to enable them during their daily tasks.

And third, it is always fun to dive into a new programming language. And finally PowerShell has a way to interact with C#. So if the need ever arises to get stuff done the good old C# way there is nothing stopping you Smile

Hello PowerShell

Before we end this post, let’s see the Hello World Example:

echo "Hello PowerShell"

Jup that is it, one line and we are done.

In the next post we will dive into the basics of writing PowerShell code.


There is more in this blog post series: