はじめに
手動テスト絶対許さないテスト自動化促進おじさんです
(今回の調査で手動テストも良いなーっておもいましたまる)
担当「@umasakiに自動テストの調査してもらうかのぉ」
私「Webの方は進めてひと段落してまっせ!」
担当「Windowsアプリケーションもあるで」
私「それはまだできまへん」
上長「めっちゃ期待してるでワレェェェ!」
私「こうなったらやってやるって!」
ということでヒアリングすると、Windowsアプリケーションでも結構な工数がシステムテストに取られてるっぽい。
ここを打開するべく調査をしました。
2018/09/13
必要ない設定や問題を追記しました。
利用したソフトウェア
検証するときに利用したソフトウェアです。
SikuliXというソフトにめちゃめちゃ惹かれましたが、Selenium統一のため以下のソフトになりました。
ソフト | バージョン | 備考 |
---|---|---|
java | 1.8.0_161 | |
selenium-server-standalone.jar | 3.11.0 | |
Node.js | 8.11.1 | |
windows-build-tools | 2.3.0 | npmからインストール |
Appium | 1.8.0 | npmからインストール |
wd | 1.6.2 | npmからインストール |
WinAppDriver | 1.0 | |
Windows 10 SDK | inspect.exeを利用 |
インストール
Windows10 32bit に環境を構築しました。
Windows10 を開発者モードに設定
設定 ⇒ 更新とセキュリティ ⇒ 開発者向け ⇒ 開発者モード で設定しました。
Node.js のインストール
node-v8.11.1-x86.msi をインストールしました。
npmでAppiumなどをインストール
サイトにある『簡単なインストールで今すぐAppiumを体験しよう』の内容で進めたところ、Appiumのインストールで速攻つまづきました。
ここから先はコマンドプロンプトを管理者権限で起動して作業しました。(したと思います)
接続の設定
上4つの設定はプロキシ使ってなかったら必要ないと思います。
一番したのコマンドも意味調べてないです。はい。
set HTTP_PROXY=http://proxyserver:8080
set HTTPS_PROXY=http://proxyserver:8080
npm config -g set proxy http://proxyserver:8080
npm config -g set https-proxy http://proxyserver:8080
npm config -g set registry http://registry.npmjs.org/
Pythonとか入れろとかのエラーを回避
Python入れろーとか色々エラーがでるのですが、このコマンドで解決しました。
便利
npm install --global --production windows-build-tools
Appiumをインストール
ふぃー(・д・`*)
npm install -g appium
2018/09/13 追記
Windows Application Driverだけの場合、Appium Clientは必要ありません。
Windows Application Driverをインストール
2018/09/13 追記
以下のコマンドでもインストールできました。
内部的にはWindowsApplicationDriver.msiを実行しているようなので、コマンドプロンプトを管理者権限で実行しなくてはいけないかもしれません。
npm install appium-windows-driver
WindowsApplicationDriver.msi をインストールしました。
環境構築
Selenium Grid Hubを立ち上げる
以下のコマンドを実行します。
java -jar selenium-server-standalone-3.11.0.jar -role hub
AppiumをNodeとして立ち上げる
jsonのconfiguration設定は意味調べてないです。
いらなそうな設定もあるがコピーペ。
{
"capabilities":
[
{
"platformName":"Windows",
"deviceName":"WindowsPC",
"maxInstances": 1
}
],
"configuration":
{
"cleanUpCycle":2000,
"timeout":30000,
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
"url":"(Node側)http://XXX.XXX.XXX.XXX:4723/wd/hub",
"host": "(Node側)XXX.XXX.XXX.XXX",
"port": (Node側)4723,
"maxSession": 1,
"register": true,
"registerCycle": 5000,
"hubPort": (Hub側)4444,
"hubHost": "(Hub側)XXX.XXX.XXX.XXX"
}
}
設定ファイルができたら以下のコマンドを実行します。
appium --nodeconfig NodeConfigAppium.json
実際に動かしてみる
サンプルをちょこっと変えて実行しました。
これで動かすと日本語OSであればコンソールに『表示は 8 です』と表示されます。
Mavenの設定は過去記事の環境に追加したので以下のようになっています。
Appiumだけ考えると結構いらないものが入ってますな。
package test;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.junit.AfterClass;Windows Application Driver
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import io.appium.java_client.windows.WindowsDriver;
public class CalculatorTest {
private static WindowsDriver<WebElement> CalculatorSession = null;
private static WebElement CalculatorResult = null;
@BeforeClass
public static void setup() {
try {
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("app", "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App");
capabilities.setCapability("deviceName", "WindowsPC");
capabilities.setCapability(CapabilityType.PLATFORM_NAME, "Windows");
CalculatorSession = new WindowsDriver<WebElement>(new URL("http://XXX.XXX.XXX.XXX:4723/wd/hub"), capabilities);
CalculatorSession.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
CalculatorResult = CalculatorSession.findElementByAccessibilityId("CalculatorResults");
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
@AfterClass
public static void TearDown() {
CalculatorResult = null;
if (CalculatorSession != null) {
CalculatorSession.quit();
}
CalculatorSession = null;
}
@Test
public void Addition() {
CalculatorSession.findElementByAccessibilityId("num1Button").click();
CalculatorSession.findElementByAccessibilityId("plusButton").click();
CalculatorSession.findElementByAccessibilityId("num7Button").click();
CalculatorSession.findElementByAccessibilityId("equalButton").click();
System.out.println(CalculatorResult.getText());
}
}
要素を調べる
2018/07/20 追記
下記よりWinAppDriver UI Recorderで調べた方が早いです。
Windows 10 SDKをインストールすると入る inspect.exe を利用します。
私の環境では C:\Program Files\Windows Kits\10\bin\10.0.16299.0\x86\inspect.exe にいました。
我流ですが・・・inspect.exe を起動して Always on Top のチェックを外します。
調査したいアプリケーション(ここでは電卓)を起動し、カーソルをしばらく合わせるかクリックし、AutomationIdを調べソースに反映していきました。
困っていること
2018/09/13 追記
以下の困りごとは appium 1.9.0 で直ってました
存在しない要素を指定すると指定時間でエラーにならず10分以上待つ
存在しない要素を指定すると指定時間でエラーにならず10分以上待つ
ログをの出力方法を変えて調査してみる。
appium 起動時の引数
appium --nodeconfig NodeConfigAppium.json --log "C:/Users/XXXXX/Desktop/node/log.txt" --log-level "info" --log-timestamp --local-timezone
出力ログ
〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
●電卓の結果要素を取得してるはず
2018-05-02 14:33:07:512 - info: [HTTP] --> POST /wd/hub/session/4b9d3b16-2dd0-4e79-82f8-ce5694e514c6/element
2018-05-02 14:33:07:512 - info: [HTTP] {"using":"accessibility id","value":"CalculatorResults"}
2018-05-02 14:33:07:512 - info: [W3C] Driver proxy active, passing request on via HTTP proxy
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT] ==========================================
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT] POST /wd/hub/session/6DF966FD-DB90-4ECC-B490-552323C225FF/element HTTP/1.1
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT] Accept: */*
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT] Connection: keep-alive
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT] Content-Length: 56
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT] Content-Type: application/json
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT] Host: 127.0.0.1:4724
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT] User-Agent: appium
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:33:07:590 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:33:07:622 - info: [WinAppDriver] [STDOUT] HTTP/1.1 200 OK
2018-05-02 14:33:07:622 - info: [WinAppDriver] [STDOUT] Content-Length: 100
2018-05-02 14:33:07:622 - info: [WinAppDriver] [STDOUT] Content-Type: application/json
2018-05-02 14:33:07:622 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:33:07:622 - info: [WinAppDriver] [STDOUT] {"sessionId":"6DF966FD-DB90-4ECC-B490-552323C225FF","status":0,"value":{"ELEMENT":"42.3540260.3.5"}}
2018-05-02 14:33:07:622 - info: [JSONWP Proxy] Replacing sessionId 6DF966FD-DB90-4ECC-B490-552323C225FF with 4b9d3b16-2dd0-4e79-82f8-ce5694e514c6
2018-05-02 14:33:07:622 - info: [HTTP] <-- POST /wd/hub/session/4b9d3b16-2dd0-4e79-82f8-ce5694e514c6/element 200 117 ms - 100
〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
●存在しない要素を取得してるはず
2018-05-02 14:33:32:841 - info: [HTTP] --> POST /wd/hub/session/4b9d3b16-2dd0-4e79-82f8-ce5694e514c6/element
2018-05-02 14:33:32:841 - info: [HTTP] {"using":"accessibility id","value":"num1Buttonabc"}
2018-05-02 14:33:32:841 - info: [W3C] Driver proxy active, passing request on via HTTP proxy
2018-05-02 14:33:33:044 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:33:33:044 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:33:33:044 - info: [WinAppDriver] [STDOUT] ==========================================
2018-05-02 14:33:33:059 - info: [WinAppDriver] [STDOUT] POST /wd/hub/session/6DF966FD-DB90-4ECC-B490-552323C225FF/element HTTP/1.1
2018-05-02 14:33:33:059 - info: [WinAppDriver] [STDOUT] Accept: */*
2018-05-02 14:33:33:059 - info: [WinAppDriver] [STDOUT] Connection: keep-alive
2018-05-02 14:33:33:059 - info: [WinAppDriver] [STDOUT] Content-Length: 52
2018-05-02 14:33:33:059 - info: [WinAppDriver] [STDOUT] Content-Type: application/json
2018-05-02 14:33:33:059 - info: [WinAppDriver] [STDOUT] Host: 127.0.0.1:4724
2018-05-02 14:33:33:059 - info: [WinAppDriver] [STDOUT] User-Agent: appium
2018-05-02 14:33:33:059 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:33:33:059 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:33:45:825 - info: [WinAppDriver] [STDOUT] HTTP/1.1 404 Not Found
2018-05-02 14:33:45:841 - info: [WinAppDriver] [STDOUT] Content-Length: 139
2018-05-02 14:33:45:841 - info: [WinAppDriver] [STDOUT] Content-Type: application/json
2018-05-02 14:33:45:841 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:33:45:841 - info: [WinAppDriver] [STDOUT] {"status":7,"value":{"error":"no such element","message":"An element could not be located on the page using the given search parameters."}}
↑↑↑POST返すまでに10分かかってる↓↓↓
2018-05-02 14:43:32:858 - info: [HTTP] <-- POST /wd/hub/session/4b9d3b16-2dd0-4e79-82f8-ce5694e514c6/element - - ms - -
〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
2018-05-02 14:47:20:139 - info: [HTTP] --> DELETE /wd/hub/session/4b9d3b16-2dd0-4e79-82f8-ce5694e514c6
2018-05-02 14:47:20:139 - info: [HTTP] {}
2018-05-02 14:47:20:139 - info: [Appium] Removing session 4b9d3b16-2dd0-4e79-82f8-ce5694e514c6 from our master session list
2018-05-02 14:47:20:171 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:47:20:171 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:47:20:171 - info: [WinAppDriver] [STDOUT] ==========================================
2018-05-02 14:47:20:171 - info: [WinAppDriver] [STDOUT] DELETE /wd/hub/session/6DF966FD-DB90-4ECC-B490-552323C225FF HTTP/1.1
2018-05-02 14:47:20:171 - info: [WinAppDriver] [STDOUT] Accept: */*
2018-05-02 14:47:20:186 - info: [WinAppDriver] [STDOUT] Connection: keep-alive
2018-05-02 14:47:20:186 - info: [WinAppDriver] [STDOUT] Content-Length: 0
2018-05-02 14:47:20:186 - info: [WinAppDriver] [STDOUT] Content-Type: application/json
2018-05-02 14:47:20:186 - info: [WinAppDriver] [STDOUT] Host: 127.0.0.1:4724
2018-05-02 14:47:20:186 - info: [WinAppDriver] [STDOUT] User-Agent: appium
2018-05-02 14:47:20:186 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:47:20:186 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:47:20:218 - info: [WinAppDriver] [STDOUT] HTTP/1.1 200 OK
2018-05-02 14:47:20:218 - info: [WinAppDriver] [STDOUT] Content-Length: 63
2018-05-02 14:47:20:233 - info: [WinAppDriver] [STDOUT] Content-Type: application/json
2018-05-02 14:47:20:233 - info: [WinAppDriver] [STDOUT]
2018-05-02 14:47:20:233 - info: [WinAppDriver] [STDOUT] {"sessionId":"6DF966FD-DB90-4ECC-B490-552323C225FF","status":0}
2018-05-02 14:47:20:233 - warn: [WinAppDriver] Did not get confirmation WinAppDriver deleteSession worked; Error was: Error: Did not get a valid response object. Object was: {"sessionId":"6DF966FD-DB90-4ECC-B490-552323C225FF","status":0}
2018-05-02 14:47:20:514 - info: [HTTP] <-- DELETE /wd/hub/session/4b9d3b16-2dd0-4e79-82f8-ce5694e514c6 200 295 ms - 76
〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
WinAppDriverで存在しない要素を取得して404を出した後、Postするまでに10分かかってる・・・
Appiumの問題(設定?)か切り分けるために、Windows Application Driverを直接起動して確かめる。
WinAppDriver 起動時の引数
ソース変えないで実行できるように引数で調整。
管理者権限で実行しないとだめってのをどこかで見ました。
"C:\Program Files\Windows Application Driver\WinAppDriver.exe" XXX.XXX.XXX.XXX 4723/wd/hub
結果・・・すぐ終わるやん!
エラーもNoSuchElementExceptionってちゃんと帰ってくるし、
Appium経由で解決できなければ、WinAppDriverを直接起動した方が良いかなぁ。
2018/09/13 追記
そして色々やってて新たな困りごとが・・・
1つのマシンでWindows Application Driver(WinAppDriver.exe)から複数アプリを起動しているとquitで起動しているアプリすべてのコネクションが切れる
Appiumを経由してWinAppDriver.exeが呼ばれてるんですが、WinAppDriver.exeのプロセスが複数アプリでも1つで、quitが呼ばれるとexeがなくなっているように見えました。
WinAppDriver.exeを直接起動するとquitでもWinAppDriver.exeのプロセスがなくなりません。(それはそれでどうかと思うんですが)
なのでうまく動きます。
closeだとプロセスは残ってもSelenium Gridでドライバが解放されてない扱いになるのでタイムアウトになるまで待つしかなくなります。
AppiumでWinAppDriver.exeを複数プロセスで起動してくれるとか何かしら処置がない限り、1つのマシンで起動できるSessionを1つに制限することにしました。