【PowerShell】Selenium-Module SeShouldHave コードチェック

目次

概要

 Seleniumで取得した要素やウィンドウが期待した内容かチェックし、条件が成立しない場合、エラーを発生させます。SeShouldHaveを利用するためには、まずドライバーを$Global:SeDriver変数に代入しなければ動作しません。

 PowerShellでSeleniumを利用するに当たって、ある程度簡易的にSeleniumを利用できる様に専用のモジュールがGitHubに用意されています。いきなりPowerShellでSeleniumを扱うより、Seleniumを-Moduleを利用した方が簡単にPowerShellでSleniumを利用することができます。環境構築するには、以下ページを参照してみてください。

コマンド(Commond)

SeShouldHave

代替コマンド(Alias)

無し

構文(Syntax)

  • SeShouldHave [-Selection] <string[]> [-By <string>] [-PassThru] [-Timeout <int>] [<CommonParameters>]
  • SeShouldHave [-Selection] <string[]> [-With] <string> [[-Operator] <string>] [[-Value] <Object>] [-By <string>] [-PassThru] [-Timeout <int>] [<CommonParameters>]
  • SeShouldHave [[-Operator] <string>] [[-Value] <Object>] -Alert [-PassThru] [-Timeout <int>] [<CommonParameters>]
  • SeShouldHave -NoAlert [-Timeout <int>] [<CommonParameters>]
  • SeShouldHave [[-Operator] <string>] [-Value] <Object> -Title [-Timeout <int>] [<CommonParameters>]
  • SeShouldHave [[-Operator] <string>] [-Value] <Object> -URL [-Timeout <int>] [<CommonParameters>]

オプション

Name引数型解説Short Example
Selectionstring検証対象を指定SeShouldHave -Selection $Element.TagName -With 'Text' -Operator match -Value "new" -By TagName
BystringWeb要素取得方法を以下から入力
“CssSelector”, “Name”, “Id”, “ClassName”, “LinkText”, “PartialLinkText”, “TagName”, “XPath”
SeShouldHave -Selection $Element.TagName -With 'Text' -Operator match -Value "new" -By TagName
PassThruhashtableオブジェクトのプロパティ情報を取得SeShouldHave -Operator match -Value "programan" -Title -PassThru
Timeoutintタイムアウト時間
Withstring検証対象のプロパティ要素を以下から指定
'Text', 'Displayed', 'Enabled', 'TagName', 'X', 'Y', 'Width', 'Height', 'Choice'
SeShouldHave -Selection $Element.TagName -With 'Text' -Operator match -Value "new" -By TagName
Operatorstring演算子を以下から指定
'Contains', 'eq', 'ne', 'like', 'notlike', 'match', 'notmatch', 'gt', 'le'
SeShouldHave -Selection $Element.TagName -With 'Text' -Operator match -Value "new" -By TagName
ValueObject検証に用いたいキーワード等を指定SeShouldHave -Operator match -Value "programan" -Title
Alert
NoAlert
Title検証したいウィンドウタイトルを指定SeShouldHave -Operator match -Value "programan" -Title
URL検証したいURLを指定SeShouldHave -Operator like -Value "https://programan*" -URL

※ShortExampleは、動作確認ができたコードを記載しています。

Example

 SeShouldHaveを利用するためには、まずドライバーを$Global:SeDriver変数に代入しなければ動作しません。

$Driver = Start-SeChrome -DefaultDownloadPath $DownloadDir -StartURL "https://programan.org/" -Quiet
$Element = Get-SeElement -Target $Driver -ClassName "newmark" -Timeout 10

$Global:SeDriver = $Driver
SeShouldHave -Operator like -Value "https://programan*" -URL
SeShouldHave -Operator match -Value "programan" -Title
SeShouldHave -Selection $Element.TagName -With 'Text' -Operator match -Value "new" -By TagName
Stop-SeDriver $Driver

Module

SeShouldHaveのSelenium-Module構文を以下に掲載します。

function SeShouldHave {
    [cmdletbinding(DefaultParameterSetName = 'DefaultPS')]
    param(
        [Parameter(ParameterSetName = 'DefaultPS', Mandatory = $true , Position = 0, ValueFromPipeline = $true)]
        [Parameter(ParameterSetName = 'Element' , Mandatory = $true , Position = 0, ValueFromPipeline = $true)]
        [string[]]$Selection,

        [Parameter(ParameterSetName = 'DefaultPS', Mandatory = $false)]
        [Parameter(ParameterSetName = 'Element' , Mandatory = $false)]
        [ValidateSet('CssSelector', 'Name', 'Id', 'ClassName', 'LinkText', 'PartialLinkText', 'TagName', 'XPath')]
        [ByTransformAttribute()]
        [string]$By = 'XPath',

        [Parameter(ParameterSetName = 'Element' , Mandatory = $true , Position = 1)]
        [string]$With,

        [Parameter(ParameterSetName = 'Alert' , Mandatory = $true)]
        [switch]$Alert,
        [Parameter(ParameterSetName = 'NoAlert' , Mandatory = $true)]
        [switch]$NoAlert,
        [Parameter(ParameterSetName = 'Title' , Mandatory = $true)]
        [switch]$Title,
        [Parameter(ParameterSetName = 'URL' , Mandatory = $true)]
        [Alias('URI')]
        [switch]$URL,

        [Parameter(ParameterSetName = 'Element' , Mandatory = $false, Position = 3)]
        [Parameter(ParameterSetName = 'Alert' , Mandatory = $false, Position = 3)]
        [Parameter(ParameterSetName = 'Title' , Mandatory = $false, Position = 3)]
        [Parameter(ParameterSetName = 'URL' , Mandatory = $false, Position = 3)]
        [ValidateSet('like', 'notlike', 'match', 'notmatch', 'contains', 'eq', 'ne', 'gt', 'lt')]
        [OperatorTransformAttribute()]
        [String]$Operator = 'like',

        [Parameter(ParameterSetName = 'Element' , Mandatory = $false, Position = 4)]
        [Parameter(ParameterSetName = 'Alert' , Mandatory = $false, Position = 4)]
        [Parameter(ParameterSetName = 'Title' , Mandatory = $true , Position = 4)]
        [Parameter(ParameterSetName = 'URL' , Mandatory = $true , Position = 4)]
        [Alias('contains', 'like', 'notlike', 'match', 'notmatch', 'eq', 'ne', 'gt', 'lt')]
        [AllowEmptyString()]
        $Value,

        [Parameter(ParameterSetName = 'DefaultPS')]
        [Parameter(ParameterSetName = 'Element')]
        [Parameter(ParameterSetName = 'Alert')]
        [Alias('PT')]
        [switch]$PassThru,

        [Int]$Timeout = 0
    )
    begin {
        $endTime = [datetime]::now.AddSeconds($Timeout)
        $lineText = $MyInvocation.Line.TrimEnd("$([System.Environment]::NewLine)")
        $lineNo = $MyInvocation.ScriptLineNumber
        $file = $MyInvocation.ScriptName
        Function expandErr {
            param ($message)
            [Management.Automation.ErrorRecord]::new(
                [System.Exception]::new($message),
                'PesterAssertionFailed',
                [Management.Automation.ErrorCategory]::InvalidResult,
                @{
                    Message  = $message
                    File     = $file
                    Line     = $lineNo
                    Linetext = $lineText
                }
            )
        }
        function applyTest {
            param(
                $Testitems,
                $Operator,
                $Value
            )
            Switch ($Operator) {
                'Contains' { return ($testitems -contains $Value) }
                'eq' { return ($TestItems -eq $Value) }
                'ne' { return ($TestItems -ne $Value) }
                'like' { return ($TestItems -like $Value) }
                'notlike' { return ($TestItems -notlike $Value) }
                'match' { return ($TestItems -match $Value) }
                'notmatch' { return ($TestItems -notmatch $Value) }
                'gt' { return ($TestItems -gt $Value) }
                'le' { return ($TestItems -lt $Value) }
            }
        }

        #if operator was not passed, allow it to be taken from an alias for the -value
        if (-not $PSBoundParameters.ContainsKey('operator') -and $lineText -match ' -(eq|ne|contains|match|notmatch|like|notlike|gt|lt) ') {
            $Operator = $matches[1]
        }
        $Success = $false
        $foundElements = @()
    }
    process {
        #If we have been asked to check URL or title get them from the driver. Otherwise call Get-SEElement.
        if ($URL) {
            do {
                $Success = applyTest -testitems $Global:SeDriver.Url -operator $Operator -value $Value
                Start-Sleep -Milliseconds 500
            }
            until ($Success -or [datetime]::now -gt $endTime)
            if (-not $Success) {
                throw (expandErr "PageURL was $($Global:SeDriver.Url). The comparison '-$operator $value' failed.")
            }
        }
        elseif ($Title) {
            do {
                $Success = applyTest -testitems $Global:SeDriver.Title -operator $Operator -value $Value
                Start-Sleep -Milliseconds 500
            }
            until ($Success -or [datetime]::now -gt $endTime)
            if (-not $Success) {
                throw (expandErr "Page title was $($Global:SeDriver.Title). The comparison '-$operator $value' failed.")
            }
        }
        elseif ($Alert -or $NoAlert) {
            do {
                try {
                    $a = $Global:SeDriver.SwitchTo().alert()
                    $Success = $true
                }
                catch {
                    Start-Sleep -Milliseconds 500
                }
                finally {
                    if ($NoAlert -and $a) { throw (expandErr "Expected no alert but an alert of '$($a.Text)' was displayed") }
                }
            }
            until ($Success -or [datetime]::now -gt $endTime)

            if ($Alert -and -not $Success) {
                throw (expandErr "Expected an alert but but none was displayed")
            }
            elseif ($value -and -not (applyTest -testitems $a.text -operator $Operator -value $value)) {
                throw (expandErr "Alert text was $($a.text). The comparison '-$operator $value' failed.")
            }
            elseif ($PassThru) { return $a }
        }
        else {
            foreach ($s in $Selection) {
                $GSEParams = @{By = $By; Selection = $s }
                if ($Timeout) { $GSEParams['Timeout'] = $Timeout }
                try { $e = Get-SeElement @GSEParams }
                catch { throw (expandErr $_.Exception.Message) }

                #throw if we didn't get the element; if were only asked to check it was there, return gracefully
                if (-not $e) { throw (expandErr "Didn't find '$s' by $by") }
                else {
                    Write-Verbose "Matched element(s) for $s"
                    $foundElements += $e
                }
            }
        }
    }
    end {
        if ($PSCmdlet.ParameterSetName -eq "DefaultPS" -and $PassThru) { return $e }
        elseif ($PSCmdlet.ParameterSetName -eq "DefaultPS") { return }
        else {
            foreach ($e in $foundElements) {
                switch ($with) {
                    'Text' { $testItem = $e.Text }
                    'Displayed' { $testItem = $e.Displayed }
                    'Enabled' { $testItem = $e.Enabled }
                    'TagName' { $testItem = $e.TagName }
                    'X' { $testItem = $e.Location.X }
                    'Y' { $testItem = $e.Location.Y }
                    'Width' { $testItem = $e.Size.Width }
                    'Height' { $testItem = $e.Size.Height }
                    'Choice' { $testItem = (Get-SeSelectionOption -Element $e -ListOptionText) }
                    default { $testItem = $e.GetAttribute($with) }
                }
                if (-not $testItem -and ($Value -ne '' -and $foundElements.count -eq 1)) {
                    throw (expandErr "Didn't find '$with' on element")
                }
                if (applyTest -testitems $testItem -operator $Operator -value $Value) {
                    $Success = $true
                    if ($PassThru) { $e }
                }
            }
            if (-not $Success) {
                if ($foundElements.count -gt 1) {
                    throw (expandErr "$Selection match $($foundElements.Count) elements, none has a value for $with which passed the comparison '-$operator $value'.")
                }
                else {
                    throw (expandErr "$with had a value of $testitem which did not pass the the comparison '-$operator $value'.")
                }
            }
        }
    }
}
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

VBAを中心とした自動化、効率化の手法を紹介しています。現在は、SeleniumBasicのexamplesを紹介しています。その内、SeleniumBasic以外の手法も掲載したいと思っております。

目次