Chromiumプロジェクトにチェンジリストを送ってAndroid WebViewテストを改善した話
※この記事は自動テスト Advent Calendar 2020の3日目の記事です。
こんにちは、Magic Podの開発をしている脇坂です。
先日は Appium 1.19.0への貢献の話をしましたが、今度はChromeDriverへの貢献の話をします。ChromeDriver87から、弊社でチェンジリスト※1を出したandroidDevToolsPortというAndroid WebViewテスト向けのcapabilityが追加されています。
背景
実は話は1年ぐらい前に遡ります。当時Android WebViewのテスト機能 の開発をしている時、なぜかローカル環境では問題なく動くテストがクラウド環境のAndroidエミュレータでは動かない問題がありました。Appiumログ※2 には次のようなログ※3 が出ていました。
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 reachable\n (Driver info: chromedriver=74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}),platform=Mac OS X 10.14.6 x86_64)"}}
最初はさっぱりわからなかったのですが、いろいろ調べたところ、どうやら謎のポートを開こうとして、クラウド環境のポートフィルタ※4 に引っかかっていたらしいことがわかりました。そしてそのポートの正体はChrome DevTools用のポートらしいとわかりました。
ChromeDriver※5の実装も確認したところ、その裏がとれました。ポート指定もできないようです。よって、ポートフィルタを使う環境において、Android WebViewのテストはかなり厳しいことがわかりました。
解決策
そこで、Chrome DevToolsのポートを指定できるように、ChromeDriverを改修することにしました。愚直な解決策ではありますが、Android 10に搭載されたChrome74にのみ対応すれば良かった※6ため、当時は必要十分でした。ちなみに、ビルドと改修作業ですが、Chromiumプロジェクトのドキュメントはそれなりに充実しており、ビルドツールも整っていたため、初回のビルドに盛大な時間がかかること以外はあまり問題になりませんでした。
チェンジリストを出したきっかけ
涼しい顔して片付けた感を出しましたが、実際のところChromeDriverの改修が無事終わって良かったなぁと思いました。それでしばらく放置別のことをやっていましたが、Chrome 85がリリースされてからAndroid WebViewテストの機能が動かないケースがでてきました。Magic Pod側の改修で対応しましたが、この件でAndroid Chromeの重要性を認識するようになりました。AndroidのChromeバージョンを指定してMagic Podをテストできるなら、今後は同じ問題をより早く検知できる。こう考えた時、ChromeDriverを手前味噌ビルドし続けるのは苦しいと感じました。そこで、自分本意な理由であれですが、ChromeDriverを管轄しているChromiumプロジェクトにチェンジリストを出すことにしました。
チェンジリストの出し方
多くのOSSはGitHubを使ってますが、Chromiumプロジェクトではそれに代わる諸々をGoogleがホストしています。不具合管理にはMonorail、バージョン管理にはGit、コードレビューにはGerritを使っています。最初とっつきにくく感じるかもしれませんが、概ねGitHubでプルリクエストを出す時とそんなに変わらないと思います。具体的には下記のような流れになると思います。
- Monorailで問題点と解決策を書いてフィードバックをもらう
- 1で合意が取れたら、実装、動作確認する。足せるならテストも足す
- 出来上がった変更をGerritからレビューを出す。レビューは1で相手してくれた人にお願いする
- 3で何度かやりとりして、問題なければ取り込まれる
Chromiumは Canary->Dev->Beta->Stableの順でステージング※7されていて、取り込まれた変更は基本的に1-2ヶ月先にリリースされるStable版で一般お披露目されます。
androidDevToolsPort capabilityについて
今回追加されたandroidDevToolsPortを使うと、ChromeDriverがAndroid WebViewと通信をするために開くポート番号を指定することができます。具体的には次のようにcapabilityを指定します。
capabilities: { (...), chromeOptions: {androidDevToolsPort: <ポート番号>} }
こうすることでポートフィルタ環境でもAppiumによる Android WebViewのテストが可能になります。基本的にはポート番号を指定するだけの機能ですが、さらに応用的な使い方として、Chrome 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({ // Chrome DevToolsにリクエストを投げる url: "http://127.0.0.1:<CDP Port>/json/list", timeout: 2000 });
上記の例ではChrome DevToolsのGET /json/listのエンドポイントにHTTPリクエストを投げています。ただし、Appiumの場合、ChromeDriverを起動するために一度Webのコンテキストに切替えないといけない点は注意が必要です。
まとめ
さて、今回はChromeDriver87に追加された androidDevToolsPort capabilityとその経緯について紹介しました。これによりポートフィルタ環境でAndroid WebViewのテストが可能になりました。機会があれば使ってみて頂けると幸いです。
注釈・出典
- GitHubでいうプルリクエストのようなもの
- Magic PodはAppiumを使ってる
- 弊社Slackから掘り起こした当時のもの。今思えばshowChromedriverLog capabilityを使えば良かった気がする
- TCP/IPのポート番号に基いて通信の許可・拒否を設定することができるもの
- Android WebViewの実体はChromeであり、AppiumはChromeDriverを介してAndroid WebViewを操作している
- 弊社クラウド環境で提供しているAndroid エミュレータでは、Chromeのバージョンは固定されている
- https://www.chromestatus.com/features/schedule