8.3 KiB
8.3 KiB
| applyTo | description |
|---|---|
| **/*.Tests.ps1 | Pester v5規約に基づくPowerShell Pesterテストのベストプラクティス |
PowerShell Pester v5 テストガイドライン
このガイドは、PowerShell Pester v5 モジュールを使用して自動化されたテストを作成するための PowerShell 固有の指示を提供します。一般的な PowerShell スクリプト作成のベストプラクティスについては、powershell.instructions.mdの PowerShell コマンドレット開発ガイドラインに従ってください。
ファイル命名と構造
- ファイル規約:
*.Tests.ps1命名パターンを使用 - 配置: テスト対象のコードの隣または専用テストディレクトリにテストファイルを配置
- インポートパターン:
BeforeAll { . $PSScriptRoot/FunctionName.ps1 }を使用してテスト対象の関数をインポート - 直接コードなし: すべてのコードを Pester ブロック(
BeforeAll、Describe、Context、Itなど)内に配置
テスト構造の階層
BeforeAll { # テスト対象の関数をインポート }
Describe 'FunctionName' {
Context 'When condition' {
BeforeAll { # コンテキストのセットアップ }
It 'Should behavior' { # 個別のテスト }
AfterAll { # コンテキストのクリーンアップ }
}
}
コアキーワード
Describe: トップレベルのグループ化、通常はテスト対象の関数名Context: 特定のシナリオのための Describe 内のサブグループIt: 個別のテストケース、説明的な名前を使用Should: テスト検証のためのアサーションキーワードBeforeAll/AfterAll: ブロックごとに一度だけセットアップ/ティアダウンBeforeEach/AfterEach: 各テストの前後でセットアップ/ティアダウン
セットアップとティアダウン
BeforeAll: 含まれるブロックの開始時に一度実行、高コストな操作に使用BeforeEach: ブロック内のすべてのItの前に実行、テスト固有のセットアップに使用AfterEach: すべてのItの後に実行、テストが失敗しても保証されるAfterAll: ブロックの終了時に一度実行、クリーンアップに使用- 変数スコープ:
BeforeAll変数は子ブロックで利用可能(読み取り専用)、BeforeEach/It/AfterEachは同じスコープを共有
アサーション(Should)
- 基本比較:
-Be,-BeExactly,-Not -Be - コレクション:
-Contain,-BeIn,-HaveCount - 数値:
-BeGreaterThan,-BeLessThan,-BeGreaterOrEqual - 文字列:
-Match,-Like,-BeNullOrEmpty - 型:
-BeOfType,-BeTrue,-BeFalse - ファイル:
-Exist,-FileContentMatch - 例外:
-Throw,-Not -Throw
モッキング
Mock CommandName { ScriptBlock }: コマンドの動作を置き換える-ParameterFilter: パラメータが条件に一致する場合のみモック-Verifiable: 検証が必要なモックとしてマークShould -Invoke: モックが特定の回数呼び出されたことを検証Should -InvokeVerifiable: すべての検証可能なモックが呼び出されたことを検証- スコープ: モックはデフォルトで含まれるブロックスコープ
Mock Get-Service { @{ Status = 'Running' } } -ParameterFilter { $Name -eq 'TestService' }
Should -Invoke Get-Service -Exactly 1 -ParameterFilter { $Name -eq 'TestService' }
テストケース(データ駆動テスト)
パラメータ化されたテストには-TestCasesまたは-ForEachを使用:
It 'Should return <Expected> for <Input>' -TestCases @(
@{ Input = 'value1'; Expected = 'result1' }
@{ Input = 'value2'; Expected = 'result2' }
) {
Get-Function $Input | Should -Be $Expected
}
データ駆動テスト
-ForEach: データから複数のテストを生成するためDescribe、Context、Itで利用可能-TestCases:Itブロックでの-ForEachの別名(後方互換性)- ハッシュテーブルデータ: 各項目はテストで利用可能な変数を定義(例:
@{ Name = 'value'; Expected = 'result' }) - 配列データ: 現在の項目に
$_変数を使用 - テンプレート: 動的展開のためにテスト名で
<変数名>を使用
# ハッシュテーブルアプローチ
It 'Returns <Expected> for <Name>' -ForEach @(
@{ Name = 'test1'; Expected = 'result1' }
@{ Name = 'test2'; Expected = 'result2' }
) { Get-Function $Name | Should -Be $Expected }
# 配列アプローチ
It 'Contains <_>' -ForEach 'item1', 'item2' { Get-Collection | Should -Contain $_ }
タグ
- 利用可能:
Describe、Context、Itブロック - フィルタリング:
Invoke-Pesterで-TagFilterと-ExcludeTagFilterを使用 - ワイルドカード: タグは柔軟なフィルタリングのため
-likeワイルドカードをサポート
Describe 'Function' -Tag 'Unit' {
It 'Should work' -Tag 'Fast', 'Stable' { }
It 'Should be slow' -Tag 'Slow', 'Integration' { }
}
# 高速なユニットテストのみ実行
Invoke-Pester -TagFilter 'Unit' -ExcludeTagFilter 'Slow'
スキップ
-Skip: テストをスキップするためにDescribe、Context、Itで利用可能- 条件付き: 動的スキップには
-Skip:$conditionを使用 - ランタイムスキップ: テスト実行中に
Set-ItResult -Skippedを使用(セットアップ/ティアダウンは実行される)
It 'Should work on Windows' -Skip:(-not $IsWindows) { }
Context 'Integration tests' -Skip { }
エラーハンドリング
- 失敗時継続: 複数の失敗を収集するために
Should.ErrorAction = 'Continue'を使用 - 重要な箇所で停止: 前提条件に
-ErrorAction Stopを使用 - 例外のテスト: 例外テストには
{ Code } | Should -Throwを使用
ベストプラクティス
- 説明的な名前: 動作を説明する明確なテスト説明を使用
- AAA パターン: 準備(Arrange)、実行(Act)、検証(Assert)
- 分離されたテスト: 各テストは独立している必要がある
- 別名を避ける: 完全なコマンドレット名を使用(
?ではなくWhere-Object) - 単一責任: 可能な場合はテストあたり一つのアサーション
- テストファイルの構成: 関連するテストを Context ブロックでグループ化。Context ブロックはネスト可能
テストパターンの例
BeforeAll {
. $PSScriptRoot/Get-UserInfo.ps1
}
Describe 'Get-UserInfo' {
Context 'When user exists' {
BeforeAll {
Mock Get-ADUser { @{ Name = 'TestUser'; Enabled = $true } }
}
It 'Should return user object' {
$result = Get-UserInfo -Username 'TestUser'
$result | Should -Not -BeNullOrEmpty
$result.Name | Should -Be 'TestUser'
}
It 'Should call Get-ADUser once' {
Get-UserInfo -Username 'TestUser'
Should -Invoke Get-ADUser -Exactly 1
}
}
Context 'When user does not exist' {
BeforeAll {
Mock Get-ADUser { throw "User not found" }
}
It 'Should throw exception' {
{ Get-UserInfo -Username 'NonExistent' } | Should -Throw "*not found*"
}
}
}
構成
構成は実行動作を制御するためにInvoke-Pesterを呼び出す際にテストファイル外で定義されます。
# 構成を作成(Pester 5.2以降)
$config = New-PesterConfiguration
$config.Run.Path = './Tests'
$config.Output.Verbosity = 'Detailed'
$config.TestResult.Enabled = $true
$config.TestResult.OutputFormat = 'NUnitXml'
$config.Should.ErrorAction = 'Continue'
Invoke-Pester -Configuration $config
主要セクション: Run(Path、Exit)、Filter(Tag、ExcludeTag)、Output(Verbosity)、TestResult(Enabled、OutputFormat)、CodeCoverage(Enabled、Path)、Should(ErrorAction)、Debug