Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Beyond Pester 103 : Applying a testing mindset

Glenn
April 22, 2023

Beyond Pester 103 : Applying a testing mindset

Pester is a great tool. You’ve probably used it for unit and acceptance testing, but you feel there’s something missing; How much more is there to testing? Is it just making sure my script works? It’s time to look at how testing can be used in everything (well almost everything…) you do!

Glenn

April 22, 2023
Tweet

More Decks by Glenn

Other Decks in Technology

Transcript

  1. Beyond Pester 103
    @glennsarti glenn-sarti
    Applying a testing mindset to PowerShell
    Glenn Sarti - Senior Software Engineer at

    View Slide

  2. Beyond Pester 101
    Applying testing principles to PowerShell
    Glenn Sarti
    Software Engineer, Windows Team

    View Slide

  3. @glennsarti
    To reduce the risk that a
    user will experience an
    unexpected behaviour

    View Slide

  4. @glennsarti
    Unit (White box)
    Integration
    Unit (Black box)
    Characterisation

    View Slide

  5. @glennsarti
    Reduce duration
    Remove tests
    Reorder tests
    General
    maintenance

    View Slide

  6. Beyond Pester 102
    Acceptance testing with PowerShell
    @glennsarti glenn-sarti

    View Slide

  7. @glennsarti
    Cynefin Framework
    “The Cynefin framework (/ˈkʌnɪvɪn/
    KUN-iv-in) is a conceptual framework
    used to aid decision-making”
    - https://www.youtube.com/watch?v=N7oz366X0-8

    View Slide

  8. @glennsarti
    Operational Acceptance Tests
    Operation Validation Tests
    User Acceptance Tests
    Compliance Acceptance Tests

    View Slide

  9. @glennsarti
    Operational Acceptance Tests
    Operation Validation Tests
    User Acceptance Tests
    Compliance Acceptance Tests

    View Slide

  10. @glennsarti
    ?
    @glennsarti

    View Slide

  11. Designing automated test suites
    About 60% automation testing and 40% manual
    Contribute towards maintaining regression suite
    Ability to write clear and concise test/bug reports
    Review and analyze system specifications
    Regression testing, reporting
    @glennsarti

    View Slide

  12. Designing automated test suites
    About 60% automation testing and 40% manual
    Contribute towards maintaining regression suite
    Ability to write clear and concise test/bug reports
    Review and analyze system specifications
    Regression testing, reporting
    @glennsarti

    View Slide

  13. Wanted: Testing Mindset
    Creative Thinker
    Problem Solver
    Explorer / Experimenter
    @glennsarti

    View Slide

  14. Wanted: Testing Mindset
    Creative Thinker
    Problem Solver
    Explorer / Experimenter
    @glennsarti

    View Slide

  15. Wanted: Testing Mindset
    Creative Thinker
    Problem Solver
    Explorer / Experimenter
    @glennsarti

    View Slide

  16. Wanted: Testing Mindset
    Creative Thinker
    Problem Solver
    Explorer / Experimenter
    @glennsarti

    View Slide

  17. Wanted: Testing Mindset
    Creative Thinker
    Problem Solver
    Explorer / Experimenter
    @glennsarti

    View Slide

  18. Wanted: Testing Mindset
    Creative Thinker
    Problem Solver
    Explorer / Experimenter
    @glennsarti

    View Slide

  19. Wanted: Testing Mindset
    Creative Thinker
    Problem Solver
    Explorer / Experimenter
    @glennsarti

    View Slide

  20. Wanted: Testing Mindset
    Creative Thinker
    Problem Solver
    Explorer / Experimenter
    @glennsarti

    View Slide

  21. Wanted: Testing Mindset
    Creative Thinker
    Problem Solver
    Explorer / Experimenter
    @glennsarti

    View Slide

  22. Wanted: Testing Mindset
    Creative Thinker
    Problem Solver
    Explorer / Experimenter
    @glennsarti

    View Slide

  23. @glennsarti

    View Slide

  24. @glennsarti

    View Slide

  25. @glennsarti
    Testing is one of the most
    profitable investments engineers can
    make to improve the reliability of
    their product. Testing isn’t an activity
    that happens once or twice in the
    lifecycle of a project; it’s continuous.


    - https://sre.google/sre-book/testing-reliability/

    View Slide

  26. @glennsarti
    “Shifting left” is about building quality into
    the software development process. When
    you shift left, fewer things break in
    production, because any issues are detected
    and resolved earlier.
    - Puppet State of DevOps Report 2016

    View Slide

  27. @glennsarti
    ?
    @glennsarti

    View Slide

  28. @glennsarti
    @glennsarti
    AD Account Cleanup Script
    • Disable accounts that haven’t logged in
    for 45 days
    • Delete disabled accounts after 6 months
    • Be able to exclude some accounts
    • Log all activities

    View Slide

  29. @glennsarti
    @glennsarti
    Param (
    $ScriptPath = "C:\Automation\AD\Cleanup\",
    $LogDirectory = "logfiles\",
    $Date = (Get-Date).ToString("dd-MM-yyyy"),
    $NamedExceptions = (Get-Content $ScriptPath`ADnamedExceptions.txt),
    $Server = "DC002.domain.com"
    )
    Function Get-AgedAccounts {
    Param (
    [string]$AccountType,
    [int]$AgedAccountThreshold,
    [int]$NewAccountThreshold
    )
    $LastLogonDate = (Get-Date).AddDays(-$AgedAccountThreshold)
    $WhenCreated = (Get-Date).AddDays(-$NewAccountThreshold)
    If ($AccountType -eq "User") {
    $AgedAccounts = Get-ADUser -Filter {
    (enabled -eq $True -and PasswordNeverExpires -eq $False -and WhenCreated -lt $WhenCreated -and samAccountType -eq "805306368") -and
    ((LastLogonDate -lt $LastLogonDate) -or (LastLogonDate -notlike "*"))
    } -Properties lastLogonDate,whenCreated,passWordLastSet,whenChanged -Server $server |
    Select-Object -Properties distinguishedName,samAccountName,lastLogonDate,whenCreated,passWordLastSet,whenChanged,objectClass
    $AgedAccounts
    } ElseIf ($AccountType -eq "Computer") {
    $AgedAccounts = Get-ADComputer -Filter {
    (enabled -eq $True -and PasswordNeverExpires -eq $False -and WhenCreated -lt $WhenCreated -and samAccountType -eq "805306369") -and
    ((LastLogonDate -lt $LastLogonDate) -or (LastLogonDate -notlike "*"))
    } -Properties lastLogonDate,whenCreated,passWordLastSet,whenChanged -Server $server |
    Select-Object -Property distinguishedName,samAccountName,lastLogonDate,whenCreated,passWordLastSet,whenChanged,objectClass
    $AgedAccounts
    } Else {
    $AgedAccounts
    }
    }
    Function Get-DisabledAccounts {
    Param (
    [string]$AccountType,
    [int]$LastModifiedThreshold
    )
    $LastModifiedDate = (Get-Date).AddDays(-$LastModifiedThreshold)
    If ($AccountType -eq "User") {
    $DisabledAccounts = Get-ADUser -Filter {
    enabled -eq $False -and samAccountType -eq "805306368" -and whenChanged -lt $LastModifiedDate
    } -properties lastLogonDate,whenCreated,passWordLastSet,whenChanged -server $server |
    Select-Object -Property distinguishedName,samAccountName,lastLogonDate,whenCreated,passWordLastSet,whenChanged,objectClass
    $DisabledAccounts
    } ElseIf ($AccountType -eq "Computer") {
    $DisabledAccounts = Get-ADComputer -Filter {
    enabled -eq $False -and samAccountType -eq "805306369" -and whenChanged -lt $LastModifiedDate
    } -properties lastLogonDate,whenCreated,passWordLastSet,whenChanged -server $server |
    Select-Object -Property distinguishedName,samAccountName,lastLogonDate,whenCreated,passWordLastSet,whenChanged,objectClass
    $DisabledAccounts
    } Else {
    $DisabledAccounts
    }
    }
    $AgedAccounts = $null
    $AgedAccounts = Get-AgedAccounts User 45 21
    $AgedAccounts += Get-AgedAccounts Computer 45 14
    $AgedAccounts.Count
    $DisabledAccounts = $null
    $DisabledAccounts = Get-DisabledAccounts Computer 183
    # $DisabledAccounts += Get-DisabledAccounts User 183
    $DisabledAccounts.Count
    ForEach ($AgedAccount in $AgedAccounts) {
    If ($NamedExceptions -contains $AgedAccount.DistinguishedName) {
    $Result = "Match found in named exceptions file"
    } Else {
    Disable-ADAccount $AgedAccount.DistinguishedName -Server $Server # -WhatIf
    $Result = $?
    }
    Add-Member -InputObject $AgedAccount -MemberType NoteProperty `
    -Name ScriptDisabled -Value $Result
    }
    $LogFile = $Date + "disabled accounts.csv"
    $AgedAccounts |
    Export-Csv $ScriptPath$LogDirectory$LogFile -NoTypeInformation
    ForEach ($DisabledAccount in $DisabledAccounts) {
    If ($NamedExceptions -contains $DisabledAccount.DistinguishedName) {
    $Result = "Match found in named exceptions file"
    } Else {
    Remove-ADObject $DisabledAccount.DistinguishedName -Server $Server -Confirm:$False -Recursive # -WhatIf
    $Result = $?
    }
    Add-Member -InputObject $DisabledAccount -MemberType NoteProperty -Name ScriptDeleted -Value $Result
    }
    $LogFile = $Date + "-deleted accounts.csv"
    $DisabledAccounts |
    Export-Csv $ScriptPath$LogDirectory$LogFile -NoTypeInformation

    View Slide

  30. @glennsarti
    @glennsarti
    AD Account Cleanup Script
    • Disable accounts that haven’t logged in
    for 45 days
    • Delete disabled accounts after 6 months
    • Be able to exclude some accounts
    • Log all activities

    View Slide

  31. @glennsarti
    @glennsarti
    AD Account Cleanup Script
    • Disable accounts that haven’t logged in
    for 45 days
    • Delete disabled accounts after 6 months
    • Be able to exclude some accounts
    • Log all activities

    View Slide

  32. @glennsarti
    @glennsarti
    AD Account Cleanup Script
    • Disable accounts that haven’t logged in
    for 45 days
    • Delete disabled accounts after 6 months
    • Be able to exclude some accounts
    • Log all activities

    View Slide

  33. @glennsarti
    @glennsarti
    AD Account Cleanup Script
    • Disable accounts that haven’t logged in
    for 45 days
    • Delete disabled accounts after 6 months
    • Be able to exclude some accounts
    • Log all activities

    View Slide

  34. @glennsarti
    Single Responsibility
    Principle
    @glennsarti

    View Slide

  35. @glennsarti
    • Find accounts that haven’t logged in for 45
    days
    • Exclude some accounts
    • Disable the accounts
    • Log the results to a file
    @glennsarti

    View Slide

  36. @glennsarti
    @glennsarti
    Get-OldAccount |
    Skip-ExcludedAccounts |
    Disable-Account |
    Out-AuditFile

    View Slide

  37. @glennsarti
    @glennsarti
    Get-OldAccount -OlderThanDays 45 |
    Skip-ExcludedAccounts -Exclude $IgnoreAccounts |
    Disable-Account |
    Out-AuditFile -Path $AuditFileCSV

    View Slide

  38. @glennsarti
    @glennsarti
    Describe "Get-OldAccounts" {
    BeforeEach {
    $OldUserName1 = "Jasper"
    $OldUserName2 = "Tomato"
    $NotStaleUserName = "Pinapple"
    Function New-MockUser($Name, $Age) {
    # Insert mocking code here
    }
    New-MockUser $OldUserName1 46
    New-MockUser $OldUserName2 100
    New-MockUser $NotStaleUserName 45
    }
    It "only returns old accounts" {
    $Actual = Get-OldAccounts -OlderThanDays 45
    $Actual | Should-Be @($OldUserName1, $OldUserName2)
    }
    }

    View Slide

  39. @glennsarti
    @glennsarti
    Describe "Get-OldAccounts" {
    BeforeEach {
    $OldUserName1 = "Jasper"
    $OldUserName2 = "Tomato"
    $NotStaleUserName = "Pinapple"
    Function New-MockUser($Name, $Age) {
    # Insert mocking code here
    }
    New-MockUser $OldUserName1 46
    New-MockUser $OldUserName2 100
    New-MockUser $NotStaleUserName 45
    }
    It "only returns old accounts" {
    $Actual = Get-OldAccounts -OlderThanDays 45
    $Actual | Should-Be @($OldUserName1, $OldUserName2)
    }
    }
    Old accounts
    Not old
    account

    View Slide

  40. @glennsarti
    @glennsarti
    Describe "Get-OldAccounts" {
    BeforeEach {
    $OldUserName1 = "Jasper"
    $OldUserName2 = "Tomato"
    $NotStaleUserName = "Pinapple"
    Function New-MockUser($Name, $Age) {
    # Insert mocking code here
    }
    New-MockUser $OldUserName1 46
    New-MockUser $OldUserName2 100
    New-MockUser $NotStaleUserName 45
    }
    It "only returns old accounts" {
    $Actual = Get-OldAccounts -OlderThanDays 45
    $Actual | Should-Be @($OldUserName1, $OldUserName2)
    }
    }

    View Slide

  41. @glennsarti
    @glennsarti
    Get-OldAccount `
    -OlderThanDays 45 |
    Skip-ExcludedAccounts `
    -Exclude $IgnoreAccounts |
    Disable-Account |
    Out-AuditFile -Path $AuditFileCSV
    $AgedAccounts = $null
    $AgedAccounts = Get-AgedAccounts User 45
    # ...
    ForEach ($AgedAccount in $AgedAccounts) {
    If ($NamedExceptions -contains $AgedAccount.DistinguishedName) {
    $Result = "Match found in named exceptions file"
    } Else {
    Disable-ADAccount $AgedAccount.DistinguishedName `
    -Server $Server
    $Result = $?
    }
    Add-Member -InputObject $AgedAccount -MemberType NoteProperty `
    -Name ScriptDisabled -Value $Result
    }
    $LogFile = $Date + "disabled accounts.csv"
    $AgedAccounts |
    Export-Csv $ScriptPath$LogDirectory$LogFile -NoTypeInformation
    Before After

    View Slide

  42. @glennsarti
    • Find accounts that were disabled 6 months
    ago
    • Exclude some accounts
    • Delete the accounts
    • Log the results to a file
    @glennsarti

    View Slide

  43. @glennsarti
    @glennsarti
    Get-OldAccount -OlderThanDays 45 |
    Skip-ExcludedAccounts -Exclude $IgnoreAccounts |
    Disable-Account |
    Out-AuditFile -Path $AuditFileCSV
    Get-DisabledAccount -OlderThanDays 180 |
    Skip-ExcludedAccounts -Exclude $IgnoreAccounts |
    Remove-Account |
    Out-AuditFile -Path $AuditFileCSV

    View Slide

  44. @glennsarti
    Avoid Implicit
    Dependencies
    @glennsarti

    View Slide

  45. @glennsarti
    @glennsarti
    Function Get-AgedAccounts {
    Param (
    [string]$AccountType,
    [int]$AgedAccountThreshold,
    [int]$NewAccountThreshold
    )
    $LastLogonDate = (Get-Date).AddDays(-$AgedAccountThreshold)
    $WhenCreated = (Get-Date).AddDays(-$NewAccountThreshold)
    If ($AccountType -eq "User") {
    $AgedAccounts = Get-ADUser -Filter {
    (enabled -eq $True -and PasswordNeverExpires -eq $False -and WhenCreated -lt $WhenCreated
    –and …

    View Slide

  46. @glennsarti
    @glennsarti
    Function Get-AgedAccounts {
    Param (
    [string]$AccountType,
    [int]$AgedAccountThreshold,
    [int]$NewAccountThreshold
    )
    $LastLogonDate = (Get-Date).AddDays(-$AgedAccountThreshold)
    $WhenCreated = (Get-Date).AddDays(-$NewAccountThreshold)
    If ($AccountType -eq "User") {
    $AgedAccounts = Get-ADUser -Filter {
    (enabled -eq $True -and PasswordNeverExpires -eq $False -and WhenCreated -lt $WhenCreated
    –and …

    View Slide

  47. @glennsarti
    @glennsarti
    Function Get-AgedAccounts {
    Param (
    [string]$AccountType,
    [int]$AgedAccountThreshold,
    [int]$NewAccountThreshold
    )
    $LastLogonDate = (Get-Date).AddDays(-$AgedAccountThreshold)
    $WhenCreated = (Get-Date).AddDays(-$NewAccountThreshold)
    If ($AccountType -eq "User") {
    $AgedAccounts = Get-ADUser -Filter {
    (enabled -eq $True -and PasswordNeverExpires -eq $False -and WhenCreated -lt $WhenCreated
    –and …

    View Slide

  48. @glennsarti
    @glennsarti
    Function Get-AgedAccounts {
    Param (
    [string]$AccountType,
    [int]$AgedAccountThreshold,
    [DateTime]$CreatedAfter
    )
    $LastLogonDate = (Get-Date).AddDays(-$AgedAccountThreshold)
    If ($AccountType -eq "User") {
    $AgedAccounts = Get-ADUser -Filter {
    (enabled -eq $True -and PasswordNeverExpires -eq $False -and WhenCreated -ge $CreatedAfter
    –and …

    View Slide

  49. @glennsarti
    @glennsarti
    Get-OldAccount -OlderThanDays 45 |
    Skip-ExcludedAccounts -Exclude $IgnoreAccounts |
    Disable-Account |
    Out-AuditFile -Path $AuditFileCSV
    Get-DisabledAccount -OlderThanDays 180 |
    Skip-ExcludedAccounts -Exclude $IgnoreAccounts |
    Remove-Account |
    Out-AuditFile -Path $AuditFileCSV

    View Slide

  50. @glennsarti
    @glennsarti
    $DisableTime = (Get-Date).AddDays(-45)
    $RemoveTime = (Get-Date).AddMonths(-6)
    Get-OldAccount -OlderThan $DisableTime |
    Skip-ExcludedAccounts -Exclude $IgnoreAccounts |
    Disable-Account |
    Out-AuditFile -Path $AuditFileCSV
    Get-DisabledAccount -OlderThan $RemoveTime |
    Skip-ExcludedAccounts -Exclude $IgnoreAccounts |
    Remove-Account |
    Out-AuditFile -Path $AuditFileCSV

    View Slide

  51. @glennsarti
    Types of tests – Unit (Black box)
    “Tools do one thing … Tools don’t
    know where their input data has
    generated … Tools accept all input
    only from their parameters … Tools
    don’t know how their output will be
    used, “
    - The Many Forms of Scripting: which to use - Manning
    @glennsarti

    View Slide

  52. @glennsarti
    Why is testing hard?
    @glennsarti

    View Slide

  53. @glennsarti
    @glennsarti

    View Slide

  54. @glennsarti
    TDD
    @glennsarti

    View Slide

  55. @glennsarti
    @glennsarti
    …here’s another one: TDD (Test-driven development)
    … why not write down what your trying to accomplish
    in the form of tests … Make sure all of those tests fail
    and then write PowerShell code to accomplish the
    necessary tasks until all of the tests pass.
    - https://mikefrobbins.com/2014/10/09/using-pester-for-test-driven-development-in-powershell/

    View Slide

  56. @glennsarti
    @glennsarti
    - https://sqldbawithabeard.com/2017/06/30/creating-a-powershell-module-and-tdd-for-get-sqldiagrecommendations/
    I approached writing this module using
    Test Driven Development with Pester.
    This means that I have to write my
    tests before I write my code.

    View Slide

  57. @glennsarti
    TDD anyone?
    @glennsarti

    View Slide

  58. @glennsarti
    1. Add a test
    2. It should fail
    3. Write the code
    4. Tests should pass
    @glennsarti
    - https://en.wikipedia.org/wiki/Test-driven_development

    View Slide

  59. @glennsarti
    1. Add a test
    2. It should fail
    3. Write the code
    4. Tests should pass
    5. Refactor
    6. Repeat
    @glennsarti
    - https://en.wikipedia.org/wiki/Test-driven_development

    View Slide

  60. @glennsarti
    1. Add a test
    2. It should fail
    3. Write the code
    4. Tests should pass
    5. Refactor
    6. Repeat
    @glennsarti
    - https://en.wikipedia.org/wiki/Test-driven_development
    Iterate

    View Slide

  61. @glennsarti
    1. Add a test
    2. It should fail
    3. Write the code
    4. Tests should pass
    5. Refactor
    6. Repeat
    @glennsarti
    - https://en.wikipedia.org/wiki/Test-driven_development
    Always adding quality

    View Slide

  62. @glennsarti
    1. Add a test
    2. It should fail
    3. Write the code
    4. Tests should pass
    5. Refactor
    6. Repeat
    @glennsarti
    - https://en.wikipedia.org/wiki/Test-driven_development
    Focus on requirements

    View Slide

  63. @glennsarti
    1. Add a test
    2. It should fail
    3. Write the code
    4. Tests should pass
    5. Refactor
    6. Repeat
    @glennsarti
    - https://en.wikipedia.org/wiki/Test-driven_development
    Small QoL things

    View Slide

  64. @glennsarti
    @glennsarti
    ❌ Code before tests
    ❌ Blocking work
    ❌ The end state
    TDD is not

    View Slide

  65. @glennsarti
    @glennsarti
    ✅ Fast feedback loops
    ✅ Focus on requirements
    ✅ A high confidence change tool
    TDD is

    View Slide

  66. @glennsarti
    @glennsarti
    … we are 100% capable of doing TDD with
    Powershell, No Excuses! … It’s that simple, and
    it’s a beautiful thing.
    - https://devingleasonlambert.medium.com/test-driven-development-by-example-using-powershell-what-is-tdd-9a5006c9931
    - Devin Gleason-Lambert

    View Slide

  67. @glennsarti
    @glennsarti
    AD Account Cleanup Script
    • Disable accounts that haven’t logged in
    for 45 days
    • Delete disabled accounts after 6 months
    • Be able to exclude some accounts
    • Log all activities

    View Slide

  68. @glennsarti
    Describe "Get-OldAccounts" {
    BeforeEach {
    $OldUserName1 = "Jasper"
    $OldUserName2 = "Tomato"
    $NotStaleUserName = "Pinapple"
    Function New-MockUser($Name, $Age) {
    # Insert mocking code here
    }
    New-MockUser $OldUserName1 46
    New-MockUser $OldUserName2 100
    New-MockUser $NotStaleUserName 45
    }
    It "only returns old accounts" {
    $Actual = Get-OldAccounts -OlderThanDays 45
    $Actual | Should-Be @($OldUserName1, $OldUserName2)
    }
    }

    View Slide

  69. @glennsarti
    $DisableTime = (Get-Date).AddDays(-45)
    $RemoveTime = (Get-Date).AddMonths(-6)
    Get-OldAccount -OlderThan $DisableTime |
    Skip-ExcludedAccounts -Exclude $IgnoreAccounts |
    Disable-Account |
    Out-AuditFile -Path $AuditFileCSV
    Get-DisabledAccount -OlderThan $RemoveTime |
    Skip-ExcludedAccounts -Exclude $IgnoreAccounts |
    Remove-Account |
    Out-AuditFile -Path $AuditFileCSV

    View Slide

  70. @glennsarti
    @glennsarti
    AD Account Cleanup Script
    • Disable accounts that haven’t logged in
    for 45 days
    • Delete disabled accounts after 6 months
    • Be able to exclude some accounts
    • Log all activities

    View Slide

  71. @glennsarti
    @glennsarti
    TDD for everyone

    View Slide

  72. @glennsarti
    TDD for everyone
    @glennsarti
    “The code is more what you’d call ‘guidelines’ than actual rules.”
    - Captain Barbosa – Pirates of the Caribbean

    View Slide

  73. @glennsarti
    Q: Where to start?
    @glennsarti

    View Slide

  74. @glennsarti
    Q: Where to start?
    A: It depends 😕
    @glennsarti

    View Slide

  75. @glennsarti
    1. Happy path
    2. Sad path
    3. Weird 💩 path
    @glennsarti

    View Slide

  76. @glennsarti
    A software tester walks into a bar ...
    Orders a beer
    Orders ten beers
    Orders a nothing
    Orders 200 beers
    Tries to leave without paying
    Orders -1 beers
    Orders a cat
    @glennsarti

    View Slide

  77. @glennsarti
    @glennsarti
    Happy
    Sad
    Weird
    A software tester walks into a bar ...
    Orders a beer
    Orders ten beers
    Orders a nothing
    Orders 200 beers
    Tries to leave without paying
    Orders -1 beers
    Orders a cat

    View Slide

  78. @glennsarti
    AD Cleanup script – Get old Accounts
    An account logged in 46 days ago
    An account logged in 45 days ago
    @glennsarti
    Happy

    View Slide

  79. @glennsarti
    AD Cleanup script – Get old Accounts
    An account logged in 46 days ago
    An account logged in 45 days ago
    An account that’s never logged in
    Network error
    @glennsarti
    Happy
    Sad

    View Slide

  80. @glennsarti
    AD Cleanup script – Get old Accounts
    An account logged in 46 days ago
    An account logged in 45 days ago
    An account that’s never logged in
    Network error
    An account logged in 1 day into the future
    @glennsarti
    Happy
    Sad
    Weird

    View Slide

  81. @glennsarti
    AD Cleanup script – Get old Accounts
    An account logged in 46 days ago
    An account logged in 45 days ago
    An account that’s never logged in
    Network error
    An account logged in 1 day into the future
    @glennsarti
    Happy
    Sad
    Weird

    View Slide

  82. @glennsarti
    @glennsarti
    “ If it hurts, do it more
    frequently, and bring the
    pain forward. “
    - https://www.amazon.com.au/Continuous-Delivery-Reliable-Deployment-Automation/dp/0321601912
    - Jez Humble

    View Slide

  83. @glennsarti
    Operation Validation Framework
    - https://github.com/PowerShell/Operation-Validation-Framework
    A set of tools for executing validation of the
    operation of a system. It provides a way to
    organize and execute Pester tests which are
    written to validate operation … ”

    @glennsarti

    View Slide

  84. @glennsarti

    View Slide

  85. @glennsarti
    @glennsarti
    Tests are tools

    View Slide

  86. @glennsarti
    @glennsarti
    Gherkin

    View Slide

  87. @glennsarti
    @glennsarti
    Feature: It retrieves old accounts
    Background: Login to Test AD
    Given test AD server 'testad.local'
    And a user '[email protected]' which logged in 45 days ago
    And a user '[email protected]' which logged in 46 days ago
    And a user '[email protected]' which logged in 100 days ago
    Scenario: Getting many accounts
    When getting accounts older than 45 days
    Then it returns user '[email protected]'
    And it returns user '[email protected]'
    And it does not return user '[email protected]'

    View Slide

  88. @glennsarti
    @glennsarti
    Compliance Testing

    View Slide

  89. @glennsarti
    Metadata
    Test
    @glennsarti

    View Slide

  90. @glennsarti
    @glennsarti
    Compliance Testing
    Open Policy Agent (OPA)
    HashiCorp Sentinel*

    View Slide

  91. @glennsarti
    @glennsarti
    OPA – Conftest - Rego syntax

    View Slide

  92. @glennsarti
    @glennsarti
    HashiCorp - Sentinel
    deny_unencrypted_managed_disk = rule when {
    all allManagedDisks as _, disks {
    all disks.change.after.encryption_settings as encryption_settings {
    encryption_settings.enabled is true
    }
    }
    }

    View Slide

  93. @glennsarti
    @glennsarti
    Load Testing

    View Slide

  94. @glennsarti
    @glennsarti
    package gatlingBlog
    import scala.concurrent.duration._
    import io.gatling.core.Predef._
    import io.gatling.http.Predef._
    class SartiDevSimulation1 extends Simulation
    {
    val httpProtocol = http
    .baseUrl("https://sarti.dev")
    val scn = scenario("SendSimpleQuery")
    .exec(
    http("root_request")
    .get("/")
    )
    setUp(scn.inject(
    atOnceUsers(100)
    ).protocols(httpProtocol))
    }

    View Slide

  95. @glennsarti
    @glennsarti
    package gatlingBlog
    import scala.concurrent.duration._
    import io.gatling.core.Predef._
    import io.gatling.http.Predef._
    class SartiDevSimulation1 extends Simulation
    {
    val httpProtocol = http
    .baseUrl("https://sarti.dev")
    val scn = scenario("SendSimpleQuery")
    .exec(
    http("root_request")
    .get("/")
    )
    setUp(scn.inject(
    atOnceUsers(100)
    ).protocols(httpProtocol))
    }
    Request
    URL
    Load

    View Slide

  96. @glennsarti
    @glennsarti

    View Slide

  97. @glennsarti
    @glennsarti
    So many tools…

    View Slide

  98. @glennsarti

    View Slide


  99. If it's truth you're interested
    in, Dr.Tyree's Philosophy class
    is right down the hall
    — Indiana Jones
    @glennsarti

    View Slide

  100. @glennsarti

    View Slide

  101. Does my PowerShell do
    what it should?
    @glennsarti

    View Slide

  102. Does my PowerShell do
    what it should?
    How do I know my
    PowerShell does
    what it should?
    @glennsarti

    View Slide

  103. THANK YOU!
    Please use the link below to submit a session rating!
    @glennsarti
    http://sarti.dev/
    https://speakerdeck.com/glennsarti
    https://powershellsummit.org/sessionfeedback

    View Slide

  104. @glennsarti
    Resources
    Beyond Pester
    https://sarti.dev/presentation/powershell-summit2018-pester
    https://sarti.dev/presentation/powershell-summit2019-pester
    DevOps
    https://www.amazon.com.au/Phoenix-Project-DevOps-Helping-Business/dp/0988262592
    https://sre.google/sre-book/testing-reliability/
    https://services.google.com/fh/files/misc/state-of-devops-2018.pdf
    https://www.amazon.com.au/Continuous-Delivery-Reliable-Deployment-Automation/dp/0321601912
    TDD
    https://en.wikipedia.org/wiki/Test-driven_development
    https://mikefrobbins.com/2014/10/09/using-pester-for-test-driven-development-in-powershell/
    https://sqldbawithabeard.com/2017/06/30/creating-a-powershell-module-and-tdd-for-get-sqldiagrecommendations/
    https://devingleasonlambert.medium.com/test-driven-development-by-example-using-powershell-what-is-tdd-9a5006c9931
    Images
    https://unsplash.com
    @glennsarti

    View Slide

  105. @glennsarti
    Resources
    Doctor don’t Defenstrate
    https://www.youtube.com/watch?v=xu9dRXgmTNc
    Compliance
    https://www.conftest.dev/
    https://www.hashicorp.com/sentinel
    @glennsarti

    View Slide