Testing DSC Configurations with Pester and AppVeyor

I spent the last few days tinkering with AppVeyor. It’s an interesting service to help enable continuous integration and delivery in the Microsoft ecosystem.

Last night I realized it might offer a simple means to test the outcome of your DSC configurations. Here’s the recipe for a simple POC, with plenty of room for you to tweak and integrate with your existing processes:

  • Create a DSC configuration you want to test
  • Create a short script to apply that configuration
  • Create some Pester tests to verify the desired state of your system, post configuration
  • Create the AppVeyor yaml to control this process
  • Add this to an appropriate AppVeyor source (Example covering GitHub)
  • Test away! Make a change to the DSC code, commit, and AppVeyor spins up a VM, applies the DSC configuration, and your Pester tests verify the outcome

This certainly isn’t a perfect method, but it would be a simple way for anyone to get up and running writing and testing DSC configurations and resources.

I’m going to make the assumption that you are familiar with GitHub, Pester, and some of the basics of AppVeyor from my first overview.

Wait, what is DSC?

Windows PowerShell Desired State Configuration is a configuration management platform from Microsoft. It’s still young, but is fast tracked for the Common Engineering Criteria, receives a good deal of attention from the PowerShell team, and the guy who brought us PowerShell is quite excited about it. It’s probably something you should be paying close attention to.

There is quite a variety of resources to get started with. The DSC Book from PowerShell.org is a nice overview, and the soon-to-be-published MVA series was quite helpful (Getting Started, Advanced).

Let’s look at some caveats to testing DSC over AppVeyor.

Yes, but…

  • You could do much of this on your own, with tools like Client Hyper-V and AutomatedLab. You might even have a similar toolset in place at work.
  • No testing of distributed systems. This allows testing on a single VM.
  • Limited selection of operating systems to deploy on. There is an OS option in the yaml, presumably this means we may see more.
  • Your configurations cannot restart the VM. Hoping this will change, but depending on their architecture and design, this may be tough.
  • You’re deploying on a hosted service. If your DSC configurations are integrated with your CMDB and other internal resources, this may be a show stopper.
  • A good DSC resource should have a solid ‘test’ function. That being said, a single DSC resource’s test function might not handle the intricate combination of resources applied to a system.

Right. I’m sure I’m missing others as well. Certainly not perfect, but if your goal is to write and test some general DSC resources or configurations, and you don’t have the tools in house, this is a fantastic and simple way to spin up fresh VMs, configure them with DSC, and verify that the resulting system is now in the desired state.

Another caveat – building your own system that would perform a similar functionality would be an incredibly valuable experience. They always say “don’t re-invent the wheel,” but if your goal is experience and to learn, re-inventing the wheel is a great way to get there!

Pick a source

I’m going to stick to GitHub for this. Keep in mind that AppVeyor is only free for open source projects. Consider your security posture before uploading any sensitive DSC configurations.


Pick a DSC configuration to test

We’re going with an incredibly basic example here:

Configuration ContosoWebsite
param (
[string[]]$ComputerName = $ENV:ComputerName
Node $ComputerName
#Install the IIS Role
WindowsFeature IIS
Ensure = "Present"
Name = "Web-Server""
#Install ASP.NET 4.5
WindowsFeature ASP
Ensure = "Present"
Name = "Web-Asp-Net45"
#Install PowerShell AD... for fun...
WindowsFeature ADPS
Ensure = "Present"
Name = "RSAT-AD-PowerShell"
view raw WebServer.ps1 hosted with ❤ by GitHub

Write a controller script to apply the configuration

There are plenty of ways to do this. Modify this POC example to meet your needs.

# This script will invoke a DSC configuration
# This is a simple proof of concept
"`n`tPerforming DSC Configuration`n"
. .\DSC\WebServer.ps1
Set-Content -Path .\Artifacts.txt
Start-DscConfiguration .\ContosoWebsite -Wait -Force -verbose

Most of this should be self explanatory. We force application of the ContosoWebsite configuration from WebServer.ps1. The one extra bit is that we save the path to the resulting MOF file in Artifacts.txt. We upload this later on.

Write your Pester tests

Go crazy. I wrote some very simple, limited tests for this POC:

Describe "Web Server" {
It "Is Installed" {
$Output = Get-WindowsFeature web-server
$Output.InstallState | Should Be "Installed"
It "Includes ASP.NET 4.5" {
$Output = Get-WindowsFeature Web-Asp-Net45
$Output.InstallState | Should Be "Installed"
Describe "ActiveDirectory Module" {
It "Is Installed" {
$Output = Get-WindowsFeature RSAT-AD-PowerShell
$Output.InstallState | Should Be "Installed"
view raw DSC.Tests.ps1 hosted with ❤ by GitHub

Keep in mind that you aren’t limited to one pass. You could theoretically apply your configuration, test, add a ‘mischief’ script that messes with the configuration, and test to verify that your DSC configuration brings things back in line.

Write the AppVeyor yaml

We’re almost done!  At this point, we’re going to tell AppVeyor what to run. There’s a lot more you can configure in the yaml, so be sure to flip through the options and experiment.

# See http://www.appveyor.com/docs/appveyor-yml for many more options
# Skip on updates to the readme.
# We can force this by adding [skip ci] or [ci skip] anywhere in commit message
message: /updated readme.*/
- cinst pester
build: false
# Invoke DSC configuration!
- ps: . .\Tests\appveyor.dsc.ps1
# Test with native PS version, finalize
- ps: . .\Tests\appveyor.pester.ps1 -Test -Finalize
- ps: Get-Content .\Artifacts.txt | Foreach-Object { Push-AppveyorArtifact $_ }
view raw AppVeyor.yml hosted with ❤ by GitHub

What does this do?

  • We ignore any commits that match ‘updated readme’, to avoid unnecessary builds.
  • We run appveyor.dsc.ps1, which applies the DSC configuration and saves the mof path.
  • We run appveyor.pester.ps1, which invokes the pester script, sends test results to AppVeyor, and tells us if the build passed.
  • We upload the mof file, which will be available on the artifacts page for your AppVeyor project.

Tie it all together

We’re good to go! We create a GitHub repository, add this to our AppVeyor projects, and make a commit (covered here). Browse around the project on AppVeyor to see the results:


That’s it – we now have a simple framework for automated DSC resource and configuration testing. There’s a lot more you might want to do, but the simple POC material is in the AppVeyor-DSC-Test repository on GitHub.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s