Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

Agenda 1. WebDriver とは 2. PHP で WebDriver binding をスクラッチ実装する 3. Chrome DevTools Protocol (CDP) とは 4. PHP で CDP binding をスクラッチ実装する

Slide 3

Slide 3 text

About Me Kazuki Higashiguchi Backend Engineer of Autify AIを用いたソフトウェアテスト自動化プラットフォーム ID: @hgsgtk

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

01. WebDriverとは

Slide 6

Slide 6 text

WebDriver ブラウザ*1 を操作したり観察できる遠隔制御インターフェース *1 厳密にいうと、”User agent” という表現が正確です。操作対象はウェブブラウザに限定されません。たとえば Appium は WebDriver protocol を使用してモバイルアプリを操作します。 例: - ウェブ文書内のDOM要素の検出・操作 - ブラウザ動作の制御

Slide 7

Slide 7 text

中立なインターフェース プログラミング言語とプラットフォームに中立なインターフェース WebDriver interface …etc …etc

Slide 8

Slide 8 text

プログラムから見たWebDriver WebDriver HTTP request HTTP response JSON ベースの HTTP API*1、各プログラミング言語でHTTP Clientを実装 *1 WebDriver protocol では PHP 側を Local end 、WebDriver 側を Remote end と定義しています。

Slide 9

Slide 9 text

ブラウザから見たWebDriver WebDriver interface *1 ChromeDriver SafariDriver geckodriver IEDriver OperaDriver ※2 *1 W3C勧告 によって、それぞれのドライバーが実装しなければならない API が定義されています。 *2 モバイルアプリのテスト自動化フレームワークである Appium では iOS 用の XCUITest Driver など Appium 自身がメンテナ ンスする独自ドライバーを実装・提供しています。

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

02. PHP で WebDriver binding をスク ラッチ実装する

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

デモンストレーション

Slide 16

Slide 16 text

WebDriverを起動する ChromeDriverを使用する場合... ローカルで起動すると、 ポート 9515 に、 APIサーバーが立ち上がる*1 *1 本例では、同一ホストシステムで立ち上げた ChromeDriver を直接使用する構成をとっていますが、 Remote WebDriver や Selenium Server(Grid) を用いる別のホスト内で立ち上げた WebDriver を使用する構成もあります(参考: Selenium components)。

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

PHPで実装する 1. http://localhost:9515/session へ POST リクエスト*1を送信する 2. ChromeDriverがブラウザを開く 3. HTTPレスポンスが返却され Session Id が手に入る *1 W3C WebDriver プロトコルはこの一つの HTTP リクエストを Command と定義し、多くの Command 定義によって構成され ています。

Slide 19

Slide 19 text

開いたブラウザに対応するSession Id Session Element SessionID ElementID Session Id を指定してページ操作 - DOM要素を取得 - スクリーンショットを撮る - 前のページに戻る - 現在のURLを取得する - etc

Slide 20

Slide 20 text

PHP 8.0 Constructor property promotion を使用した値クラス

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

要素を取得する 1. 要素検索方法(LocatorStrategy) と検索値を用意 2. /session/{sessionId}/element へ POST リクエスト 3. HTTPレスポンスが返却され、 Element Id が手に入る

Slide 25

Slide 25 text

PHP 8.1 Enum を使用した列挙型

Slide 26

Slide 26 text

取得した要素に対応するElement Id Session Element SessionID ElementID Element Id を指定して要素操作 - テキストの取得 - クリック - 入力 - etc

Slide 27

Slide 27 text

ページ要素をクリック /session/{sessionId}/element/{elementId}/click へPOSTリクエスト

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

実装してみたくなったあなたへ、おすすめ資料集 - Seleniumの公式ドキュメントで概要 を理解する - テスト自動化プラットフォームのブロ グ(e.g. BrowserStack、SourceLab、Autify) WebDriverをもっと理解したい! 自分で実装してみたい! - WebDriver仕様のエンドポイント一 覧で出来ることを知る - Curlでリクエストを送ってみる - php-webdriverなどbinding実装を 読んでみる*1

Slide 31

Slide 31 text

03. Chrome DevTools Protocol とは

Slide 32

Slide 32 text

Chrome DevTools Protocol (CDP) Chromium*1 ・Chrome・その他Blink*2 ベースのブラウザのデバッ グ用プロトコル *1 Chromium はオープンソースのブラウザプロジェクトです。 Microsoft Edge や Opera など多数のブラウザで利用されていま す。 *2 Blink は Chromium によって利用されているレンダリングエンジンです。 例: - ページ遷移やスクリーンショット取得等のブラウザ操作 - JavaScriptカバレッジ等のプロファイル - パフォーマンスメトリクスの収集

Slide 33

Slide 33 text

Chrome DevTools Protocolの使用例 Chrome DevTools - Lighthouse ページのパフォーマンス・品質改善のため のツール - etc ブラウザオートメーションツール - Puppeteer - Playwright - Selenium 4 *1 - etc *1 Selenium 4 にて、 Chrome DevTools Protocol に直接アクセスできる API getDevTools() と executeCdpCommand() が導 入されました。

Slide 34

Slide 34 text

プログラムから見たChrome DevTools Protocol HTTP request HTTP response WebSocketサーバー、各プログラミング言語でWebSocket clientを実装する API WebSocket connection

Slide 35

Slide 35 text

ブラウザから見たChrome DevTools Protocol Chrome DevTools Protocol Remote protocol *1 *1 FireFoxでは Remote Protocol という低レベルのデバッグインターフェースを提供しています。デバッガである Remote Debugging Protocol を補完する立ち位置で Chrome DevTools Protocol のサブセットを実装しています。 Chromium-base

Slide 36

Slide 36 text

04. PHP で CDP binding をスクラッチ実 装する

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

デモンストレーション

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

targetIdとwebSocketDebuggerUrl 専用のWebSocket endpoint: /devtools/page/{targetId} 例:ws://127.0.0.1:9222/devtools/page/7938D87B3D0A3C4D1F0F1F0D5706D297

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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)

Slide 47

Slide 47 text

ネットワークトラッキングを有効化 WebSocketコネクションへ Network.enable コマンドを送信する

Slide 48

Slide 48 text

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 現在も定期的なメンテナンスあり

Slide 49

Slide 49 text

Textalk/websocket-phpを使用したWebSocketクライアント send() でメッセージを書き、 receive() でメッセージを読む

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

PHP 8.1 : First class callable syntaxを用いたコールバック関数 CallableExpr(...) という記法 PHPの文法上直接コールできるあらゆる式で使える Callable から Closure*1 を生成する *1 Closure は無名関数を表すクラスです。

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

コラム: プロトコル定義に基づく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 バージョンも公開されていま す。

Slide 61

Slide 61 text

コラム: プロトコル定義に基づくPHPコードの自動生成 jakubkulhan/chrome-devtools-protocol のアプローチ*1 js_protocol.json JSON JSON protocol.json JSON browser_protocol.json 定義ファイルを一つにまとめ PHPコードを生成 クラスファイル群 nette/php-generator コード生成スク リプト *1 dotNet や Go 等他言語でも同様のコード生成アプローチが取られています。

Slide 62

Slide 62 text

実装してみたくなったあなたへ、おすすめ資料集 - 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を 読んでみる

Slide 63

Slide 63 text

ご視聴ありがとうございました デモリクエスト受付中 https://autify.com/ja/demo