Welcome to the Pester Testing Playground! This repository provides a comprehensive, hands-on introduction to Pester, the testing and mocking framework for PowerShell. Whether you're new to testing or looking to improve your skills, this repo takes you from basic to expert-level testing patterns.
- What is Pester?
- Repository Structure
- Getting Started
- Learning Path
- Running Tests
- Best Practices
- Additional Resources
Pester is a testing and mocking framework for PowerShell that enables you to:
- Write unit tests and integration tests for your PowerShell code
- Mock external dependencies to isolate code under test
- Generate code coverage reports
- Integrate tests into CI/CD pipelines
- Validate configurations and deployments
Pester follows a simple file naming convention (*.Tests.ps1) and uses an intuitive DSL with keywords like Describe, Context, It, Should, and Mock.
The repository is organized into progressive learning levels:
pesterdevPlayground/
β
βββ 01-Basic/ # Level 1: Fundamentals
β βββ Get-Greeting.ps1 # Simple string function
β βββ Get-Greeting.Tests.ps1 # Basic assertions and contexts
β
βββ 02-Intermediate/ # Level 2: Parameterized Testing
β βββ Calculator.ps1 # Arithmetic operations
β βββ Calculator.Tests.ps1 # TestCases and data-driven tests
β
βββ 03-Advanced/ # Level 3: Mocking & Dependencies
β βββ UserValidation.ps1 # Functions with external calls
β βββ UserValidation.Tests.ps1 # Mocking and mock assertions
β
βββ 04-Expert/ # Level 4: Integration, File I/O & DateTime
β βββ FileOperations.ps1 # Configuration file management
β βββ FileOperations.Tests.ps1 # Setup/teardown and integration tests
β βββ DateTimeParsing.ps1 # Robust date parsing functions
β βββ DateTimeParsing.Tests.ps1 # Comprehensive date format testing
β
βββ README.md # This file
- PowerShell 5.1 or PowerShell 7+
- Pester 5.x (recommended)
If you don't have Pester installed, run:
# Install Pester (requires admin/elevated privileges)
Install-Module -Name Pester -Force -SkipPublisherCheck
# Verify installation
Import-Module Pester -PassThruYou should see output similar to:
ModuleType Version Name
---------- ------- ----
Script 5.x.x Pester
git clone https://github.com/yourusername/pesterdevPlayground.git
cd pesterdevPlaygroundFollow these levels in order to progressively build your Pester skills:
Concepts Covered:
BeforeAllblock for setupDescribeandContextfor organizing testsItblocks for individual test cases- Basic
Shouldassertions (-Be,-BeLike,-Match) - Testing default parameters and error conditions
- Pipeline support testing
What You'll Learn:
- How to structure a basic test file
- Dot-sourcing functions to test
- Writing clear, descriptive test cases
- Testing both happy paths and error scenarios
Run Tests:
Invoke-Pester -Path .\01-Basic\Get-Greeting.Tests.ps1 -Output DetailedConcepts Covered:
- TestCases for parameterized testing
- Data-driven tests with multiple inputs
- Testing mathematical operations
- Edge case validation
- Integration tests combining multiple functions
What You'll Learn:
- How to reduce test duplication with TestCases
- Testing multiple scenarios efficiently
- Organizing related test cases
- Validating complex calculations
Run Tests:
Invoke-Pester -Path .\02-Intermediate\Calculator.Tests.ps1 -Output DetailedConcepts Covered:
- Mocking functions and external dependencies
- Mock assertions with
Should -Invoke - Parameter filters for precise mock verification
BeforeEachfor per-test setup- Testing code with external API calls
- Verifying call order and behavior
What You'll Learn:
- How to isolate code from external dependencies
- Mocking strategies for unit testing
- Verifying function interactions
- Testing error handling without hitting real APIs
Run Tests:
Invoke-Pester -Path .\03-Advanced\UserValidation.Tests.ps1 -Output DetailedConcepts Covered:
- BeforeAll/AfterAll for test suite setup/teardown
- BeforeEach/AfterEach for test-level cleanup
- Testing file system operations
- Using
$TestDrivefor temporary test files - Integration testing with real I/O
- Idempotency testing
- Complete workflow testing
- Explicit format DateTime parsing to prevent ambiguous date interpretation
- UTC conversion and timezone handling
- DateTimeOffset for timezone-aware operations
- Format validation before parsing
- Flexible format detection for multiple date formats
- Production-ready patterns addressing real-world date format issues
What You'll Learn:
- How to safely test file operations
- Proper test isolation and cleanup
- Integration test patterns
- Testing concurrent operations
- End-to-end workflow validation
- How to safely parse date strings with explicit formats
- Converting between local time, UTC, and DateTimeOffset
- Preventing production issues with ambiguous date parsing
- Testing leap years, end-of-year dates, and edge cases
- Handling international date formats (US vs European)
- Batch processing dates via pipeline
- Real-world integration scenarios (API timestamps, log parsing, database storage)
File Operations Functions:
New-ConfigurationFile- Create configuration filesGet-ConfigurationFile- Read configuration filesUpdate-ConfigurationFile- Modify configuration filesRemove-ConfigurationFile- Delete configuration filesBackup-ConfigurationFile- Backup configuration filesTest-ConfigurationFile- Validate configuration files
DateTime Parsing Functions:
ConvertTo-DateTime- Parse with explicit format specificationConvertTo-DateTimeUtc- Parse and convert to UTCConvertTo-DateTimeOffsetUtc- Parse with timezone offset preservationTest-DateTimeFormat- Validate date format before parsingConvertFrom-DateTime- Convert DateTime to ISO 8601 stringConvertTo-DateTimeFlexible- Automatic format detection from common formats
Run Tests:
# Run all expert level tests (file operations + datetime)
Invoke-Pester -Path .\04-Expert\ -Output Detailed
# Run specific test files
Invoke-Pester -Path .\04-Expert\FileOperations.Tests.ps1 -Output Detailed
Invoke-Pester -Path .\04-Expert\DateTimeParsing.Tests.ps1 -Output DetailedTo run all tests in the repository:
Invoke-Pester -Output Detailed# Basic tests
Invoke-Pester -Path .\01-Basic\ -Output Detailed
# Intermediate tests
Invoke-Pester -Path .\02-Intermediate\ -Output Detailed
# Advanced tests
Invoke-Pester -Path .\03-Advanced\ -Output Detailed
# Expert tests (includes both file operations and datetime parsing)
Invoke-Pester -Path .\04-Expert\ -Output DetailedInvoke-Pester -Path .\02-Intermediate\Calculator.Tests.ps1 -Output Detailed
Invoke-Pester -Path .\04-Expert\FileOperations.Tests.ps1 -Output Detailed
Invoke-Pester -Path .\04-Expert\DateTimeParsing.Tests.ps1 -Output Detailed$config = New-PesterConfiguration
$config.Run.Path = '.\02-Intermediate\'
$config.CodeCoverage.Enabled = $true
$config.CodeCoverage.Path = '.\02-Intermediate\Calculator.ps1'
$config.Output.Verbosity = 'Detailed'
Invoke-Pester -Configuration $config# Run with minimal output (only failed tests)
Invoke-Pester
# Run with detailed output (all tests)
Invoke-Pester -Output Detailed
# Run specific tests by name
Invoke-Pester -FullNameFilter "*adds*"
# Run tests and stop on first failure
Invoke-Pester -Stop
# Generate test results in NUnit format (for CI/CD)
$config = New-PesterConfiguration
$config.TestResult.Enabled = $true
$config.TestResult.OutputPath = 'TestResults.xml'
Invoke-Pester -Configuration $configBased on the Pester documentation and examples in this repo:
- Place test files next to the code they test
- Use the
*.Tests.ps1naming convention - Keep functions in separate
.ps1files - Use dot-sourcing in
BeforeAllto import functions
- Use
Describefor the function or module being tested - Use
Contextto group related scenarios - Use
Itfor individual test cases - Keep test names descriptive and readable
- Use
BeforeAllfor expensive setup (runs once per block) - Use
BeforeEachfor per-test setup - Use
AfterAllandAfterEachfor cleanup - Leverage
$TestDrivefor temporary file testing
- Use specific assertions (
-Be,-BeExactly,-BeLike,-Match) - Test both positive and negative cases
- Use
Should -Throwfor error testing - Use parameter filters for precise expectations
- Mock external dependencies to isolate code
- Use
Should -Invoketo verify mock calls - Use parameter filters to verify correct arguments
- Test both with and without mocks when appropriate
- Use
-TestCasesto reduce duplication - Provide descriptive test names with placeholders
- Include edge cases and boundary conditions
- Keep test data close to the test
- Aim for high coverage, but focus on meaningful tests
- Don't just test for coverage percentage
- Cover error paths and edge cases
- Review coverage reports to find gaps
This is a learning repository! Feel free to:
- Add more examples
- Improve existing tests
- Fix bugs or typos
- Add documentation
- Share your experiences
This project is provided as-is for educational purposes. Feel free to use, modify, and share!
After completing all four levels:
- Practice - Write tests for your own PowerShell scripts
- Integrate - Add Pester to your CI/CD pipeline
- Explore - Learn about code coverage and test-driven development (TDD)
- Share - Help others learn Pester!
Happy Testing! π
If you found this helpful, consider starring the repository and sharing it with others learning PowerShell testing.