0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PowerShellでUnitTestを作成するためのサンプル

Posted at

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
        }
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?