1
1

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.

SeleniumとPowershell(Pester)を用いた画面テスト自動化(キャプチャ自動取得機能付)

Last updated at Posted at 2023-08-18

TL;DR

  • 画面テスト自動化する機会があり、SeleniumとPowershellのテスティングフレームワーク(Pester)を組み合わせてスクリプトを作成したので備忘のため掲載。

  • UITestSuiteSampleForEdge.ps1のItブロック内の処理をテストしたいWebサービスにあわせて適宜修正してご活用ください。

  • テストケース単位に打鍵前後で画面キャプチャ取得します。以下2スクリプトを同フォルダに格納し実行してください。(画面キャプチャはデスクトップ上に保存されます)

  • 前提ブラウザはEdgeですがWebdriver差替により、他ブラウザでも動作可能な見込みです。(未検証)

UITestSuiteSampleForEdge.ps1
Set-StrictMode -Version 3.0


# テスト実施前にEdgeプロセスを停止しておくことをお勧めします。
# またテスト終了後Edgeプロセスはそのままとなります。適宜結果確認の上、手動停止ください。

# エラー発生時は処理中断。
$ErrorActionPreference = "Stop"

# ドライバ類の読み込み ref:https://note.com/dokoka3568/n/n4df03afcfe26
# 自環境のEdgeバージョンに合致するmsedgedriverをDL(https://developer.microsoft.com/ja-jp/microsoft-edge/tools/webdriver/)
# webdriver.dll入手先 https://www.nuget.org/packages/Selenium.WebDriver
# webdriver.support.dll入手先 https://www.nuget.org/packages/Selenium.Support
# DLしたファイルは必ず、ゾーン識別子情報を削除しておく。(対象ファイルのプロパティ画面を表示。画面下部の「セキュリティ」の欄にある「許可する」をチェック)
Add-Type -Path (Join-Path $PSScriptRoot "lib\WebDriver.dll")
Add-Type -Path (Join-Path $PSScriptRoot "lib\WebDriver.Support.dll")

# Screenshot取得用
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms

# ScreenShot取得クラスの読み込み
. (Join-Path $PSScriptRoot "CommonScreenShotUtil.ps1")

# オプションの指定
$Options = New-Object OpenQA.Selenium.Edge.EdgeOptions

# Headlessモード利用する際はこちらをコメントアウト
# $Options.AddArgument("headless")

# Edge Driverでサービスを作成
$Service = [OpenQA.Selenium.Edge.EdgeDriverService]::CreateDefaultService((Join-Path $PSScriptRoot "lib"), "msedgedriver.exe")

# ドライバオブジェクトを作成
$driver = New-Object OpenQA.Selenium.Edge.EdgeDriver($Service, $Options)

# 画面の最大化
$driver.Manage().Window.Maximize()
#$driver.Manage().Cookies.DeleteAllCookies();

# ScreenShotオブジェクトの作成と保存先の指定
$screenShotDriver = New-Object CommonScreenShotUtil("SampleApp", (Join-Path $env:userprofile "Desktop"))

# 処理間隔(秒)
$intervalSeconds = 1

# サービスURL
$url = "http://localhost:8080/"

Describe "SampleApp-UITest" {

    It "read-case" {

        $driver.Navigate().GoToUrl($url)

        $xpath = "/html/body/div[5]/div[1]/table/tbody[16]/tr/td[5]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Text | Should -Be "10,000"

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)
    }
 
    It "update-case" {

        $xpath = "/html/body/div[5]/div[1]/table/tbody[1]/tr/td[7]/form/button[1]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Click()

        Start-Sleep -Seconds $intervalSeconds

        $xpath = "/html/body/div[5]/div[1]/table/tbody[1]/tr/td[3]/input"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Clear()

        Start-Sleep -Seconds $intervalSeconds

        $element.SendKeys("660000")

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)

        Start-Sleep -Seconds $intervalSeconds

        $xpath = "/html/body/div[5]/div[1]/table/tbody[1]/tr/td[7]/button[1]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Click()        

        Start-Sleep -Seconds $intervalSeconds

        $xpath = "/html/body/div[5]/div[1]/table/tbody[1]/tr/td[3]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Text | Should -Be "660,000"

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)

    }

    It "update-case(invalid)" {

        $xpath = "/html/body/div[5]/div[1]/table/tbody[1]/tr/td[7]/form/button[1]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Click()

        Start-Sleep -Seconds $intervalSeconds

        $xpath = "/html/body/div[5]/div[1]/table/tbody[1]/tr/td[3]/input"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Clear()

        Start-Sleep -Seconds $intervalSeconds

        $element.SendKeys("test")

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)

        Start-Sleep -Seconds $intervalSeconds

        $xpath = "/html/body/div[5]/div[1]/table/tbody[1]/tr/td[7]/button[1]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Click()        

        Start-Sleep -Seconds $intervalSeconds

        # メッセージ確認
        $xpath = "/html/body/div[5]/div[1]/table/thead/tr[1]/th[2]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Text | Should -BeLike "*不正な値が入力されました*"

        $xpath = "/html/body/div[5]/div[1]/table/tbody[1]/tr/td[3]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Text | Should -Be "660,000"

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)

    }    

    It "delete-case" {

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)

        #検証用の当初値を取得
        $xpath = "/html/body/div[5]/div[1]/table/tbody[2]/tr/td[2]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $preservedValue = $element.Text
        Write-Host "Value:$preservedValue"

        #削除ボタンを押下
        $xpath = "/html/body/div[5]/div[1]/table/tbody[2]/tr/td[7]/form/button[2]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Click()

        Start-Sleep -Seconds $intervalSeconds

        # アラートをハンドルするためのオブジェクトを取得
        $alert = $driver.SwitchTo().Alert()
        # アラートのメッセージに対してOKを押す
        $alert.Accept()

        Start-Sleep -Seconds $intervalSeconds

        #当初値から変更されているかチェック
        $xpath = "/html/body/div[5]/div[1]/table/tbody[2]/tr/td[2]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $currentValue = $element.Text
        Write-Host "Value:$currentValue"

        $preservedValue | Should -Not -Be $currentValue

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)

    }

    It "create-case" {


        # selectBoxの上から3つ目を選択
        $xpath = "/html/body/div[5]/div[1]/table/tfoot/tr/td[1]/select"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $dropdown = [OpenQA.Selenium.Support.UI.SelectElement]($element)
        $dropdown.SelectByIndex(3)

        Start-Sleep -Seconds $intervalSeconds

        # 摘要を入力
        $xpath = "/html/body/div[5]/div[1]/table/tfoot/tr/td[2]/input"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.clear()
        $element.sendKeys("テスト入力")

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)

        Start-Sleep -Seconds $intervalSeconds

        # 追加ボタンを押下
        $xpath = "//*[@id='detailTable']/tfoot/tr/td[7]/button"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.click()

        Start-Sleep -Seconds $intervalSeconds

        # 値を検証
        $xpath = "/html/body/div[5]/div[1]/table/tbody[16]/tr/td[5]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Text | Should -Be "20,000"

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)

    }

    It "save" {

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)

        # 一覧保存ボタンを押下
        $xpath = "/html/body/div[5]/div[1]/table/thead/tr[1]/th[1]/form/button"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.click()

        Start-Sleep -Seconds $intervalSeconds

        # メッセージ確認
        $xpath = "/html/body/div[5]/div[1]/table/thead/tr[1]/th[2]"
        $element = $driver.FindElement([OpenQA.Selenium.By]::XPath($xpath))
        $element.Text | Should -BeLike "*保存しました*"

        $screenShotDriver.createScreenShot($MyInvocation.UnboundArguments[1].CurrentTest.Name)

    }

    $driver.Quit()

}

CommonScreenShotUtil.ps1

class CommonScreenShotUtil {

    [String]$filePath

    CommonScreenShotUtil($filePrefix,$filePath) {

        $this.filePath = $filePath

    }

    [void] createScreenShot($filePrefix){

        $width = 0;
        $height = 0;
        $workingAreaX = 0;
        $workingAreaY = 0;

        $screen = [System.Windows.Forms.Screen]::AllScreens

        foreach ($item in $screen) {
            if ($workingAreaX -gt $item.WorkingArea.X) {
                $workingAreaX = $item.WorkingArea.X;
            }

            if ($workingAreaY -gt $item.WorkingArea.Y) {
                $workingAreaY = $item.WorkingArea.Y;
            }

            $width = $width + $item.Bounds.Width;

            if ($item.Bounds.Height -gt $height) {
                $height = $item.Bounds.Height;
            }
        }

        $bounds = [Drawing.Rectangle]::FromLTRB($workingAreaX, $workingAreaY, $width, $height); 
        $bmp = New-Object Drawing.Bitmap $width, $height;
        $graphics = [Drawing.Graphics]::FromImage($bmp);

        $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size);

        $bmp.Save((Join-Path $this.filePath ($filePrefix + (Get-Date).ToString("-yyyyMMdd-HHmmssfff") + '.bmp')));

        $graphics.Dispose();
        $bmp.Dispose();
    }
}
1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?