Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ブラウザ自動操作技術の深層へ、直接触れて学ぶ WebDriver と Chrome DevTools Protocol

ブラウザ自動操作技術の深層へ、直接触れて学ぶ WebDriver と Chrome DevTools Protocol

ウェブアプリケーションの開発においてE2Eテストの自動化は身近なトピックです。SeleniumやPuppetter、PlaywrightやAppiumなどがブラウザ・ネイティブアプリの自動操作のOSSとしてよく挙げられます。しかし、それらの裏側はご存知でしょうか?

本トークではこれらのツールの背後にいるWebDriver、Chrome DevTools Protocolsに焦点を当てます。

WebDriver、CDPとはなにか、その違い、仕様について、PHPエンジニアに身近な言語を用いて"直接"実装することを通じて解説します。

本トークを通じて直接触れることでライブラリでwrapされている裏側まで知ることできます。E2Eテスト自動化の課題に出会ったときに「裏側がこうだからたぶんこういうことだよね」と想像できるようになる、少し世界の見え方が変わる時間を提供します。

88964b936e864ca7d326272eaa70fa9a?s=128

Kazuki Higashiguchi
PRO

March 28, 2022
Tweet

More Decks by Kazuki Higashiguchi

Other Decks in Technology

Transcript

  1. ブラウザ自動操作技術の深層へ 直接触れて学ぶ WebDriverと Chrome DevTools Protocol Kazuki Higashiguchi April 10,

    2022 @ PHPerKaigi 2022
  2. Agenda 1. WebDriver とは 2. PHP で WebDriver binding をスクラッチ実装する

    3. Chrome DevTools Protocol (CDP) とは 4. PHP で CDP binding をスクラッチ実装する
  3. About Me Kazuki Higashiguchi Backend Engineer of Autify AIを用いたソフトウェアテスト自動化プラットフォーム ID:

    @hgsgtk
  4. Autify Solution AIを用いたWeb/MobileアプリのE2Eテスト自動化サービス No codeで誰でも簡単 AIがメンテナンス デモリクエスト受付中 https://autify.com/ja/demo

  5. 01. WebDriverとは

  6. WebDriver ブラウザ*1 を操作したり観察できる遠隔制御インターフェース *1 厳密にいうと、”User agent” という表現が正確です。操作対象はウェブブラウザに限定されません。たとえば Appium は WebDriver

    protocol を使用してモバイルアプリを操作します。 例: - ウェブ文書内のDOM要素の検出・操作 - ブラウザ動作の制御
  7. 中立なインターフェース プログラミング言語とプラットフォームに中立なインターフェース WebDriver interface …etc …etc

  8. プログラムから見たWebDriver WebDriver HTTP request HTTP response JSON ベースの HTTP API*1、各プログラミング言語でHTTP

    Clientを実装 *1 WebDriver protocol では PHP 側を Local end 、WebDriver 側を Remote end と定義しています。
  9. ブラウザから見たWebDriver WebDriver interface *1 ChromeDriver SafariDriver geckodriver IEDriver OperaDriver ※2

    *1 W3C勧告 によって、それぞれのドライバーが実装しなければならない API が定義されています。 *2 モバイルアプリのテスト自動化フレームワークである Appium では iOS 用の XCUITest Driver など Appium 自身がメンテナ ンスする独自ドライバーを実装・提供しています。
  10. Selenium WebDriver*1 仕様を使って、ブラウザを自動操作する ための仕組み - Selenium Grid: 並列実行を実現するインフラ - Selenium

    IDE:ブラウザ操作を自動記録し再生できるツール - Language bindings:各言語でのAPI実装 - WebDriver *1 Selenium が使用するプロトコルは過去に使用されていた JSON Wire Protocol Specification と、現行の W3C specification の 2 種類があります。各 binding 実装の中身では、この2つの仕様それぞれに対応したコードがちらほら実装さ れていることが見れます。
  11. 02. PHP で WebDriver binding をスク ラッチ実装する

  12. PHPでWebDriver bindingを実装する JSON APIの仕様を読み解き ブラウザのライフサイクルを意識した APIクライアントを実装する

  13. 実装する自動化フロー ブラウザを開く ページ遷移 ボタンをクリック フォーム入力

  14. 実装した自動化コード * 今回の実装は https://github.com/hgsgtk/phpwd にて公開しています。

  15. デモンストレーション

  16. WebDriverを起動する ChromeDriverを使用する場合... ローカルで起動すると、 ポート 9515 に、 APIサーバーが立ち上がる*1 *1 本例では、同一ホストシステムで立ち上げた ChromeDriver

    を直接使用する構成をとっていますが、 Remote WebDriver や Selenium Server(Grid) を用いる別のホスト内で立ち上げた WebDriver を使用する構成もあります(参考: Selenium components)。
  17. ブラウザを開く ブラウザを開く ページ遷移 ボタンをクリック フォーム入力

  18. PHPで実装する 1. http://localhost:9515/session へ POST リクエスト*1を送信する 2. ChromeDriverがブラウザを開く 3. HTTPレスポンスが返却され

    Session Id が手に入る *1 W3C WebDriver プロトコルはこの一つの HTTP リクエストを Command と定義し、多くの Command 定義によって構成され ています。
  19. 開いたブラウザに対応するSession Id Session Element SessionID ElementID Session Id を指定してページ操作 -

    DOM要素を取得 - スクリーンショットを撮る - 前のページに戻る - 現在のURLを取得する - etc
  20. PHP 8.0 Constructor property promotion を使用した値クラス

  21. ページ遷移する ブラウザを開く ページ遷移 ボタンをクリック フォーム入力

  22. PHPで実装する /session/{sessionId}/url へPOSTリクエスト

  23. ボタンをクリック・フォーム入力 ブラウザを開く ページ遷移 ボタンをクリック フォーム入力

  24. 要素を取得する 1. 要素検索方法(LocatorStrategy) と検索値を用意 2. /session/{sessionId}/element へ POST リクエスト 3.

    HTTPレスポンスが返却され、 Element Id が手に入る
  25. PHP 8.1 Enum を使用した列挙型

  26. 取得した要素に対応するElement Id Session Element SessionID ElementID Element Id を指定して要素操作 -

    テキストの取得 - クリック - 入力 - etc
  27. ページ要素をクリック /session/{sessionId}/element/{elementId}/click へPOSTリクエスト

  28. フォームに入力する /session/{sessionId}/element/{elementId}/value へPOSTリクエスト

  29. 実装した自動化コード(再掲) * 今回の実装は https://github.com/hgsgtk/phpwd にて公開しています。

  30. 実装してみたくなったあなたへ、おすすめ資料集 - Seleniumの公式ドキュメントで概要 を理解する - テスト自動化プラットフォームのブロ グ(e.g. BrowserStack、SourceLab、Autify) WebDriverをもっと理解したい! 自分で実装してみたい!

    - WebDriver仕様のエンドポイント一 覧で出来ることを知る - Curlでリクエストを送ってみる - php-webdriverなどbinding実装を 読んでみる*1
  31. 03. Chrome DevTools Protocol とは

  32. Chrome DevTools Protocol (CDP) Chromium*1 ・Chrome・その他Blink*2 ベースのブラウザのデバッ グ用プロトコル *1 Chromium

    はオープンソースのブラウザプロジェクトです。 Microsoft Edge や Opera など多数のブラウザで利用されていま す。 *2 Blink は Chromium によって利用されているレンダリングエンジンです。 例: - ページ遷移やスクリーンショット取得等のブラウザ操作 - JavaScriptカバレッジ等のプロファイル - パフォーマンスメトリクスの収集
  33. Chrome DevTools Protocolの使用例 Chrome DevTools - Lighthouse ページのパフォーマンス・品質改善のため のツール -

    etc ブラウザオートメーションツール - Puppeteer - Playwright - Selenium 4 *1 - etc *1 Selenium 4 にて、 Chrome DevTools Protocol に直接アクセスできる API getDevTools() と executeCdpCommand() が導 入されました。
  34. プログラムから見たChrome DevTools Protocol HTTP request HTTP response WebSocketサーバー、各プログラミング言語でWebSocket clientを実装する API

    WebSocket connection
  35. ブラウザから見たChrome DevTools Protocol Chrome DevTools Protocol Remote protocol *1 *1

    FireFoxでは Remote Protocol という低レベルのデバッグインターフェースを提供しています。デバッガである Remote Debugging Protocol を補完する立ち位置で Chrome DevTools Protocol のサブセットを実装しています。 Chromium-base
  36. 04. PHP で CDP binding をスクラッチ実 装する

  37. PHPでCDP bindingを実装する WebSocketコネクション上で 定義されたプロトコルに沿って メッセージを送受信する WebSocketクライアントを実装する

  38. 実装する自動化フロー タブを開く ページを開く ネットワーク トラッキングを有効化 集計

  39. 実装した自動化コード * 今回の実装は https://github.com/hgsgtk/php-cdp にて公開しています。

  40. デモンストレーション

  41. リモートデバッグを有効にしてChromeを起動 –remote-debugging-port=9222 ポート 9222 に、APIサーバーが立ち上がる

  42. 実装する自動化フロー タブを開く ページを開く ネットワーク トラッキングを有効化 集計

  43. タブを開く 1. http://127.0.0.1:9222/json/new へGETリクエスト 2. 新しいタブが開かれる 3. HTTPレスポンスが返却される 4. targetIdとwebSocketDebuggerUrl

    が得られる
  44. targetIdとwebSocketDebuggerUrl 専用のWebSocket endpoint: /devtools/page/{targetId} 例:ws://127.0.0.1:9222/devtools/page/7938D87B3D0A3C4D1F0F1F0D5706D297

  45. 実装する自動化フロー タブを開く ページを開く ネットワーク トラッキングを有効化 集計

  46. WebSocket上でのコマンド送受信プロトコル JSON形式でリクエストとレスポンスを表現する JSON-RPC *1 リクエスト Members: id, method, params *1

    JSON-RPC は 1.0 と 2.0 の 2 つのバージョンがあり、2.0 ではリクエストの形式に id, method, param に加えて jsonrpc と いうメンバーが追加されています。 CDP のプロトコルは JSON-RPC 1.0 がベースとなっています。 レスポンス Members: id, result, (error)
  47. ネットワークトラッキングを有効化 WebSocketコネクションへ Network.enable コマンドを送信する

  48. WebSocket library in PHP リポジトリ Description ratchetphp/Ratchet 非同期のWebSocketサーバー Starred: 5.7K

    beyondcode/laravel-websoc kets Laravel用のWebSocketライブラリ Starred: 4.3K Textalk/websocket-php WebSocketクライアントとサーバー両方を提供 Starred: 691 現在も定期的なメンテナンスあり
  49. Textalk/websocket-phpを使用したWebSocketクライアント send() でメッセージを書き、 receive() でメッセージを読む

  50. 実装する自動化フロー タブを開く ページを開く ネットワーク トラッキングを有効化 集計

  51. ネットワークトラッキング有効化で得られる通知 Experimentalな機能を含めて、 30種類のEventが送られてくる

  52. 特定のイベントだけを購読したい 例:ブラウザから送信されたリクエストを確認したい Network.requestWillBeSent のみ購読するリスナーを登録する

  53. リスナーを登録しメッセージ受信時に処理する No port specified リスナーを登録する - 購読したい Method - コールバック(Callable)関数

  54. リスナーを登録しメッセージ受信時に処理する No port specified 特定の Method を受信すると、 コールバック関数を呼び出す 例:Network.responseReceivedExtraInfo

  55. 「HTTPレスポンスを受け取った」イベントだけを購読する Network.responseReceived のみ購読するリスナーを登録する

  56. PHP 8.1 : First class callable syntaxを用いたコールバック関数 CallableExpr(...) という記法 PHPの文法上直接コールできるあらゆる式で使える

    Callable から Closure*1 を生成する *1 Closure は無名関数を表すクラスです。
  57. 実装する自動化フロー タブを開く ページを開く ネットワーク トラッキングを有効化 集計

  58. ページを開く Page.navigate コマンドを送信

  59. 実装した自動化コード(再掲) * 今回の実装は https://github.com/hgsgtk/php-cdp にて公開しています。

  60. コラム: プロトコル定義に基づくPHPコードの自動生成 プロトコルAPIの定義ファイル*1 - Domain: Page・DOM・Networkなど - Types: 型定義 -

    Commands: Domain内で行える操作 - Events: 送られるイベント 例:browser_protocol.json *1 browser_protocol.pdl と js_protocol.pdl という2つの定義ファイルがあり、 ChromeDevTools/devtools-protocol では JSON バージョンも公開されていま す。
  61. コラム: プロトコル定義に基づくPHPコードの自動生成 jakubkulhan/chrome-devtools-protocol のアプローチ*1 js_protocol.json JSON JSON protocol.json JSON browser_protocol.json

    定義ファイルを一つにまとめ PHPコードを生成 クラスファイル群 nette/php-generator コード生成スク リプト *1 dotNet や Go 等他言語でも同様のコード生成アプローチが取られています。
  62. 実装してみたくなったあなたへ、おすすめ資料集 - CDPの公式ドキュメントで概要を理 解する - Chrome-remote-interfaceや Puppeteerを使ってCDPに触れる - Chrome DevTools

    の Protocol monitor で流れるCDP req/resを眺 める CDPをもっと理解したい! 自分で実装してみたい! - Getting startedを読んでプロトコ ルを理解する - Vanilla-protocol-viewerを活用し てコマンドを探す - jakubkulhan/chrome-devtools-pr otocolなど既存のPHP bindingを 読んでみる
  63. ご視聴ありがとうございました デモリクエスト受付中 https://autify.com/ja/demo