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アプリと呼ぶことにします
7
WebViewアプリの⾃動テスト
そもそもWebView要素の中⾝の捉え⽅は2つある
i.Webな画⾯要素として捉える(e.g. input )
ii.ネイティブな画⾯要素として捉える(e.g. android.widget.EditText )
ネイティブな画⾯要素としてテストする時の問題
i.テストケース(ロケータ)が作りにくい(特にiOS)
ii.プラットフォーム差分を吸収しづらい
そのため、Webな画⾯要素としてテストする⽅が好ましい
8
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アプリテストではコンテキストとウィンドウハンドルを扱う必要がある
14
コンテキスト(context)
UIコンポーネントの特定や検証の対象が「Webなのか」
「ネイティブなのか」を決めるもの
e.g.findelement時にWebViewから、Webの要素を
探すのかネイティブの要素を探すのかを決める
driver.switchContext('<コンテキスト名>'); のような
APIでコンテキストを切替える
参考:http://appium.io/docs/en/writing-running-appium/web/hybrid/index.html 15
ウィンドウハンドル(windowhandle)
Androidのみ(iOSだと普段使うことはない)
Webコンテキストの時、アプリ上のどのWebViewが
要素特定や検証の対象かを決めるもの
driver.switchToWindow('<ウィンドウハンドル名>'); の
ようなAPIでウィンドウハンドルを切替える
以下、単にウィンドウ(window)と呼ぶことにします
16
コンテキストとウィンドウのデバッグ
ChromeDevTools/WebInspectorを使う
1つのアプリに2つのWebViewが読み込まれている時、
1つのコンテキストと2つのウィンドウが存在
17
コンテキストの切り替えができない時は
ChromeDevTools/WebInspectorを使い、問題の切り分けを⾏う
WebViewのHTMLが⾒えない場合は、アプリか端末設定に問題があることが多い
⼿前味噌ですが、https://www.trident-qa.com/magic-pod-webview/の
真ん中あたりの情報が(多少)参考になると思います 18
AndroidのWebViewアプリテストの仕組み
19
AndroidのWebViewアプリテストの仕組み
AppiumはMobileJsonWireProtocolを実装したクライアントサーバモデル
SeleniumのJsonWireProtocolを拡張したもの
HTTP/REST形式で、リクエスト及びレスポンスにJSONを使う
様々なプログラミング⾔語でテストコードが書ける
ただし、ネイティブアプリをテストする場合と通信経路が少し異なる
参考:https://speakerdeck.com/jlipps/the-mobile-json-wire-protocol 20
通信経路
21
通信経路解説
以下のAppiumクライアントコード(WebDriverIO)を例に説明
1. | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
2. | driver.$("//input[@id='datePick']") // xpathで要素を探す
22
通信経路の確⽴(1/3)
> | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
| driver.$("//input[@id='datePick']") // xpathで要素を探す
23
通信経路の確⽴(2/3)
AppiumがChromeDriverを起動する
> | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
| driver.$("//input[@id='datePick']") // xpathで要素を探す
24
通信経路の確⽴(3/3)
ChromeDriverでAndroid端末内のChromeDevToolsとソケット通信を確⽴する
> | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
| driver.$("//input[@id='datePick']") // xpathで要素を探す
25
要素の探索(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
要素の探索(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
要素の探索(3/3)
ChromeDriverサーバからAndroid端末のChromeDevToolsにリクエストを投げる
Runtime.evaluate {"expression": "JSコード(Selenium Atoms)",
"returnByValue": true}
ソケット通信で専⽤コマンドとJSコードを送り、ブラウザ上で実⾏している
| driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
> | driver.$("//input[@id='datePick']") // xpathで要素を探す 28
AndroidのWebViewアプリテストのハマりどころ
.ウィンドウ区別つかない問題
.ポートフィルタリングできない問題
29
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
1.ウィンドウ区別つかない問題
タイトルやURLを使っても区別がつかない場合がある
31
1.ウィンドウ区別つかない問題-原因
ウィンドウがdetachedという状態で残っていることが原因
32
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
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
2.ポートフィルタリングできない問題-原因
ChromeDevToolsのポートがポートフィルタの設定に引っかかっていた
しかもChromeDriverは任意のポート番号を使うようにハードコードされていた!
35
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
iOSのWebViewアプリテストの仕組み
37
iOSのWebViewアプリテストの仕組み
iOSになっても基本は同じ。ただし、ChromeDriverは出てこない
38
通信経路
iOS実機の場合(iOSシミュレータの場合もさほど違いはありません)
39
通信経路解説
以下のAppiumクライアントコード(WebDriverIO)を例に説明
1. | driver.getContexts(); // コンテキストを取得
2. | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
3. | driver.$("//input[@id='datePick']") // xpathで要素を探す
40
通信経路の確⽴(1/3)
> | driver.getContexts(); // コンテキストを取得
| driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
| driver.$("//input[@id='datePick']") // xpathで要素を探す
41
通信経路の確⽴(2/3)
Appiumサーバ内部でRemoteDebuggerを起動する
> | driver.getContexts(); // コンテキストを取得
| driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
| driver.$("//input[@id='datePick']") // xpathで要素を探す
42
通信経路の確⽴(3/3)
iOS端末内でWebInspectorを起動する
> | driver.getContexts(); // コンテキストを取得
| driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
| driver.$("//input[@id='datePick']") // xpathで要素を探す
43
通信経路の切替
RemoteDebuggerを使うよう、Appiumサーバの内部状態を切替える
| driver.getContexts(); // コンテキストを取得
> | driver.switchContext('<WEBVIEW_***>'); // webコンテキストに切替
| driver.$("//input[@id='datePick']") // xpathで要素を探す
44
要素の探索(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
要素の探索(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
iOSのWebViewアプリテストのハマりどころ
.Safariハング問題
.Webコンテキストが⾒つからない問題
47
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
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
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
1.Safariハング問題-再現条件
.ある程度の規模のWebコンテンツをWebViewに表⽰している
3000⾏程度のHTMLファイル?
.その画⾯でネイティブ要素をfindelementする
.iOS14.2未満(!)
iOS14.2*Appium1.19.0で再現しなくなったのを確認
51
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-safari-web-inspector-with-apps-compiled-for-production/42122477#42122477 55
2.Webコンテキストが⾒つからない問題-解決策
. Development ビルドのipaファイルを使う
.ビルド済みipaファイルの署名を書き換える
fastlaneのresignAPIを使えば可能
https://docs.fastlane.tools/actions/resign/
56
まとめ
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" 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
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
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
通信経路(AndroidNativeアプリ)
67
通信経路(iOSNativeアプリ)
68
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
EOF
70

More Related Content

PDF
ソーシャルゲームのためのデータベース設計
PDF
新入社員のための大規模ゲーム開発入門 サーバサイド編
PDF
IL2CPPに関する軽い話
PDF
ドメイン駆動設計 ( DDD ) をやってみよう
PPTX
Redisの特徴と活用方法について
PDF
テスト文字列に「うんこ」と入れるな
PDF
サーバー未経験者がソーシャルゲームを通して知ったサーバーの事
PDF
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
ソーシャルゲームのためのデータベース設計
新入社員のための大規模ゲーム開発入門 サーバサイド編
IL2CPPに関する軽い話
ドメイン駆動設計 ( DDD ) をやってみよう
Redisの特徴と活用方法について
テスト文字列に「うんこ」と入れるな
サーバー未経験者がソーシャルゲームを通して知ったサーバーの事
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス

What's hot (20)

PDF
Ansibleはじめよぉ -Infrastructure as Codeを理解-
PDF
マイクロサービス 4つの分割アプローチ
PDF
マルチテナント化で知っておきたいデータベースのこと
PDF
AWSのログ管理ベストプラクティス
PDF
Appium 2.0 ではじめるモバイルアプリテスト
PDF
Mavenの真実とウソ
PDF
より速く より運用しやすく 進化し続けるJVM(Java Developers Summit Online 2023 発表資料)
PDF
[AWS EXpert Online for JAWS-UG 18] 見せてやるよ、Step Functions の本気ってやつをな
PPTX
RLSを用いたマルチテナント実装 for Django
ODP
SPAのルーティングの話
PDF
【Unity】 Behavior TreeでAIを作る
PDF
開発速度が速い #とは(LayerX社内資料)
PDF
Twitterのsnowflakeについて
PDF
シリコンバレーの「何が」凄いのか
PPTX
CloudFront経由でのCORS利用
PDF
Docker Compose 徹底解説
PDF
コンテナ未経験新人が学ぶコンテナ技術入門
PDF
ユーザーストーリー駆動開発で行こう。
PDF
TDD のこころ
PPTX
Goss入門
Ansibleはじめよぉ -Infrastructure as Codeを理解-
マイクロサービス 4つの分割アプローチ
マルチテナント化で知っておきたいデータベースのこと
AWSのログ管理ベストプラクティス
Appium 2.0 ではじめるモバイルアプリテスト
Mavenの真実とウソ
より速く より運用しやすく 進化し続けるJVM(Java Developers Summit Online 2023 発表資料)
[AWS EXpert Online for JAWS-UG 18] 見せてやるよ、Step Functions の本気ってやつをな
RLSを用いたマルチテナント実装 for Django
SPAのルーティングの話
【Unity】 Behavior TreeでAIを作る
開発速度が速い #とは(LayerX社内資料)
Twitterのsnowflakeについて
シリコンバレーの「何が」凄いのか
CloudFront経由でのCORS利用
Docker Compose 徹底解説
コンテナ未経験新人が学ぶコンテナ技術入門
ユーザーストーリー駆動開発で行こう。
TDD のこころ
Goss入門
Ad

Similar to AppiumのWebViewアプリテストの仕組みとハマりどころ (20)

PDF
jQuery と MVC で実践する標準志向 Web 開発
PDF
[公開用]Netラボ2012年2月勉強会 asp.netmvc4 beta新機能の紹介
PDF
VSCodeで始めるAzure Static Web Apps開発
PPTX
13016 n分で作るtype scriptでnodejs
PDF
Tech talk salesforce mobile sdk
PPTX
20111204 WebBroser Control Tips for Windows Phone
PDF
iOS WebView App
PDF
20200516 selenium-meetup-winappdriver
PDF
Featuring Project Silk & Liike: 楽しい "モダン" Web 開発のちょっとディープなお話
PPTX
Selenium webdriver使ってみようず
PPTX
Express Web Application Framework
PDF
Vue入門
PDF
ソーシャルアプリ勉強会(第一回資料)配布用
PDF
APIMeetup 20170329_ichimura
PDF
Next2Dで始めるゲーム開発 - Game Development Starting with Next2D
PDF
[使い倒し]GitHubのIssueとTFS/VSOのWorkItem連動に挑む(2015/08/26)
PPTX
Web リソースを活用した簡単アプリケーション開発(Windows Phone)
PPTX
Web Intents入門
PDF
勉強会force#3 iOSアプリ開発
PPT
ASP.NET MVC 1.0
jQuery と MVC で実践する標準志向 Web 開発
[公開用]Netラボ2012年2月勉強会 asp.netmvc4 beta新機能の紹介
VSCodeで始めるAzure Static Web Apps開発
13016 n分で作るtype scriptでnodejs
Tech talk salesforce mobile sdk
20111204 WebBroser Control Tips for Windows Phone
iOS WebView App
20200516 selenium-meetup-winappdriver
Featuring Project Silk & Liike: 楽しい "モダン" Web 開発のちょっとディープなお話
Selenium webdriver使ってみようず
Express Web Application Framework
Vue入門
ソーシャルアプリ勉強会(第一回資料)配布用
APIMeetup 20170329_ichimura
Next2Dで始めるゲーム開発 - Game Development Starting with Next2D
[使い倒し]GitHubのIssueとTFS/VSOのWorkItem連動に挑む(2015/08/26)
Web リソースを活用した簡単アプリケーション開発(Windows Phone)
Web Intents入門
勉強会force#3 iOSアプリ開発
ASP.NET MVC 1.0
Ad

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