powershellpester

How do I use Pester to test for both an error and a wrong value?


I'm trying to test if certain sites has been blocked succesfully for a client using Pester v4.
But I can't figure out how to mark two failed attempts as one single success test.

I'd like to combine two following failure tests in to one

$PrivacyBlackList = @('nexusrules.live.com', 'auc-visio-telemetry.officeapps.live.com')

Describe '- Check MS Telemetry Compliance' {

  Context '- Get Windows and Office Telemetry' {

    foreach ($BlackSite in $PrivacyBlackList) {

      It "Should not succesfully connect to $BlackSite" {
        $ConnectTest = Invoke-WebRequest -Uri $BlackSite -UseBasicParsing -TimeoutSec 3
        $ConnectTest.StatusCode | Should -Not -Be '200'
      }

      It "Should timeout connecting to $BlackSite" {
        {$ConnectTest = Invoke-WebRequest -Uri $BlackSite -UseBasicParsing -TimeoutSec 3} |
          Should -Throw 'The operation has timed out.'
      }

    }# end foreach
  }
}

Describing - Check MS Telemetry Compliance

  Context - Get Windows and Office Telemetry
    [-] Should not succesfully connect to nexusrules.live.com 3.23s
      WebException: The operation has timed out.
    [+] Should timeout connecting to nexusrules.live.com 3.23s
    [-] Should not succesfully connect to auc-visio-telemetry.officeapps.live.com 2s
      Expected '200' to be different from the actual value, but got the same value.
      9:         $ConnectTest.StatusCode | Should -Not -Be '200'
    [-] Should timeout connecting to auc-visio-telemetry.officeapps.live.com 1.19s
      Expected an exception, with message 'The operation has timed out.' to be thrown, 
      but no exception was thrown.
      14:           Should -Throw 'The operation has timed out.'

Pester has no "-Be -Or"...

Edit 1: @mklement0 pointed out that in my simplifed example (now removed) Should -BeIn will solve the simplified example.

Edit 2: Changed simplified example (now removed) to be more in line with my real issue

Edit 3: Changing simplified example (now removed) to do errors :)


Solution

  • The problem you have is that Invoke-WebRequest returns a non-terminating error when it can't connect to a URL, which is why your test is failing.

    You can deal with the error by wrapping the call to Invoke-WebRequest in a try..catch (no need to do anything in the catch block):

    $PrivacyBlackList = @('nexusrules.live.com', 'auc-visio-telemetry.officeapps.live.com')
    
    Describe '- Check MS Telemetry Compliance' {
    
      Context '- Get Windows and Office Telemetry' {
    
        foreach ($BlackSite in $PrivacyBlackList) {
    
          It "Should not succesfully connect to $BlackSite" {
            try { $ConnectTest = Invoke-WebRequest -Uri $BlackSite -UseBasicParsing -TimeoutSec 3 -ErrorAction Stop } catch {}
            $ConnectTest.StatusCode | Should -Not -Be '200'
          }
    
          It "Should timeout connecting to $BlackSite" {
            {$ConnectTest = Invoke-WebRequest -Uri $BlackSite -UseBasicParsing -TimeoutSec 3} |
              Should -Throw 'The operation has timed out.'
          }
    
        }# end foreach
      }
    }
    

    As Santiago Squarzon said, if you want both checks to be a single test you can combine them into a single It:

        It "Should timeout connecting to $BlackSite and not return 200" {
            {$ConnectTest = Invoke-WebRequest -Uri $BlackSite -UseBasicParsing -TimeoutSec 3} | Should -Throw 'The operation has timed out.'
            $ConnectTest.StatusCode | Should -Not -Be '200'
          }
    

    Edit: If you want to make a second check conditional on the outcome of the first, perhaps you could do something like this:

    It "Should not succesfully connect to $BlackSite" {
        try { $ConnectTest = Invoke-WebRequest -Uri $BlackSite -UseBasicParsing -TimeoutSec 3 -ErrorAction Stop } catch {}
        $ConnectTest.StatusCode | Should -Not -Be '200'
    
        if (-not $ConnectTest.StatusCode) {
            { Invoke-WebRequest -Uri $BlackSite -UseBasicParsing -TimeoutSec 3 } | Should -Throw 'The operation has timed out.'
        }
    }