Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
AppiumのWebViewアプリテストの
仕組みとハマりどころ
mwakizaka(TRIDENTInc)
⾃⼰紹介
脇坂雅幸
エンジニア@TRIDENTInc.
MagicPodの開発とテニスをしています
2
MagicPod
テスト⾃動化サービス
https://magic-pod.com/
2017年07⽉ローンチ
モバイルアプリとデスクトップブラウザ
アプリのテスト⾃動化に対応
3
本⽇の話
WebViewの実体はブラウザ
AppiumによるWebViewアプリテストはChromeDevToolsのプロトコルで動いてる
WebViewアプリはWebアプリとしてテストしましょう
4
本⽇の流れ
WebView
Appium
WebViewアプリテストの仕組みとハマりどころ
Android編
iOS編
まとめ
5
WebView
6
WebView
モバイルアプリにおける画⾯要素の1つ(右図の⾚枠)
Webコンテンツを表⽰することが可能
実体はブラウザ(AndroidはChrome、iOSはSafari)
Webの技術でAndroid/iOSアプリで開発できる
さらにWeb...
WebViewアプリの⾃動テスト
そもそもWebView要素の中⾝の捉え⽅は2つある
i.Webな画⾯要素として捉える(e.g. input )
ii.ネイティブな画⾯要素として捉える(e.g. android.widget.EditText ...
WebViewアプリのデバッグAndroid(1/2)
ChromeDevToolsを使う
9
WebViewアプリのデバッグAndroid(2/2)
例えば、デスクトップブラウザアプリと同じように⾒栄えを⾊々試したりできる
10
WebViewアプリのデバッグiOS(1/2)
Safariの開発者メニューからWebInspectorを使う
11
WebViewアプリのデバッグiOS(2/2)
iOSでも同様にHTMLタグの中⾝を確認したりできる
12
Appium
13
Appium
OSSでクロスプラットフォームなE2Eテスト⾃動化フレームワーク
WebDriverを拡張したプロトコルでiOSやAndroidアプリを⾃動操作できる
WebViewアプリテストではコンテキストとウィンドウハンドルを扱う必要がある...
コンテキスト(context)
UIコンポーネントの特定や検証の対象が「Webなのか」
「ネイティブなのか」を決めるもの
e.g.findelement時にWebViewから、Webの要素を
探すのかネイティブの要素を探すのかを決める
driv...
ウィンドウハンドル(windowhandle)
Androidのみ(iOSだと普段使うことはない)
Webコンテキストの時、アプリ上のどのWebViewが
要素特定や検証の対象かを決めるもの
driver.switchToWindow('<ウィ...
コンテキストとウィンドウのデバッグ
ChromeDevTools/WebInspectorを使う
1つのアプリに2つのWebViewが読み込まれている時、
1つのコンテキストと2つのウィンドウが存在
17
コンテキストの切り替えができない時は
ChromeDevTools/WebInspectorを使い、問題の切り分けを⾏う
WebViewのHTMLが⾒えない場合は、アプリか端末設定に問題があることが多い
⼿前味噌ですが、https://www....
AndroidのWebViewアプリテストの仕組み
19
AndroidのWebViewアプリテストの仕組み
AppiumはMobileJsonWireProtocolを実装したクライアントサーバモデル
SeleniumのJsonWireProtocolを拡張したもの
HTTP/REST形式で、リクエ...
通信経路
21
通信経路解説
以下のAppiumクライアントコード(WebDriverIO)を例に説明
1. | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
2. | driver.$("//i...
通信経路の確⽴(1/3)
> | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
| driver.$("//input[@id='datePick']") // xpathで要素を...
通信経路の確⽴(2/3)
AppiumがChromeDriverを起動する
> | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
| driver.$("//input[@id='...
通信経路の確⽴(3/3)
ChromeDriverでAndroid端末内のChromeDevToolsとソケット通信を確⽴する
> | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替...
要素の探索(1/3)
AppiumクライアントからAppiumサーバにHTTPリクエストを投げる
http://localhost:<appium_port>/wd/hub/session/<session_id>/element
| driv...
要素の探索(2/3)
AppiumサーバからChromeDriverサーバにリクエストがプロキシされる
http://localhost:
<chrome_driver_port>/wd/hub/session/<session_id>/ele...
要素の探索(3/3)
ChromeDriverサーバからAndroid端末のChromeDevToolsにリクエストを投げる
Runtime.evaluate {"expression": "JSコード(Selenium Atoms)",
"r...
AndroidのWebViewアプリテストのハマりどころ
.ウィンドウ区別つかない問題
.ポートフィルタリングできない問題
29
1.ウィンドウ区別つかない問題
2つ以上のWebViewが読み込まれている場合、
GetWindowHandlesAPIを呼び、ウィンドウを選択する
driver.getWindowHandles();
-> ["CDwindow-05FAC4...
1.ウィンドウ区別つかない問題
タイトルやURLを使っても区別がつかない場合がある
31
1.ウィンドウ区別つかない問題-原因
ウィンドウがdetachedという状態で残っていることが原因
32
1.ウィンドウ区別つかない問題-解決策
ChromeDevToolsのAPIを使う
GET /json or /json/list のAPIを使うと detached かどうかわかる
https://chromedevtools.github....
2.ポートフィルタリングできない問題
ローカルのマシンで問題なく動いたAndroidWebViewのテストが
なぜかクラウド環境で動作しなかった
SetContextAPIを呼んだ時に次のようなエラーが出た
2019-11-29 11:22:3...
2.ポートフィルタリングできない問題-原因
ChromeDevToolsのポートがポートフィルタの設定に引っかかっていた
しかもChromeDriverは任意のポート番号を使うようにハードコードされていた!
35
2.ポートフィルタリングできない問題-解決策
ChromeDevToolsのポート番号を指定するためにChromeDriverを改修
こちらはChromiumプロジェクトに修正パッチを送りました
https://chromium-review....
iOSのWebViewアプリテストの仕組み
37
iOSのWebViewアプリテストの仕組み
iOSになっても基本は同じ。ただし、ChromeDriverは出てこない
38
通信経路
iOS実機の場合(iOSシミュレータの場合もさほど違いはありません)
39
通信経路解説
以下のAppiumクライアントコード(WebDriverIO)を例に説明
1. | driver.getContexts(); // コンテキストを取得
2. | driver.switchContext('<WEBVIEW_**...
通信経路の確⽴(1/3)
> | driver.getContexts(); // コンテキストを取得
| driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
| driver.$("/...
通信経路の確⽴(2/3)
Appiumサーバ内部でRemoteDebuggerを起動する
> | driver.getContexts(); // コンテキストを取得
| driver.switchContext('<WEBVIEW_***>'...
通信経路の確⽴(3/3)
iOS端末内でWebInspectorを起動する
> | driver.getContexts(); // コンテキストを取得
| driver.switchContext('<WEBVIEW_***>'); // w...
通信経路の切替
RemoteDebuggerを使うよう、Appiumサーバの内部状態を切替える
| driver.getContexts(); // コンテキストを取得
> | driver.switchContext('<WEBVIEW_**...
要素の探索(1/2)
AppiumクライアントからAppiumサーバにHTTPリクエストを投げる
http://localhost:<appium_port>/wd/hub/session/<session_id>/element
| driv...
要素の探索(2/2)
RemoteDebuggerからiOS端末のWebInspectorにリクエストを投げる
Runtime.evaluate {"expression": "JSコード(Selenium Atoms)",
"returnBy...
iOSのWebViewアプリテストのハマりどころ
.Safariハング問題
.Webコンテキストが⾒つからない問題
47
1.Safariハング問題
WebViewテストのパフォーマンスが劇的に悪化
完全に固まるわけではない
再現コード(WebDriverIO)
01. | // ネイティブコンテキストで任意の要素を探す
02. | await driver.$(...
1.Safariハング問題
正常時のパフォーマンス
[HTTP] --> POST /wd/hub/session/1d99092f-6a81-4229-937b-c0c0ce3b9e03/context
[HTTP] {"name":"WEB...
1.Safariハング問題-原因
とある条件を満たすと、2⾏⽬でSafariがハングする
01. | // ネイティブコンテキストで任意の要素を探す
02. | await driver.$("XCUIElementTypeWebView");...
1.Safariハング問題-再現条件
.ある程度の規模のWebコンテンツをWebViewに表⽰している
3000⾏程度のHTMLファイル?
.その画⾯でネイティブ要素をfindelementする
.iOS14.2未満(!)
iOS14.2*Ap...
1.Safariハング問題-解決策
今のところ、iOS14.2未満を避けるかページ(HTML)サイズを⾒直すしかない模様
MobileSafariはiOSのバージョンアップでしか更新できない
52
2.Webコンテキストが⾒つからない問題
WebViewを使っているにも関わらず、Webコンテンツが⾒えない
iOS実機 SafariのDevelopタブ
考えられる原因はいくつかあるが、最もニッチな事例を紹介
53
2.Webコンテキストが⾒つからない問題-期待値
本来は github.com - releases のような形でWebコンテンツが⾒えるはず
54
2.Webコンテキストが⾒つからない問題-原因
実はiOS実機向けのipaファイルは Development ビルドでなければならない
https://stackoverflow.com/questions/37524723/use-safar...
2.Webコンテキストが⾒つからない問題-解決策
. Development ビルドのipaファイルを使う
.ビルド済みipaファイルの署名を書き換える
fastlaneのresignAPIを使えば可能
https://docs.fastlan...
まとめ
57
プラットフォーム固有な問題を乗り越えた先
WebのロケータをiOS/Androidで共有できるので、
クロスプラットフォームなテストスクリプトが作りやすくなる
テストケースの作成・メンテナンスコストを抑えられます
58
まとめ
WebViewの実体はブラウザ
AppiumによるWebViewアプリテストはChromeDevToolsのプロトコルで動いてる
WebViewアプリはWebアプリとしてテストしましょう
59
採⽤しています
テクノロジーの⼒でテストの世界を変えたいエンジニアの⽅を⼤募集中
https://www.trident-qa.com/recruit/ 60
おわり
61
以下、おまけ
62
テストケース(ロケータ)作りにくいの件(1/2)
e.g.http://example.selenium.jp/reserveApp_Renewal/で実験
Android iOS 63
テストケース(ロケータ)作りにくいの件(2/2)
対応する画⾯要素(iOSだとdatePickというidが使えない)
Androidの場合
<android.widget.EditText (...) text="2020/12/5" reso...
androidDevToolsPortの使い道
Android端末のDevToolsに直接アクセスすることができるようになります
const wdio = require("webdriverio");
const axios = requir...
1.Safariハング問題-補⾜
この問題が起きた時、以下のようなAppiumログが出ることがあるようです
アラートを出した覚えはないですが。。。
これ⾒たら、Safariハングしたかも、と思っていいかもです
[WD Proxy] Got re...
通信経路(AndroidNativeアプリ)
67
通信経路(iOSNativeアプリ)
68
Ref
iOS/AndroidのUIテストを⾃動化するAppiumのテストスクリプトの書き⽅とインスペ
クターの使い⽅(3/3)
https://www.atmarkit.co.jp/ait/articles/1506/02/news017_3...
EOF
70
Prochain SlideShare
Chargement dans…5
×

AppiumのWebViewアプリテストの仕組みとハマりどころ

STAC 2020

  • Soyez le premier à commenter

AppiumのWebViewアプリテストの仕組みとハマりどころ

  1. 1. AppiumのWebViewアプリテストの 仕組みとハマりどころ mwakizaka(TRIDENTInc)
  2. 2. ⾃⼰紹介 脇坂雅幸 エンジニア@TRIDENTInc. MagicPodの開発とテニスをしています 2
  3. 3. MagicPod テスト⾃動化サービス https://magic-pod.com/ 2017年07⽉ローンチ モバイルアプリとデスクトップブラウザ アプリのテスト⾃動化に対応 3
  4. 4. 本⽇の話 WebViewの実体はブラウザ AppiumによるWebViewアプリテストはChromeDevToolsのプロトコルで動いてる WebViewアプリはWebアプリとしてテストしましょう 4
  5. 5. 本⽇の流れ WebView Appium WebViewアプリテストの仕組みとハマりどころ Android編 iOS編 まとめ 5
  6. 6. WebView 6
  7. 7. WebView モバイルアプリにおける画⾯要素の1つ(右図の⾚枠) Webコンテンツを表⽰することが可能 実体はブラウザ(AndroidはChrome、iOSはSafari) Webの技術でAndroid/iOSアプリで開発できる さらにWebアプリとしてテスト可能 本⾴以降、WebViewを使ったアプリのことを WebViewアプリと呼ぶことにします 7
  8. 8. WebViewアプリの⾃動テスト そもそもWebView要素の中⾝の捉え⽅は2つある i.Webな画⾯要素として捉える(e.g. input ) ii.ネイティブな画⾯要素として捉える(e.g. android.widget.EditText ) ネイティブな画⾯要素としてテストする時の問題 i.テストケース(ロケータ)が作りにくい(特にiOS) ii.プラットフォーム差分を吸収しづらい そのため、Webな画⾯要素としてテストする⽅が好ましい 8
  9. 9. WebViewアプリのデバッグAndroid(1/2) ChromeDevToolsを使う 9
  10. 10. WebViewアプリのデバッグAndroid(2/2) 例えば、デスクトップブラウザアプリと同じように⾒栄えを⾊々試したりできる 10
  11. 11. WebViewアプリのデバッグiOS(1/2) Safariの開発者メニューからWebInspectorを使う 11
  12. 12. WebViewアプリのデバッグiOS(2/2) iOSでも同様にHTMLタグの中⾝を確認したりできる 12
  13. 13. Appium 13
  14. 14. Appium OSSでクロスプラットフォームなE2Eテスト⾃動化フレームワーク WebDriverを拡張したプロトコルでiOSやAndroidアプリを⾃動操作できる WebViewアプリテストではコンテキストとウィンドウハンドルを扱う必要がある 14
  15. 15. コンテキスト(context) UIコンポーネントの特定や検証の対象が「Webなのか」 「ネイティブなのか」を決めるもの e.g.findelement時にWebViewから、Webの要素を 探すのかネイティブの要素を探すのかを決める driver.switchContext('<コンテキスト名>'); のような APIでコンテキストを切替える 参考:http://appium.io/docs/en/writing-running-appium/web/hybrid/index.html 15
  16. 16. ウィンドウハンドル(windowhandle) Androidのみ(iOSだと普段使うことはない) Webコンテキストの時、アプリ上のどのWebViewが 要素特定や検証の対象かを決めるもの driver.switchToWindow('<ウィンドウハンドル名>'); の ようなAPIでウィンドウハンドルを切替える 以下、単にウィンドウ(window)と呼ぶことにします 16
  17. 17. コンテキストとウィンドウのデバッグ ChromeDevTools/WebInspectorを使う 1つのアプリに2つのWebViewが読み込まれている時、 1つのコンテキストと2つのウィンドウが存在 17
  18. 18. コンテキストの切り替えができない時は ChromeDevTools/WebInspectorを使い、問題の切り分けを⾏う WebViewのHTMLが⾒えない場合は、アプリか端末設定に問題があることが多い ⼿前味噌ですが、https://www.trident-qa.com/magic-pod-webview/の 真ん中あたりの情報が(多少)参考になると思います 18
  19. 19. AndroidのWebViewアプリテストの仕組み 19
  20. 20. AndroidのWebViewアプリテストの仕組み AppiumはMobileJsonWireProtocolを実装したクライアントサーバモデル SeleniumのJsonWireProtocolを拡張したもの HTTP/REST形式で、リクエスト及びレスポンスにJSONを使う 様々なプログラミング⾔語でテストコードが書ける ただし、ネイティブアプリをテストする場合と通信経路が少し異なる 参考:https://speakerdeck.com/jlipps/the-mobile-json-wire-protocol 20
  21. 21. 通信経路 21
  22. 22. 通信経路解説 以下のAppiumクライアントコード(WebDriverIO)を例に説明 1. | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 2. | driver.$("//input[@id='datePick']") // xpathで要素を探す 22
  23. 23. 通信経路の確⽴(1/3) > | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 | driver.$("//input[@id='datePick']") // xpathで要素を探す 23
  24. 24. 通信経路の確⽴(2/3) AppiumがChromeDriverを起動する > | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 | driver.$("//input[@id='datePick']") // xpathで要素を探す 24
  25. 25. 通信経路の確⽴(3/3) ChromeDriverでAndroid端末内のChromeDevToolsとソケット通信を確⽴する > | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 | driver.$("//input[@id='datePick']") // xpathで要素を探す 25
  26. 26. 要素の探索(1/3) AppiumクライアントからAppiumサーバにHTTPリクエストを投げる http://localhost:<appium_port>/wd/hub/session/<session_id>/element | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 > | driver.$("//input[@id='datePick']") // xpathで要素を探す 26
  27. 27. 要素の探索(2/3) AppiumサーバからChromeDriverサーバにリクエストがプロキシされる http://localhost: <chrome_driver_port>/wd/hub/session/<session_id>/element | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 > | driver.$("//input[@id='datePick']") // xpathで要素を探す 27
  28. 28. 要素の探索(3/3) ChromeDriverサーバからAndroid端末のChromeDevToolsにリクエストを投げる Runtime.evaluate {"expression": "JSコード(Selenium Atoms)", "returnByValue": true} ソケット通信で専⽤コマンドとJSコードを送り、ブラウザ上で実⾏している | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 > | driver.$("//input[@id='datePick']") // xpathで要素を探す 28
  29. 29. AndroidのWebViewアプリテストのハマりどころ .ウィンドウ区別つかない問題 .ポートフィルタリングできない問題 29
  30. 30. 1.ウィンドウ区別つかない問題 2つ以上のWebViewが読み込まれている場合、 GetWindowHandlesAPIを呼び、ウィンドウを選択する driver.getWindowHandles(); -> ["CDwindow-05FAC41124AAF0D7A0E458BB1B689C28","CDwindow-743FE72111B559A70A90C2D08595B5E4"] ウィンドウ名には情報量がないため、 基本的にWebコンテンツのタイトルやURLで区別する https://appiumpro.com/editions/73-working-with-multile-webviews-in-android-hybrid-apps 30
  31. 31. 1.ウィンドウ区別つかない問題 タイトルやURLを使っても区別がつかない場合がある 31
  32. 32. 1.ウィンドウ区別つかない問題-原因 ウィンドウがdetachedという状態で残っていることが原因 32
  33. 33. 1.ウィンドウ区別つかない問題-解決策 ChromeDevToolsのAPIを使う GET /json or /json/list のAPIを使うと detached かどうかわかる https://chromedevtools.github.io/devtools-protocol/ あまり簡単ではないので、Appiumにプルリクエストを出しました https://github.com/appium/appium-android-driver/pull/662 Appium1.19.0から mobile:getContexts というAPIとして使えます より詳しい話はこちら https://blog.trident-qa.com/2020/11/android-mobile-getcontexts-api/ 33
  34. 34. 2.ポートフィルタリングできない問題 ローカルのマシンで問題なく動いたAndroidWebViewのテストが なぜかクラウド環境で動作しなかった SetContextAPIを呼んだ時に次のようなエラーが出た 2019-11-29 11:22:37:732 d ^[[35m[WD Proxy]^[[39m Got response with status 200: {"sessionId":"09c75c3f7a260230c14b48c356a4d974","status":100,"value": {"message":"chrome not reachablen (Driver info: chromedriver=74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9- refs/branch-heads/3729@{#29}),platform=Mac OS X 10.14.6 x86_64)"}} 弊社Slackから掘り起こした当時のAppiumログ。今思えばshowChromedriverLogcapabilityを使えば良かった気がする 34
  35. 35. 2.ポートフィルタリングできない問題-原因 ChromeDevToolsのポートがポートフィルタの設定に引っかかっていた しかもChromeDriverは任意のポート番号を使うようにハードコードされていた! 35
  36. 36. 2.ポートフィルタリングできない問題-解決策 ChromeDevToolsのポート番号を指定するためにChromeDriverを改修 こちらはChromiumプロジェクトに修正パッチを送りました https://chromium-review.googlesource.com/c/chromium/src/+/2433746 ChromeDriver87からcapabilityとして同様の機能が使えます Appiumcapabilityとしての使⽤例 capabilities: { (...), chromeOptions: {androidDevToolsPort: <ポート番号>} } より詳しい(?)話はこちら https://blog.trident-qa.com/2020/12/chromium-androiddevtoolsport/ 36
  37. 37. iOSのWebViewアプリテストの仕組み 37
  38. 38. iOSのWebViewアプリテストの仕組み iOSになっても基本は同じ。ただし、ChromeDriverは出てこない 38
  39. 39. 通信経路 iOS実機の場合(iOSシミュレータの場合もさほど違いはありません) 39
  40. 40. 通信経路解説 以下のAppiumクライアントコード(WebDriverIO)を例に説明 1. | driver.getContexts(); // コンテキストを取得 2. | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 3. | driver.$("//input[@id='datePick']") // xpathで要素を探す 40
  41. 41. 通信経路の確⽴(1/3) > | driver.getContexts(); // コンテキストを取得 | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 | driver.$("//input[@id='datePick']") // xpathで要素を探す 41
  42. 42. 通信経路の確⽴(2/3) Appiumサーバ内部でRemoteDebuggerを起動する > | driver.getContexts(); // コンテキストを取得 | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 | driver.$("//input[@id='datePick']") // xpathで要素を探す 42
  43. 43. 通信経路の確⽴(3/3) iOS端末内でWebInspectorを起動する > | driver.getContexts(); // コンテキストを取得 | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 | driver.$("//input[@id='datePick']") // xpathで要素を探す 43
  44. 44. 通信経路の切替 RemoteDebuggerを使うよう、Appiumサーバの内部状態を切替える | driver.getContexts(); // コンテキストを取得 > | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 | driver.$("//input[@id='datePick']") // xpathで要素を探す 44
  45. 45. 要素の探索(1/2) AppiumクライアントからAppiumサーバにHTTPリクエストを投げる http://localhost:<appium_port>/wd/hub/session/<session_id>/element | driver.getContexts(); // コンテキストを取得 | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 > | driver.$("//input[@id='datePick']") // xpathで要素を探す 45
  46. 46. 要素の探索(2/2) RemoteDebuggerからiOS端末のWebInspectorにリクエストを投げる Runtime.evaluate {"expression": "JSコード(Selenium Atoms)", "returnByValue": true} 実はAndroidと同様のプロトコルを使っている | driver.getContexts(); // コンテキストを取得 | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替 > | driver.$("//input[@id='datePick']") // xpathで要素を探す 46
  47. 47. iOSのWebViewアプリテストのハマりどころ .Safariハング問題 .Webコンテキストが⾒つからない問題 47
  48. 48. 1.Safariハング問題 WebViewテストのパフォーマンスが劇的に悪化 完全に固まるわけではない 再現コード(WebDriverIO) 01. | // ネイティブコンテキストで任意の要素を探す 02. | await driver.$("XCUIElementTypeWebView"); 03. | 04. | // Webコンテキストを⾒つける任意のラッパー関数 05. | const webContext = await getWebContext(driver); 06. | 07. | // Webコンテキストで任意の要素を探す 08. | // 特定の条件を満たすとパフォーマンスが悪化する 09. | await driver.switchContext(webContext); 10. | await driver.$("#r106"); https://github.com/appium/appium/issues/14149 48
  49. 49. 1.Safariハング問題 正常時のパフォーマンス [HTTP] --> POST /wd/hub/session/1d99092f-6a81-4229-937b-c0c0ce3b9e03/context [HTTP] {"name":"WEBVIEW_13197.1"} [HTTP] <-- POST /wd/hub/session/1d99092f-6a81-4229-937b-c0c0ce3b9e03/context 200 610 ms - 76 [HTTP] [HTTP] --> POST /wd/hub/session/1d99092f-6a81-4229-937b-c0c0ce3b9e03/element [HTTP] {"using":"id","value":"r106"} [HTTP] <-- POST /wd/hub/session/1d99092f-6a81-4229-937b-c0c0ce3b9e03/element 200 200 ms - 135 ハング時のパフォーマンス(1-2分待たされる) [HTTP] --> POST /wd/hub/session/d1809037-a034-41c2-81e6-dace57657e7d/context [HTTP] {"name":"WEBVIEW_11653.1"} [HTTP] <-- POST /wd/hub/session/d1809037-a034-41c2-81e6-dace57657e7d/context 200 16075 ms - 76 [HTTP] [HTTP] --> POST /wd/hub/session/d1809037-a034-41c2-81e6-dace57657e7d/element [HTTP] {"using":"id","value":"r106"} [HTTP] <-- POST /wd/hub/session/d1809037-a034-41c2-81e6-dace57657e7d/element 200 85120 ms - 135 49
  50. 50. 1.Safariハング問題-原因 とある条件を満たすと、2⾏⽬でSafariがハングする 01. | // ネイティブコンテキストで任意の要素を探す 02. | await driver.$("XCUIElementTypeWebView"); 03. | 04. | // Webコンテキストを⾒つける任意のラッパー関数 05. | const webContext = await getWebContext(driver); 06. | 07. | // Webコンテキストで任意の要素を探す 08. | // 特定の条件を満たすとパフォーマンスが悪化する 09. | await driver.switchContext(webContext); 10. | await driver.$("#r106"); 50
  51. 51. 1.Safariハング問題-再現条件 .ある程度の規模のWebコンテンツをWebViewに表⽰している 3000⾏程度のHTMLファイル? .その画⾯でネイティブ要素をfindelementする .iOS14.2未満(!) iOS14.2*Appium1.19.0で再現しなくなったのを確認 51
  52. 52. 1.Safariハング問題-解決策 今のところ、iOS14.2未満を避けるかページ(HTML)サイズを⾒直すしかない模様 MobileSafariはiOSのバージョンアップでしか更新できない 52
  53. 53. 2.Webコンテキストが⾒つからない問題 WebViewを使っているにも関わらず、Webコンテンツが⾒えない iOS実機 SafariのDevelopタブ 考えられる原因はいくつかあるが、最もニッチな事例を紹介 53
  54. 54. 2.Webコンテキストが⾒つからない問題-期待値 本来は github.com - releases のような形でWebコンテンツが⾒えるはず 54
  55. 55. 2.Webコンテキストが⾒つからない問題-原因 実はiOS実機向けのipaファイルは Development ビルドでなければならない https://stackoverflow.com/questions/37524723/use-safari-web-inspector-with-apps-compiled-for-production/42122477#42122477 55
  56. 56. 2.Webコンテキストが⾒つからない問題-解決策 . Development ビルドのipaファイルを使う .ビルド済みipaファイルの署名を書き換える fastlaneのresignAPIを使えば可能 https://docs.fastlane.tools/actions/resign/ 56
  57. 57. まとめ 57
  58. 58. プラットフォーム固有な問題を乗り越えた先 WebのロケータをiOS/Androidで共有できるので、 クロスプラットフォームなテストスクリプトが作りやすくなる テストケースの作成・メンテナンスコストを抑えられます 58
  59. 59. まとめ WebViewの実体はブラウザ AppiumによるWebViewアプリテストはChromeDevToolsのプロトコルで動いてる WebViewアプリはWebアプリとしてテストしましょう 59
  60. 60. 採⽤しています テクノロジーの⼒でテストの世界を変えたいエンジニアの⽅を⼤募集中 https://www.trident-qa.com/recruit/ 60
  61. 61. おわり 61
  62. 62. 以下、おまけ 62
  63. 63. テストケース(ロケータ)作りにくいの件(1/2) e.g.http://example.selenium.jp/reserveApp_Renewal/で実験 Android iOS 63
  64. 64. テストケース(ロケータ)作りにくいの件(2/2) 対応する画⾯要素(iOSだとdatePickというidが使えない) Androidの場合 <android.widget.EditText (...) text="2020/12/5" resource- id="datePick" (...) /> iOSの場合 <XCUIElementTypeTextField type="XCUIElementTypeTextField" value="2020/12/5" label="" enabled="true" visible="true" x="40" y="315" width="140" height="40"/> HTMLの場合 <input id="datePick" type="input" class="span4" maxlength="10" style="font-size:22px; width:140px; text-align:center;" value=""> 64
  65. 65. androidDevToolsPortの使い道 Android端末のDevToolsに直接アクセスすることができるようになります const wdio = require("webdriverio"); const axios = require("axios").axios; const option = { (...), capabilities: { (..), chromeOptions: {androidDevToolsPort: <CDP Port>} } } const driver = await wdio.remote(option); (...) await driver.switchContext(<contextName>); // ChromeDriverを起動する const detailedContexts = await axios({ // CDPにリクエスト投げる url: "http://127.0.0.1:<CDP Port>/json/list", timeout: 2000 }); AppiumでChromeDriverを起動する必要はありますが、 指定したポート番号を使ってそれ以降は直接アクセスできます 65
  66. 66. 1.Safariハング問題-補⾜ この問題が起きた時、以下のようなAppiumログが出ることがあるようです アラートを出した覚えはないですが。。。 これ⾒たら、Safariハングしたかも、と思っていいかもです [WD Proxy] Got response with status 404: { [WD Proxy] "value" : { [WD Proxy] "error" : "no such alert", [WD Proxy] "message" : "An attempt was made to operate on a modal dialog when one was not open", [WD Proxy] "traceback" : "" [WD Proxy] }, [WD Proxy] "sessionId" : "0B4FC99E-DE0F-4E68-B7FC-C99034BA43FF" [WD Proxy] } [W3C] Matched W3C error code 'no such alert' to NoSuchAlertError 66
  67. 67. 通信経路(AndroidNativeアプリ) 67
  68. 68. 通信経路(iOSNativeアプリ) 68
  69. 69. Ref iOS/AndroidのUIテストを⾃動化するAppiumのテストスクリプトの書き⽅とインスペ クターの使い⽅(3/3) https://www.atmarkit.co.jp/ait/articles/1506/02/news017_3.html WebViewアプリテストのAppium公式ドキュメント http://appium.io/docs/en/writing-running-appium/web/hybrid/ ChromeDevToolsProtocolの公式ドキュメント https://chromedevtools.github.io/devtools-protocol/ iOSにおけるWebViewアプリのメリデメの話 https://qiita.com/susu_susu__/items/aff3b8cc26cd2d5535f8 fastlaneの使い⽅参考例 https://speakerdeck.com/kariad/apurifalsepahuomansuwoji-sok-de-niji-ce-suru? slide=28 69
  70. 70. EOF 70

×