windows app test automation by robotframework + WinAppDriver

# Outline

これまでWEBのテスト自動化をメインにやってきた。
今回、windowsアプリのテスト自動化を試してみた
その設定と、現時点 2024/03/19 のはまった点を合わせて記載する

- windows10 使用
- appium 2.x 使用
- Pythonは3.12と3.6 二つ使う
- WinAppDriver を常駐し、Windows アプリを操作する



# Initial Environment

まず、環境構築前の設定内容です。
後述するが、win app テストをするにあたって、version制限がある。
そのため、web用で構築していた環境を残しつつ、win app用の別環境を構築する必要がある

### Initial Environment

| software | version |
|:-----------|:------------|
| Python       | 3.12.2        |
| Appium-Python-Client       | 4.0.0       |
| selenium       | 4.18.1       |
| robotframework-appiumlibrary       | 2.0.0       |
| urllib3       | 2.2.1       |
| appium       | 2.5.1       |


# latest versionで起きた問題

winappdriverを起動し、そこに向けてappium libraryを用いて接続する

```
*** Settings ***

Library            AppiumLibrary


*** Variables ***
${WINAPP_SERVER}      http://localhost:4723
${APP}                Microsoft.WindowsCalculator_8wekyb3d8bbwe!App
#${APP}                C:\\Windows\\System32\\notepad.exe
${PLATFORM_NAME}      Windows
${DEVICE_NAME}        WindocwPC
${AUTOMATION_NAME}    windows
${TIMEOUT}            30


*** Keywords ***
Open WinAPP
	Open Application  ${WINAPP_SERVER}
		...   app=${APP}
		...   platformName=${PLATFORM_NAME}
		...   deviceName=${DEVICE_NAME}
		...   automationName=${AUTOMATION_NAME}
		

Close WinAPP
	Close Application


*** Test Cases ***
SetUp
	Open WinAPP

Test
	Click Element  accessibility_id=clearButton
	Click Element  accessibility_id=num7Button
	Element Should Contain Text  accessibility_id=CalculatorResults  ${SPACE}7${SPACE}

TearDown
	Close WinAPP
```

すると、winappdriver側で、以下のようなエラーになった。
どうやら、appium側で勝手にcapabilitiesのkeyを変換してしまい（例えば、app -> appium:app ）、winappdriver側で認識ができなくなっている。
そのため、エラーで、appがないぞとエラーになる。

```
User-Agent: appium/4.0.0 (selenium/4.18.1 (python windows))
X-Idempotency-Key: ff729bcb-566a-4295-bce2-f892cd702415

{"capabilities": {"firstMatch": [{}], "alwaysMatch": {"appium:capabilities": {"alwaysMatch": {"automationName": "Windows", "platformName": "Windows"}, "firstMatch": [{"appium:app": "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App"}, {"appium:app": "C:\\Windows\\System32\\notepad.exe", "appium:appArguments": "D:\\log.txt", "appium:appWorkingDir": "D:\\"}, {"appium:appTopLevelWindow": "0x3039"}]}}}}
HTTP/1.1 400 Bad Request
Content-Length: 141
Content-Type: application/json

{"status":100,"value":{"error":"invalid argument","message":"Bad capabilities. Specify either app or appTopLevelWindow to create a session"}}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/2bdc7420-9c2c-e73c-8359-7323f03fe22c.png)


この件に関して以下記事にも出ていた

https://github.com/microsoft/WinAppDriver/issues/1848

どうやら、Selenium4では動かないようだ。

また、winappを操作する別のframeworkである、robot frameworkにWhiteLibraryがある。
これも試そうとしたのだが、以下のようなエラーになった

```
C:\Users\sadaaki.emura\Documents\script\robot>robot winapp_calc_white.robot
[ ERROR ] Error in library 'WhiteLibrary': Adding keyword 'attach_application_by_id' failed: Calling dynamic method 'get_keyword_arguments' failed: AttributeError: module 'inspect' has no attribute 'getargspec'
[ ERROR ] Error in library 'WhiteLibrary': Adding keyword 'attach_application_by_name' failed: Calling dynamic method 'get_keyword_arguments' failed: AttributeError: module 'inspect' has no attribute 'getargspec'
[ ERROR ] Error in library 'WhiteLibrary': Adding keyword 'attach_window' failed: Calling dynamic method 'get_keyword_arguments' failed: AttributeError: module 'inspect' has no attribute 'getargspec'
[ ERROR ] Error in library 'WhiteLibrary': Adding keyword 'button_text_should_be' failed: Calling dynamic method 'get_keyword_arguments' failed: AttributeError: module 'inspect' has no attribute 'getargspec'
[ ERROR ] Error in library 'WhiteLibrary': Adding keyword 'button_text_should_contain' failed: Calling dynamic method 'get_keyword_arguments' failed: AttributeError: module 'inspect' has no attribute 'getargspec'
[ ERROR ] Error in library 'WhiteLibrary': Adding keyword 'click_button' failed: Calling dynamic method 'get_keyword_arguments' failed: AttributeError: module 'inspect' has no attribute 'getargspec'
[ ERROR ] Error in library 'WhiteLibrary': Adding keyword 'click_item' failed: Calling dynamic method 'get_keyword_arguments' failed: AttributeError: module 'inspect' has no attribute 'getargspec'
````

調べてみると、もうメンテされてなく、かつpython3.6までのsupportのようだ。

https://github.com/Omenia/robotframework-whitelibrary


そこで、既存の環境(python v3.12)を残しつつ、win appのテストをできるpython環境を構築する

# SetUp

## Appium

Appium Clientを用いてwin app driverに接続する。
そのため、Appiumもinstallする。
下記記事を参考にして入れる

https://qiita.com/emurin/items/c17bc2cda5ed6fa47d68

その後、appiumを経由してwinappdriverを使いたい場合、以下driverも入れる

```
appium driver install --source=npm appium-windows-driver
```

今回、Client -> WinAppDriver -> テスト対象 win app で接続するので、とくになくてもいい（らしい）

## Python

Python 3.6.8rc1  をdownloadする

https://www.python.org/downloads/windows/

その後、installされているpythonを確認する

```
py --list
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/1cc18cbb-a3f5-de64-c9c4-44cc3b260d1b.png)

このように、defaultが最初にインストールしたv3.12で、version指定で3.6も使える。
v3.6に、winappdriverが動く環境を構築する

v3.6で動かしたい場合、以下のようにする

```
py -3.6 -m xxxxx
```
※ xxxxx : robotやpython script


## library

pipを用いて、 v3.6用のライブラリをinstallする

```
py -3.6 -m pip install selenium==3.14
```

```
py -3.6 -m pip install Appium-Python-Client==1.3.0
```

```
py -3.6 -m pip install robotframework-appiumlibrary==1.6.4
```

```
py -3.6 -m pip install urllib3==1.26.16
```

```
py -3.6 -m pip install robotframework-seleniumlibrary
```

```
py -3.6 -m pip install robotframework-whitelibrary
```

```
py -3.6 -m pip install pytest
```

```
py -3.6 -m pip install webdriver-manager
```

installしたlibraryの確認


```
py -3.6 -m pip list
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/cabe01cb-9e57-41b7-ba46-ea2f80c1fc62.png)

## WinAppDriver

WinAppDriverはwindows　appを操作するドライバで、スクリプトからの指示を受けて操作するものである。
appiumみたいに、サーバーとして動き、スクリプトからの処理を待ち受ける。

今回、1.3を使用した。

https://github.com/Microsoft/WinAppDriver/releases

C:\Program Files\Windows Application Driver にinstallされる
ここでcommand lineを立ち上げ、特に何もしていせず起動する。
なお、もしappiumをすでに起動している場合、port番号がdefault 4723と被るので注意。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/8e76e4e2-041e-fd61-041f-1e478da89038.png)


## Inspect

テスト自動化にあたって、Appium Inspector , Chrome Developer toolと同様に、windows アプリの要素をとる必要がある。
その要素をとるinspect toolがあるので、それをinstallする

Windows 10 SDKのなかに、inspectがある

https://developer.microsoft.com/ja-jp/windows/downloads/sdk-archive/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/09974541-cd9a-1a55-1ccb-b92d2942d80a.png)


# execution

では、実際に電卓をたたく簡単なスクリプトを実行してみる

## AppiumLibrary + WinAppDriver

```
*** Settings ***

Library            AppiumLibrary


*** Variables ***
${WINAPP_SERVER}      http://localhost:4723
${APP}                Microsoft.WindowsCalculator_8wekyb3d8bbwe!App
${PLATFORM_NAME}      Windows
${DEVICE_NAME}        WindocwPC
${AUTOMATION_NAME}    windows


*** Keywords ***
Open WinAPP
	Open Application  ${WINAPP_SERVER}
		...   app=${APP}
		...   platformName=${PLATFORM_NAME}
		...   deviceName=${DEVICE_NAME}
		...   automationName=${AUTOMATION_NAME}

Close WinAPP
	Close Application


*** Test Cases ***
SetUp
	Open WinAPP

Test
	Click Element  accessibility_id=clearButton
	Click Element  accessibility_id=num7Button
	Element Should Contain Text  accessibility_id=CalculatorResults  ${SPACE}7${SPACE}

TearDown
	Close WinAPP
```

このscriptをpython 3.6で構築した環境で実行する

```
py -3.6 -m robot winapp01.robot
```

すると、電卓が立ち上がり、操作されていることが確認できる。
なお、scriptはrobotのAppiumLibraryで書くことができるため、WEBのテスト自動化経験者は割と簡単にコードをかける。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/cddfa197-841b-2630-6bdc-42e1613ec5bc.png)


## WhiteLibrary

WhiteLibraryはWinAppDriverを特に用いず、単独でアプリを操作できるライブラリ
ただ、2019年を最後に開発が止まっているので、使い続けるか要注意

コマンド

https://omenia.github.io/robotframework-whitelibrary/keywords.html

```
*** Settings ***
Library     OperatingSystem
Library     Process
Library     WhiteLibrary

*** Test Cases ***
NotepadTest
    Launch Application      notepad.exe
    Attach Window           無題 - メモ帳
    Input Text to Textbox   id:15   Testing
```