PowerShellでシンプルな単体テストを定義する
UnitTestをクラスとして作成する方式です。
UnitTest用のベースクラスと属性を提供するためのスクリプトモジュールファイル(.psm1)。
フレームワーク的な機能を提供する。
UnitTest.psm1
using namespace System.Collections.Generic;
[AttributeUsage([AttributeTargets]::Method,AllowMultiple=$false,Inherited=$true)]
class Test : Attribute
{
Test()
{
}
}
[AttributeUsage([AttributeTargets]::Method,AllowMultiple=$false,Inherited=$true)]
class SetUp : Attribute
{
SetUp()
{
}
}
[AttributeUsage([AttributeTargets]::Method,AllowMultiple=$false,Inherited=$true)]
class TearDown : Attribute
{
TearDown()
{
}
}
class UnitTestException:ApplicationException
{
}
class ErrorMsgList:List[string]
{
}
class TestBase
{
[object]$target;
[ErrorMsgList]$msgList;
TestBase()
{
$ErrorActionPreference = "Stop"
$Error.Clear();
$this.msgList = [ErrorMsgList]::new();
}
[void]RunTest()
{
$error.Clear()
$mytype = $this.GetType();
$memberList = $mytype.GetMethods();
$setUp = $null;
$tearDown = $null;
$testMemberList = New-Object System.Collections.ArrayList
foreach($member in $memberList )
{
$att=[Attribute]::GetCustomAttributes($member)
if($att -ne $null -and $att.Count -ge 1 )
{
$name = $att[0].GetType().Name
if( $name -eq "SetUp" )
{
$setUp = $member;
}
elseif( $name -eq "TearDown" )
{
$tearDown = $member;
}
elseif( $name -eq "Test" )
{
[void]$testMemberList.Add($member);
}
}
}
$succeedCount = 0
$errorCount = 0
$No = 1
foreach($testMember in $testMemberList )
{
$name = ""
try
{
if( $setUp -ne $null )
{
[void]$this."SetUp"();
}
$this.msgList = [ErrorMsgList]::new();
$name = $testMember.Name
[void]$this."$name"();
if( $tearDown -ne $null )
{
[void]$this."TearDown"();
}
Write-Host ("[{0}]OK:{1}" -F $No,$name ) -ForegroundColor Green
$succeedCount += 1
}
catch [Exception]
{
Write-Host ( "[{0}]NG:{1}" -F $No,$name ) -ForegroundColor Red
foreach($msg in $this.msgList)
{
Write-Host $msg -ForegroundColor Red
}
if( $_.Exception -ne $null )
{
if( $_.Exception.GetType().Name -ne 'UnitTestException' )
{
Write-Host ( " + Exception: {0}" -F $_.Exception.Message ) -ForegroundColor Red
}
}
$errorCount += 1
}
finally
{
$No += 1;
}
}
if( $errorCount -eq 0 )
{
Write-Host ("`nResult:OK={0}" -F $succeedCount ) -ForegroundColor Green
}
else
{
Write-Host ("`nResult:NG={0}:OK={1}" -F $errorCount,$succeedCount ) -ForegroundColor Red
}
}
[bool]AssertEquals([object]$expected,[object]$actual,[string]$message)
{
if($expected.Equals($actual ) -ne $true )
{
$this.msgList.Add( " + AssertEquals Fail" )
$this.msgList.Add( " + Message : $message" )
$this.msgList.Add( " + Expected: $expected" )
$this.msgList.Add( " + Actual : $actual" )
throw ( [UnitTestException]::new() )
}
return $true;
}
[bool]AssertEquals([object]$expected,[object]$actual)
{
return $this.AssertEquals( $expected, $actual,"Test failed." )
}
[bool]Assert( [bool] $condition, [string] $message )
{
if( $condition -eq $false )
{
$this.msgList.Add( " + Assert Fail" )
$this.msgList.Add( " + Message: $message" )
throw ( [UnitTestException]::new() )
}
return $true;
}
[bool]Assert( [bool] $condition )
{
return $this.Assert( $condition, "Test failed." );
}
}
UnitTestSample.ps1
UnitTestのサンプルスクリプト(.ps1)
using module .\UnitTest.psm1
class TestTarget
{
[int]Add([int]$a,[int]$b)
{
Write-host "TestTarget:Add"
return $a + $b;
}
}
class TestSample : TestBase
{
TestSample()
{
Write-host "TestSample:TestSample"
$this.target = [TestTarget]::new();
}
[SetUp()]
[void]SetUp()
{
Write-host "TestSample:SetUp"
$this.target = [TestTarget]::new();
}
[TearDown()]
[void]TearDown()
{
Write-host "TestSample:TearDown"
$this.target = $null;
}
[Test()]
[void]足し算テスト()
{
Write-host "TestSample:TestAdd1"
$this.AssertEquals( 3, $this.target.Add(1,2), "Error TestAdd1" );
}
[Test()]
[void]その他の足し算テスト()
{
Write-host "TestSample:TestAdd3"
$this.Assert( $this.target.Add(0,0) -eq 0, "Error Assertでチェック" );
$this.Assert( $this.target.Add(1,-1) -eq 0 );
}
[Test()]
[void]AssertEquals_エラー()
{
Write-host "AssertEquals_エラー"
$this.AssertEquals( 1, $this.target.Add(2,0), "Error AssertEquals" );
}
[Test()]
[void]Assert_エラー()
{
Write-host "Assert_エラー"
$this.Assert( ( 1 -eq $this.target.Add(2,0)) , "Error Assert" );
}
[Test()]
[void]例外_エラー()
{
Write-host "例外_エラー"
$zero = 0
$val = 1
$ans = $val / $zero
Write-Host $ans
}
}
$error.Clear()
[void](([TestSample]::new()).RunTest());
#スクリプトのエラー処理は、ここで行う必要がある
if( ( $error -ne $null ) -and ( $error.Count -ne 0 ) )
{
$errFlag = $false
foreach($err in $error)
{
if( $err.Exception.GetType().Name -ne 'UnitTestException' )
{
if( $errFlag -eq $false )
{
$errFlag = $true
Write-host "`n*****Error info*****"
}
$err
}
}
}