ticketmaster / poshspec

Infrastructure Testing DSL running in Pester
MIT License
183 stars 32 forks source link

How to use "File Should Contain" rule #59

Closed StefanScherer closed 6 years ago

StefanScherer commented 6 years ago

I'm using Poshspec for some minimal integration tests installing in our CI builds. I have a new use case to check the contents of some files. But I have problems using the File xxx { Should Contain 'yyy' } rule.

My test file:

PS C:\projects> cat test.txt
hello world

My test script:

PS C:\projects> cat .\test.ps1
#Requires -Module Poshspec

Describe 'Files' {
    File C:\projects\test.txt { Should Exist }
    File C:\projects\test.txt { Should Not Exist }
    File C:\projects\test.txt { Should Contain 'hello' }
    File C:\projects\test.txt { Should Contain 'other' }
}

Running the test doesn't work. It seems that Poshspec just uses the file name and checks if the pattern is contained in the string.

PS C:\projects> .\test.ps1

Describing Files
  [+] File 'test.txt' Should Exist 20ms
  [-] File 'test.txt' Should Not Exist 16ms
    Expected path 'C:\projects\test.txt' to not exist, but it did exist.
    1: 'C:\projects\test.txt' | Should Not Exist
    at Invoke-LegacyAssertion, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Should.ps1:
line 188
    at <ScriptBlock>, C:\Program Files\WindowsPowerShell\Modules\Poshspec\2.2.1\Private\Invoke-PoshspecExpression.ps1: l
ine 13
  [-] File 'test.txt' Should Contain 'hello' 32ms
    Expected 'hello' to be found in collection C:\projects\test.txt, but it was not found.
    1: 'C:\projects\test.txt' | Should Contain 'hello'
    at Invoke-LegacyAssertion, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Should.ps1:
line 188
    at <ScriptBlock>, C:\Program Files\WindowsPowerShell\Modules\Poshspec\2.2.1\Private\Invoke-PoshspecExpression.ps1: l
ine 13
  [-] File 'test.txt' Should Contain 'other' 19ms
    Expected 'other' to be found in collection C:\projects\test.txt, but it was not found.
    1: 'C:\projects\test.txt' | Should Contain 'other'
    at Invoke-LegacyAssertion, C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\Functions\Assertions\Should.ps1:
line 188
    at <ScriptBlock>, C:\Program Files\WindowsPowerShell\Modules\Poshspec\2.2.1\Private\Invoke-PoshspecExpression.ps1: l
ine 13

Another question BTW: How can I get an exit code != 0 if one of the tests fails, so I can abort my CI build?

StefanScherer commented 6 years ago

Hm, strange. This happens in AppVeyor, Contains and Not Contains doesn't seem to work.

I run now a Windows container and only install poshspec and in this container it works.

PS C:\projects> .\test.ps1
Describing Files
 [+] File 'test.txt' Should Exist 478ms
 [-] File 'test.txt' Should Not Exist 217ms
   Expected: C:\projects\test.txt to not exist, but it was found
   1: 'C:\projects\test.txt' | Should Not Exist
   at <ScriptBlock>, <No file>: line 1
   at <ScriptBlock>, C:\Program Files\WindowsPowerShell\Modules\Poshspec\2.2.1\Private\Invoke-PoshspecExpression.ps1: line 13
 [+] File 'test.txt' Should Contain 'hello' 176ms
 [-] File 'test.txt' Should Contain 'other' 75ms
   Expected: file C:\projects\test.txt to contain {other}
   1: 'C:\projects\test.txt' | Should Contain 'other'
   at <ScriptBlock>, <No file>: line 1
   at <ScriptBlock>, C:\Program Files\WindowsPowerShell\Modules\Poshspec\2.2.1\Private\Invoke-PoshspecExpression.ps1: line 13
PS C:\projects> get-module

ModuleType Version    Name                                ExportedCommands                                                             
---------- -------    ----                                ----------------                                                             
Binary     1.0.0.0    CimCmdlets                          {Export-BinaryMiLog, Get-CimAssociatedInstance, Get-CimClass, Get-CimInsta...
Manifest   3.1.0.0    Microsoft.PowerShell.Management     {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Content...}           
Manifest   3.0.0.0    Microsoft.PowerShell.Security       {ConvertFrom-SecureString, ConvertTo-SecureString, Get-Acl, Get-Authentico...
Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object...}                    
Manifest   3.0.0.0    Microsoft.WSMan.Management          {Connect-WSMan, Disable-WSManCredSSP, Disconnect-WSMan, Enable-WSManCredSS...
Binary     1.0.0.1    PackageManagement                   {Find-Package, Find-PackageProvider, Get-Package, Get-PackageProvider...}    
Script     3.4.0      Pester                              {AfterAll, AfterEach, Assert-MockCalled, Assert-VerifiableMocks...}          
Script     2.2.1      Poshspec                            {AppPool, AuditPolicy, CimObject, DnsHost...}                                
Script     1.0.0.1    PowerShellGet                       {Find-Command, Find-DscResource, Find-Module, Find-RoleCapability...}        
Script     1.2        PSReadline                          {Get-PSReadlineKeyHandler, Get-PSReadlineOption, Remove-PSReadlineKeyHandl...

Any tips what might be the problem in AppVeyor environment? The other Pester version, AppVeyor seems to have 4.3.1 installed.

StefanScherer commented 6 years ago

It seems to behave different between running it like .\test.ps1 and powershell -File .\test.ps1. The Contains rules behave different in AppVeyor. Any advisory how to run it predictable in AppVeyor builds?

cdhunt commented 6 years ago

PoshSpec is just a Pester abstraction. The Contains assertion was removed in Pester (I don't remember which version). If you use Invoke-Pester against your test file you get all of Pester's functionality: -Exit, -PassTrue, -OutputXml, etc.

Does that help?

StefanScherer commented 6 years ago

Thanks @cdhunt After some hours "learning the hard way" I solved my problems. Integrating Pester based things looks hard if you come from Serverspec and used to Linux commands exiting properly. :-)

I have it running using $lastExitCode in our appveyor caller script and Invoke-Pester in the test script that sets up the environment and runs the test. I first thought I can use $ErrorActionPreference = 'Stop' in one or both of the scripts, but that didn't work. So that was my learning curve to dig deeper into the world of PowerShell and Pester.