Showing posts with label Pester. Show all posts
Showing posts with label Pester. Show all posts

Tuesday, December 02, 2014

Using Pester to validate DSC resources and configurations Part 2

Pester tests are like any other script. They grow and evolve over time. Here are a few more tests that I have testing my DSC resources and configurations that I recently added to my collection. 

Does every resource have a pester test?
This is probably one of the most important tests I have. Every resource should have a test, so why not test for that?

describe "DSCResources located in $PSScriptRoot\DSCResources" {

  foreach($Resource in $ResourceList)
  {
    context $Resource.name {

      it "Has a pester test" {

        ($Resource.fullname + "\*.test.ps1") | should exist
      }

If it is a standard resource, does it have the files it needs?
Each DSC resource needs to have two files in it. A *.psm1 file and a *.schema.mof file. I use the *.psm1 file as a quick way to identify standard resources differently than a composite resource. I know I will not ever reach a test condition that would cause once of these to fail, but I left it in place so I could change the logic later.

if(Test-Path ($Resource.fullname + "\$Resource.psm1"))
{

  it "Has a $Resource.schema.mof" {
                     
    ($Resource.fullname + "\$Resource.schema.mof") | should exist
  }
 
  it "Has a $Resource.psm1" {
                     
    ($Resource.fullname + "\$Resource.psm1") | should exist
  }

Does it pass Test-xDscSchema and Test-xDscResource tests?
I may as well test for these as part of my pester tests. They already validate a lot of things that are easy to overlook.

it "Passes Test-xDscSchema *.schema.mof" {
  Test-xDscSchema ($Resource.fullname + "\$Resource.schema.mof") | should be true
}
 
it "Passes Test-xDscResource" {
  Test-xDscResource $Resource.fullname | should be true
}

If it is a composite resource, does it have the required files?
A composite resource uses different files than a standard resource. It has a *.psd1 and a *.shema.psm1 that should exists. I don’t have any Test-xDSC functions for the composite resources so I add a few extra checks. I verify that the *.psd1 file references the *.psm1 and that the module does not throw any errors when dot sourcing it.

else
{
  it "Has a $Resource.schema.psm1" {
                     
    ($Resource.fullname + "\$Resource.schema.psm1") | should exist
  }
 
  it "Has a $Resource.psd1" {
                     
    ($Resource.fullname + "\$Resource.psd1") | should exist
  }
 
  it "Has a psd1 that loads the schema.psm1" {
 
    ($Resource.fullname + "\$Resource.psd1") | should contain "$Resource.schema.psm1"
  }
 
  it "dot-sourcing should not throw an error" {
 
    $path = ($Resource.fullname + "\$Resource.schema.psm1")
    { Invoke-expression (Get-Content $path -raw) } | should not throw
  }


I hope you find this examples useful. If you want to see more, take a look at part 1.

Monday, November 03, 2014

Using Pester to validate DSC resources and configurations

The more I use Pester, the more I like it. I found some ways to leverage it in validating my use of DSC Resources and configurations. Here are some samples to give you an idea of what I am talking about.

Are my resources loaded?
Often I will create a new resource thinking it will work only to not have it loaded for some reason. At the moment all my resources are in the same module. So I have this test to use my folder structure to test for a loaded resource.

$LoadedResources = Get-DscResource

Describe “DSCResources located in $PSScriptRoot\DSCResources" {
    $ResourceList = Get-ChildItem "$PSScriptRoot\DSCResources"
   
    Foreach($Resource in $ResourceList){
        It "$Resource Is Loaded [Dynamic]" {
            $LoadedResources |
                Where-Object{$_.name -eq $Resource} |
                Should Not BeNullOrEmpty
        }
    }
}


Can  my resource generate a mof file?
The next thing I want to know is if it will generate a mof file. I create a test like this for every DSC resource. I use the TestDrive: location to manage temporary files.

Describe "Firewall"{
    It "Creates a mof file"{
        configuration DSCTest{
            Import-DscResource -modulename MyModule  
            Node Localhost{
               Firewall SampleConfig{
                    State = "ON"
               }
            }
        }
        DSCTest -OutputPath Testdrive:\dsc
        "TestDrive:\dsc\localhost.mof" | Should Exist
    }

Do my Test and Get functions work?
For some of my resources, I even test the Get and Test functions inside the module. I first have to rename the script so I can load it. Also notice I use a Mock function to keep the Export-Module from throwing errors.


$here = Split-Path -Parent $MyInvocation.MyCommand.Path

Describe "Firewall"{
    Copy-Item "$here\Firewall.psm1" TestDrive:\script.ps1
    Mock Export-ModuleMember {return $true}

    . "TestDrive:\script.ps1"
    It "Test-TargetResource returns true or false" {
        Test-TargetResource -state "ON" |
            Should Not BeNullOrEmpty
    }

    It "Get-TargetResource returns State = on or off" {
        (Get-TargetResource -state "ON").state |
            Should Match "on|off"
    }
}

Edit: I added a part 2.