pester / Pester

Pester is the ubiquitous test and mock framework for PowerShell.
https://pester.dev/
Other
3.08k stars 470 forks source link

Should Contain/Match Fails #1075

Closed paraknell closed 6 years ago

paraknell commented 6 years ago

1. General summary

Pester tests fail when you try to see if a file contains a string. i.e

"c:\file.txt" | should contain "some words"

2. My Environment

Win 10 (1803) Pester: 4.3.1 Powershell: 5.1.17134.165 Running in: vsCode and from the CLI

$module = "ModuleName"

Describe "$module Module Tests"  {

  Context 'Module Setup' {

    It "has the a manifest file of $module.psm1" {
      "$here\$module.psd1" | Should Exist
      "$here\$module.psd1" | Should Contain "$module.psm1"
    }
  }

Should return:

Tests Passed: 1

3. Expected Behavior

I'm not sure if this is a bug, an issue with my code or an improvement request. This may have also been a removed feature as I know it was working on version 3.4 of pester, or at least the tests were considered passing then. (Might have been a false positive?)

This would be used to test if a file contained a certain custom function, help options hidden in the comments section, special parameters or other internal details to the code. Please let me know if there is another way of doing this.

Also unsure if this is related to:

121

959

960

4.Current Behavior

This is an example I am trying to run:


Describe "$module Module Tests"  {

  Context 'Module Setup' {

    It "has the a manifest file of $module.psm1" {
      "$here\$module.psd1" | Should Exist #pass
      "$here\$module.psd1" | Should Contain "$module.psm1" #fail
    }
  }

And it fails but I know the file does contain the EXACT formatting and text of the string provided in the variable $module. I have also split these into separate It blocks to verify that it is in fact an issue with the contain statement and not with the existence of the file. This has also been tested with Match and BeLike with mixed results.

I am testing against the string below:

<obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>

In these examples:

Context "These ones Pass" {

      It "should be like reboot with wildcards" {
        @(Get-Content "C:\reboot.txt") | Should BeLike "*reboot*"
      }
      It "should be like full string with no wildcards" {
        @(Get-Content "C:\reboot.txt") | Should BeLike "<obj><att id=`"type`"><val>user-defined</val></att><att id=`"name`"><val>reboot</val></att></obj>"
      }
      It "should have a count" {
        @(Get-Content "C:\reboot.txt").Count | Should BeGreaterThan 0
      }
      It "should have a Length" {
        @(Get-Content "C:\reboot.txt").Length | Should BeGreaterThan 0
      }
    }
    Context "These ones Fail" {
      It "contains reboot text with no backticks" {
        "C:\reboot.txt" | Should -Contain '<obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>'
      }
      It "contains reboot text using backticks" {
        "C:\reboot.txt" | Should -Contain "<obj><att id=`"type`"><val>user-defined</val></att><att id=`"name`"><val>reboot</val></att></obj>"
      }
      It "should be exaclty the reboot text using backticks" {
        "C:\reboot.txt" | Should BeExactly "<obj><att id=`"type`"><val>user-defined</val></att><att id=`"name`"><val>reboot</val></att></obj>"
      }
      It "should be exaclty the reboot text no backticks" {
        "C:\reboot.txt" | Should BeExactly '<obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>'
      }
      It "should contain reboot with wilcards, obviously this should fail" {
        @(Get-Content "C:\reboot.txt") | Should Contain "*reboot*"
      }
      It "should match reboot with ?'s" {
        @(Get-Content "C:\reboot.txt") | Should Match "?reboot?"
      }
      It "should be like reboot no wildcards" {
        @(Get-Content "C:\reboot.txt") | Should BeLike "reboot"
      }
      It "should match the caret symbol" {
        @(Get-Content "C:\reboot.txt").Count | Should Match "<"
      }
      It "should match with wildcards using periods" {
        @(Get-Content "C:\reboot.txt").Count | Should Match ".reboot."
      }
    }
    Context "tests from Contain Examples for further context" {
      It "finds 42 in 1-100" {
        1..100 | Should -Contain 42
      }
      It "contains b in a,b,c" {
        'a','b', 'c' | Should -Contain b
      }
      It "contains Hello in 'Hello' no spaces" {
        "Hello" | Should Contain "Hello"
      }
    }

Output to console:

Executing script .\Contains.Tests.ps1

  Describing Podcast-NoAgenda Module Tests

    Context These ones Pass
      [+] should be like reboot with wildcards 98ms
      [+] should be like full string with no wildcards 15ms
      [+] should have a count 16ms
      [+] should have a Length 16ms

    Context These ones Fail
      [-] contains reboot text with no backticks 68ms
        Expected '<obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>' to be found in collection C:\reboot.txt, but it was not found.
        33:         "C:\reboot.txt" | Should -Contain '<obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>'
        at <ScriptBlock>, C:\Contains.Tests.ps1: line 33
      [-] contains reboot text using backticks 18ms
        Expected '<obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>' to be found in collection C:\reboot.txt, but it was not found.
        36:         "C:\reboot.txt" | Should -Contain "<obj><att id=`"type`"><val>user-defined</val></att><att id=`"name`"><val>reboot</val></att></obj>"
        at <ScriptBlock>, C:\Contains.Tests.ps1: line 36
      [-] should be exaclty the reboot text using backticks 21ms
        Expected strings to be the same, but they were different.
        Expected length: 93
        Actual length:   41
        Strings differ at index 0.
        Expected: '<obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>'
        But was:  'C:\reboot.txt'
        -----------^
        39:         "C:\reboot.txt" | Should BeExactly "<obj><att id=`"type`"><val>user-defined</val></att><att id=`"name`"><val>reboot</val></att></obj>"
        at Invoke-LegacyAssertion, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Should.ps1: line 188
        at <ScriptBlock>, C:\Contains.Tests.ps1: line 39
      [-] should be exaclty the reboot text no backticks 54ms
        Expected strings to be the same, but they were different.
        Expected length: 93
        Actual length:   41
        Strings differ at index 0.
        Expected: '<obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>'
        But was:  'C:\reboot.txt'
        -----------^
        42:         "C:\reboot.txt" | Should BeExactly '<obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>'
        at Invoke-LegacyAssertion, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Should.ps1: line 188
        at <ScriptBlock>, C:\Contains.Tests.ps1: line 42
      [-] should contain reboot with wilcards, obviously this should fail 31ms
        Expected '*reboot*' to be found in collection <obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>, but it was not found.
        45:         @(Get-Content "C:\reboot.txt") | Should Contain "*reboot*"
        at Invoke-LegacyAssertion, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Should.ps1: line 188
        at <ScriptBlock>, C:\Contains.Tests.ps1: line 45
      [-] should match reboot with ?'s 23ms
        ArgumentException: parsing "?reboot?" - Quantifier {x,y} following nothing.
        at PesterMatch, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Match.ps1: line 2
        at Invoke-LegacyAssertion, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Should.ps1: line 185
        at <ScriptBlock>, C:\Contains.Tests.ps1: line 48
      [-] should be like reboot no wildcards 20ms
        Expected like wildcard 'reboot' to match '<obj><att id="type"><val>user-defined</val></att><att id="name"><val>reboot</val></att></obj>', but it did not match.
        51:         @(Get-Content "C:\reboot.txt") | Should BeLike "reboot"
        at Invoke-LegacyAssertion, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Should.ps1: line 188
        at <ScriptBlock>, C:\Contains.Tests.ps1: line 51
      [-] should match the caret symbol 24ms
        Expected regular expression '<' to match 1, but it did not match.
        54:         @(Get-Content "C:\reboot.txt").Count | Should Match "<"
        at Invoke-LegacyAssertion, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Should.ps1: line 188
        at <ScriptBlock>, C:\Contains.Tests.ps1: line 54
      [-] should match with wildcards using periods 29ms
        Expected regular expression '.reboot.' to match 1, but it did not match.
        57:         @(Get-Content "C:\reboot.txt").Count | Should Match ".reboot."
        at Invoke-LegacyAssertion, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Should.ps1: line 188
        at <ScriptBlock>, C:\Contains.Tests.ps1: line 57

    Context tests from Contain Examples for further context
      [+] finds 42 in 1-100 67ms
      [+] contains b in a,b,c 11ms
      [+] contains Hello in 'Hello' no spaces 15ms
Tests completed in 532ms
Tests Passed: 7, Failed: 9, Skipped: 0, Pending: 0, Inconclusive: 0

Be like seems to be the best solution at this point but I need to test it against the whole string and I'm not sure this is the best way of doing things.

5. Possible Solution

Nothing currently.

6. Context

I am trying to ensure that all my files I am using to hold API data actually contain that data. I need to have it know that an xml based string of code exists within that file. This is mainly used on an API for rebooting NAS/Server devices and I need to ensure that the xml code being used is in fact found before running through the rest of the script.

mikeclayton commented 6 years ago

Hi @mwtilton,

It looks like the Should Contain assertion was renamed to Should FileContentMatch in Pester 4. The Should Contain assertion is now basically a wrapper around the built-in PowerShell -contains operator.

Your original test as it was written:

"c:\file.txt" | should contain "some words"

can be changed to this instead to check the contents of a file:

"c:\file.txt" | Should -FileContentMatch "some words"

There's some additional documentation for upgrading from Pester 3 to Pester 4 here:

https://github.com/pester/Pester/wiki/Migrating-from-Pester-3-to-Pester-4

Hope this helps.

M

paraknell commented 6 years ago

This seems to have resolved my issue thank you so much! Thanks for the link as well as that seemed to help migrate some old version files as well.