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

自分だけの小さなSelenium「Olenium」を作って始める、ブラウザ自動化技術の理論と実践

ikuma-t
October 22, 2022

 自分だけの小さなSelenium「Olenium」を作って始める、ブラウザ自動化技術の理論と実践

Kaigi on Rails 2022の登壇資料です!

https://kaigionrails.org/2022/talks/ikumatdkr/

ikuma-t

October 22, 2022
Tweet

More Decks by ikuma-t

Other Decks in Programming

Transcript

  1. Olenium
    じぶんだけの小さなSelenium
    を作って始める
    ブラウザ自動化技術の と
    理論 実践
    Olenium
    @ikuma-t

    View full-size slide

  2. ikuma-t
    ・ で勤務。いわゆる です。
    株式会社エンペイ newbie
    ・最近 と名乗り始めました
    フロントエンドエンジニア
    ・未経験から で学んでプログラマーへ
    FJORD BOOT CAMP
    kaigi on rails 2022
    アニメ好き / ツール好き / パン好きな人

    View full-size slide

  3. kaigi on rails 2022
    ブラウザ自動化
    テーマ

    View full-size slide

  4. わたしとブラウザ自動化
    kaigi on rails 2022
    ・SIerでのExcelペタペタ → 自動テストに感動
    ・サンプルデータ「学校法人SQLインジェクション」の作成
    ・Cypressで自作サービスのフロントエンドのテスト

    View full-size slide

  5. kaigi on rails 2022
    なんとなく動いているけど、

    どうやって

    ブラウザを操作しているの?

    View full-size slide

  6. kaigi on rails 2022
    capybaraのfill_in!!

    View full-size slide

  7. kaigi on rails 2022
    capybaraのfill_in!!
    途中に

    なんかある

    View full-size slide

  8. kaigi on rails 2022
    capybaraのfill_in!!
    途中に

    なんかある
    ここを知りたい

    View full-size slide

  9. ブラウザ自動化の や とその を理解し、

    ブラウザ自動化を用いる際の を高める
    登場人物 用語 関係性
    解像度
    kaigi on rails 2022
    「発表のゴール」

    View full-size slide

  10. Olenium
    2. Olenium
    ・WebDriverベース

    ・HTTP

    ・Seleniumに名前が似てる
    Olaywright
    3. Olaywright
    ・CDPベース

    ・WebSocket

    ・Playwrightに名前が似てる
    kaigi on rails 2022
    xv ざっくりとした全体像
    仕様を参考に自分でブラウザを自動操作してみよう

    View full-size slide

  11. kaigi on rails 2022
    ブラウザ自動化の

    全体図
    Chapter 1

    View full-size slide

  12. わりとよく聞くブラウザ自動化/E2Eテストツール
    kaigi on rails 2022
    Selenium Playwright Puppeteer Cypress
    (Microsoft)
    Puppeteer作ってた人が移動
    (Google)

    View full-size slide

  13. ブラウザとの距離が近くなるほど、大きな力を手に入れるが...
    Devtools

    Protocol
    WebDriver 遠い






    ○ ○

    近い
    もはや

    ブラウザ
    ブラウザとの

    対話方法 ツール例 ブラウザとの

    距離 テストの安定性 クロスブラウザ 使用可能言語
    JavaScript

    in Browser

    View full-size slide

  14. ブラウザとの距離が近くなるほど、大きな力を手に入れるが...
    Devtools

    Protocol
    WebDriver 遠い






    ○ ○

    近い
    もはや

    ブラウザ
    ブラウザとの

    対話方法 ツール例 ブラウザとの

    距離 テストの安定性 クロスブラウザ 使用可能言語
    JavaScript

    in Browser
    JSしか使えない
    馬力は低いけど

    多様な環境で動く
    馬力は低いけど

    多様な環境で動く
    環境に依存するけど

    その分高馬力
    環境に依存するけど

    その分高馬力

    View full-size slide

  15. WebDriver
    kaigi on rails 2022
    使用例:Selenium
    ローカルエンド リモートエンド UserAgent
    HTTPリクエスト
    HTTPレスポンス
    WebDriver
    ChromeDriver

    geckodriverなど
    各プログラミング言語のための

    インターフェース
    Google Chrome

    Firefoxなど
    Command
    ・W3C勧告で最低限実装すべきコマンド(エンドポイント)が定義されている。

    ・リモートエンドが仲介に立つことで、幅広い環境に対応している。
    規定のエンドポイントを叩くと

    Command実行

    View full-size slide

  16. Devtools Protocol
    kaigi on rails 2022
    使用例:Playwright、Puppeteer
    クライアント
    ターゲット ターゲット
    UserAgent
    WebSocket
    実行できるMethodはProtocolで定義
    各プログラミング言語のための

    インターフェース
    操作対象のブラウザ、タブ、

    サービスワーカーなど
    Google Chrome

    Firefoxなど
    ・各ブラウザごとにDevtools Protocolが提供されている。Chrome版がCDP。

    ・SeleniumやCypressでも本流ではないが部分的に使用されている。

    View full-size slide

  17. JavaScript in Browser
    kaigi on rails 2022
    使用例:Cypress
    Proxy
    OS
    WEB
    Node.js
    WebSocket
    HTTP
    外部とのやりとりはここを通す
    これ自体は

    Vue.jsアプリ
    (DesktopAppもある)
    【iframe1】

    テスト対象のアプリ
    【iframe2】

    テストコード
    document.domainを

    いじることでSOPを回避

    View full-size slide

  18. Olenium
    2. Olenium
    ・WebDriverベース

    ・HTTP

    ・Seleniumに名前が似てる
    Olaywright
    3. Olaywright
    ・CDPベース

    ・WebSocket

    ・Playwrightに名前が似てる
    kaigi on rails 2022
    xv ざっくりとした全体像
    仕様を参考に自分でブラウザを自動操作してみよう

    View full-size slide

  19. kaigi on rails 2022
    Chapter 2
    WebDriver Olenium

    View full-size slide

  20. WebDriverという仕様
    kaigi on rails 2022
    もともとSeleniumの機能の1つ 2018年6月にW3C勧告として発表

    Seleniumが元であると明記

    View full-size slide

  21. WebDriver
    kaigi on rails 2022
    ローカルエンド リモートエンド UserAgent
    HTTPリクエスト
    HTTPレスポンス
    WebDriver
    ChromeDriver

    geckodriverなど
    各プログラミング言語のための

    インターフェース
    Google Chrome

    Firefoxなど
    Command
    規定のエンドポイントを叩くと

    Command実行
    いまから作っていくところ

    View full-size slide

  22. エンドポイント
    kaigi on rails 2022
    3) リモートエンドのエンドポイントを叩くと 2. 対応するコマンドが実行され、ブラウザが動く

    View full-size slide

  23. kaigi on rails 2022
    ・テストの実行環境を指定する

      ブラウザ名やタイムアウトを指定できる
    ・JSONオブジェクト形式で渡す
    ・空でもいいが、指定しないとエラー

      リクエストになる
    https://www.w3.org/TR/webdriver2/#capabilities
    Capabilities

    View full-size slide

  24. curlコマンドでエンドポイントを叩いてみる
    kaigi on rails 2022
    ChromeDriverを実行(localhost:9515で通知を待ち受ける)
    POST /session

    View full-size slide

  25. kaigi on rails 2022
    ・ChromeDriverが localhost:9515 で起動している

    ・/session にPOSTする
    Capabilitiesの指定
    ・sessionIdがかえってきている

    View full-size slide

  26. Session
    kaigi on rails 2022
    ほとんどのエンドポイントは「session_id」が必要

    View full-size slide

  27. Session
    kaigi on rails 2022
    ・セッションにはブラウジング・コンテキストが

     あり、これを操作していく
    ・現在操作対象となっているのが「カレント・

     ブラウジング・コンテキスト」
    ・操作対象を切り替えるには、ブラウジング・

     コンテキストを切り替えるエンドポイントを叩く
    文書が表示されるタブやウィンドウのこと。HTML Living Standardで定義

    View full-size slide

  28. 8章以降はセクションごとにエンドポイントの説明
    kaigi on rails 2022
    今話してたのが

    8. Sessions

    View full-size slide

  29. kaigi on rails 2022
    Rubyで実装

    View full-size slide

  30. Olenium
    kaigi on rails 2022
    ・Rubyで作るWebDriverの

     ローカルエンド
    ・俺のSelenium(名前だけ)

    View full-size slide

  31. Olenium::Client
    kaigi on rails 2022
    ・接続のための初期設定を行う
    ・sessionが不要なエンドポイントも

     ここに実装
    ・Olenium::Connectionは

     Net::HTTPの簡易ラッパー
    session_idが必要なエンドポイント用

    次ページ参照

    View full-size slide

  32. Olenium::Session
    kaigi on rails 2022
    資料の掲載スペースが足りないだけで

    エンドレスメソッドである意味はまったくない
    ・session_idが必要なエンドポイント群
    ・一部スクショを取るエンドポイントだけ

     分割するほどでもないのでそのまま
    ・WebDriverのセクション単位で

     別クラスとして抽出している。

     中身としては愚直にHTTPリクエストを

     しているだけです

    View full-size slide

  33. Oleniumで遊ぶ
    kaigi on rails 2022

    View full-size slide

  34. kaigi on rails 2022
    お分かりいただけただろうか...
    Olenium
    引用元:https://www.oreocookie.jp/

    View full-size slide

  35. Olenium
    2. Olenium
    ・WebDriverベース

    ・HTTP

    ・Seleniumに名前が似てる
    Olaywright
    3. Olaywright
    ・CDPベース

    ・WebSocket

    ・Playwrightに名前が似てる
    kaigi on rails 2022
    xv ざっくりとした全体像
    仕様を参考に自分でブラウザを自動操作してみよう

    View full-size slide

  36. kaigi on rails 2022
    Chrome

    Devtools

    Protocol
    Chapter 3
    Olaywright

    View full-size slide

  37. Chrome Devtools Protocolの仕様
    kaigi on rails 2022
    【各Domainごとの詳細】

    ・赤: Experimental

    ・黄: Deprecated
    プロトコルについての説明
    【バージョンごとの詳細】

    バージョンによって使用できるDomain

    や機能が異なる
    https://chromedevtools.github.io/devtools-protocol/

    View full-size slide

  38. Chrome Devtools Protocol
    kaigi on rails 2022
    使用例:Playwright、Puppeteer
    クライアント ターゲット ターゲット
    UserAgent
    WebSocket
    実行できるMethodはProtocolで定義
    各プログラミング言語のための

    インターフェース
    操作対象のブラウザ、タブ、

    サービスワーカーなど
    いまから作っていくところ

    View full-size slide

  39. kaigi on rails 2022
    WebSocket
    ・URLスキーマとしてws://または暗号化されたwss://を用いる
    ・サーバとクライアントが接続を確立した後は、

      そのコネクション上で専用のプロトコルを用いて通信を行う
    ・クライアントとサーバ間で双方向通信するためのプロトコル
    ・RailsだとActionCableで使用
    https://www.rfc-editor.org/rfc/rfc6455

    View full-size slide

  40. WebSocketでChromeと接続する
    kaigi on rails 2022
    WebSocketを扱えるツール(例:Postman)
    Chromeを起動

    View full-size slide

  41. 【再掲】Chrome Devtools Protocol
    kaigi on rails 2022
    使用例:Playwright、Puppeteer
    クライアント ターゲット ターゲット
    UserAgent
    WebSocket
    実行できるMethodはProtocolで定義
    各プログラミング言語のための

    インターフェース
    操作対象のブラウザ、タブ、

    サービスワーカーなど
    いまから作っていくところ

    View full-size slide

  42. JSON-RPC
    kaigi on rails 2022
    RPC(Remote Procedure Call)の1つ
    https://www.jsonrpc.org/specification
    同じIDで紐付け
    同じIDで紐付け

    View full-size slide

  43. kaigi on rails 2022
    メッセージを構成する①
    各Domainごとに

    Methodが定義されている
    紐付けのためのIDを指定
    の形式で指定
    定義されているMethodを参照して、methodの値を指定

    View full-size slide

  44. kaigi on rails 2022
    メッセージを構成する②
    各Methodごとの説明
    引数の一覧(optionalは任意引数)
    (少なくとも必須の)引数を設定

    View full-size slide

  45. メッセージを投げてみる①
    kaigi on rails 2022
    PostmanでTarget.createTarget
    新規タブで指定したURLが開く

    (計画通り)

    View full-size slide

  46. メッセージを投げてみる②
    kaigi on rails 2022
    PostmanでPage.navigate
    指定したURLに移動してほしいけど


    変わってない
    エラー「‘Page.navigate’ wasn’t found 」

    View full-size slide

  47. 【再掲】Chrome Devtools Protocol
    kaigi on rails 2022
    使用例:Playwright、Puppeteer
    クライアント ターゲット ターゲット
    UserAgent
    WebSocket
    実行できるMethodはProtocolで定義
    各プログラミング言語のための

    インターフェース
    操作対象のブラウザ、タブ、

    サービスワーカーなど
    いまから作っていくところ

    View full-size slide

  48. 【再掲】Chrome Devtools Protocol
    kaigi on rails 2022
    使用例:Playwright、Puppeteer
    クライアント ターゲット ターゲット
    UserAgent
    WebSocket
    実行できるMethodはProtocolで定義
    各プログラミング言語のための

    インターフェース
    操作対象のブラウザ、タブ、

    サービスワーカーなど
    いまから作っていくところ

    View full-size slide

  49. kaigi on rails 2022
    [Contributing to Chrome DevTools Protocol]

    (https://docs.google.com/document/d/1c-COD2kaK__

    5iMM5SEx-PzNA7HFmgttcYfOHHX0HaOM/edit#)
    ・デバッグ可能な実体。ページやブラウザ、

      サービスワーカー
    ・ターゲットには次の2つがある

      ・トップレベル(ex: ページ)

      ・ネストされた(ex: ウェブワーカー)
    ・ターゲット別にWebSocketのURLが

      振られている
    ターゲット

    View full-size slide

  50. メッセージを投げてみる②
    kaigi on rails 2022
    PostmanでPage.navigate
    指定したURLに移動してほしいけど


    変わってない
    エラー「‘Page.navigate’ wasn’t found 」

    View full-size slide

  51. 【再掲】メッセージを投げてみる②
    kaigi on rails 2022
    PostmanでPage.navigate
    指定したURLに移動してほしいけど


    変わってない
    エラー「‘Page.navigate’ wasn’t found 」
    ・ターゲットがbrowserだったので、エラーになっていた

     (ページ遷移ができるのはブラウザではなくて、ページ=タブなので)
    ・なので、このWebSocketの接続先(ターゲット)をページにすれば期待通りに動く

    View full-size slide

  52. ターゲットを取得するには
    kaigi on rails 2022
    https://chromedevtools.github.io/devtools-protocol/
    remote-debugging-portを指定すると、いくつかのエンドポイント(HTTP)が有効になる
    このURLでWebSocket接続をする。URLは`devtools/{target_type}/targetId`の形式

    View full-size slide

  53. メッセージを投げてみる③
    kaigi on rails 2022
    PostmanでPage.navigate
    無事ページ遷移できた!

    View full-size slide

  54. kaigi on rails 2022
    Rubyで実装

    View full-size slide

  55. Olaywright
    kaigi on rails 2022
    ・WebSocket接続には【Gem】

     websocket-client-simpleを使用
    ・大人の事情でirbで動かす前提

     (普通にやっても動きはするけど)
    ・俺のPlaywright(名前だけ)

    View full-size slide

  56. Olaywright:初期設定
    kaigi on rails 2022
    Wc GET /json/list でターゲット一覧を取3
    2c pageを接続対象に指定
    3. WebSocket接続

    View full-size slide

  57. 公開されているプロトコル定義を使用する
    kaigi on rails 2022
    browser_protocol
    2フォーマットで公開されている 各Domainの情報がJSONで返ってくる
    js_protocol
    PDL or JSON PDLはCDPを記述するために

    作られたフォーマット

    (発音:ˈpo͞
    odl")
    GET /json/protocol

    View full-size slide

  58. 例: chromedp(Go言語実装)
    kaigi on rails 2022
    ユーザー
    browser_protocol
    js_protocol
    Renée French
    PDL or JSON chromedp/pdlgen
    chromedp/

    cdproto
    chromedp/

    chromedp
    自動生成
    【罠】エラーなく動作する最新のブランチ名は、「main」ではなく「old」

    View full-size slide

  59. 例: chromedp(Go言語実装)
    kaigi on rails 2022
    ユーザー
    browser_protocol
    js_protocol
    Renée French
    PDL or JSON chromedp/pdlgen
    chromedp/

    cdproto
    chromedp/

    chromedp
    自動生成
    【罠】エラーなく動作する最新のブランチ名は、「main」ではなく「old」
    Olaywrightもこんな感じで

    動的にプロトコルをパースして

    低レベルで呼び出せるようにした

    View full-size slide

  60. Olaywrightで遊ぶ
    kaigi on rails 2022

    View full-size slide

  61. Olenium
    2. Olenium
    ・WebDriverベース

    ・HTTP

    ・Seleniumに名前が似てる
    Olaywright
    3. Olaywright
    ・CDPベース

    ・WebSocket

    ・Playwrightに名前が似てる
    kaigi on rails 2022
    xv ざっくりとした全体像
    仕様を参考に自分でブラウザを自動操作してみよう

    View full-size slide

  62. kaigi on rails 2022
    まとめ
    Chapter 4

    View full-size slide

  63. kaigi on rails 2022























    I


    途中になんかある

    View full-size slide

  64. kaigi on rails 2022























    I


    途中になんかある
    リモートエンド


    I










    HTTPリクエスト
    HTTPレスポンス
    Command
    WebDriver 規定のエンドポイントを叩くと

    Command実行

    View full-size slide

  65. kaigi on rails 2022























    I


    リモートエンド
    HTTPリクエスト











    HTTPレスポンス
    Command
    WebDriver
    Devtools Protocol
    規定のエンドポイントを叩くと

    Command実行
    JSON RPC via WebSocket
    実行できるMethodはProtocolで定義


    I










    View full-size slide

  66. kaigi on rails 2022























    I


    リモートエンド
    HTTPリクエスト











    HTTPレスポンス
    Command
    WebDriver
    Devtools Protocol
    規定のエンドポイントを叩くと

    Command実行
    JSON RPC via WebSocket
    実行できるMethodはProtocolで定義


    I










    iframe

    View full-size slide

  67. ‘‘
    ’’
    kaigi on rails 2022
    r7kamura
    [個人サイトについて](https://r7kamura.com/articles/2020-09-21-personal-website)
    多くの人にとって、ウェブの技術は魔法だ。

    少し指を動かすだけで、世界中の人に自分の声を届けられる。

    しかし自分にとって、ウェブの技術はもはや魔法ではない。

    知ってしまった以上、

    使いこなしたいと思うのが人の性というもの。

    View full-size slide

  68. kaigi on rails 2022























    I


    リモートエンド
    HTTPリクエスト











    HTTPレスポンス
    Command
    WebDriver
    Devtools Protocol
    規定のエンドポイントを叩くと

    Command実行
    JSON RPC via WebSocket
    実行できるMethodはProtocolで定義


    I










    iframe
    RailsのE2Eで馴染みのあるSelenium

    View full-size slide

  69. kaigi on rails 2022























    I


    リモートエンド
    HTTPリクエスト











    HTTPレスポンス
    Command
    WebDriver
    Devtools Protocol
    規定のエンドポイントを叩くと

    Command実行
    JSON RPC via WebSocket
    実行できるMethodはProtocolで定義


    I










    iframe
    Railsで学ぶWebの基礎
    RailsのE2Eで馴染みのあるSelenium

    View full-size slide

  70. kaigi on rails 2022























    I


    リモートエンド
    HTTPリクエスト











    HTTPレスポンス
    Command
    WebDriver
    Devtools Protocol
    規定のエンドポイントを叩くと

    Command実行
    JSON RPC via WebSocket
    実行できるMethodはProtocolで定義


    I










    iframe
    Railsで学ぶWebの基礎
    別プロトコルだけど、指定の形式でリクエストするのは同じ
    RailsのE2Eで馴染みのあるSelenium

    View full-size slide

  71. kaigi on rails 2022























    I


    リモートエンド
    HTTPリクエスト











    HTTPレスポンス
    Command
    WebDriver
    Devtools Protocol
    規定のエンドポイントを叩くと

    Command実行
    JSON RPC via WebSocket
    実行できるMethodはProtocolで定義


    I










    iframe
    Railsで学ぶWebの基礎
    別プロトコルだけど、指定の形式でリクエストするのは同じ
    他言語実装を

    参考にしてみる
    RailsのE2Eで馴染みのあるSelenium

    View full-size slide

  72. kaigi on rails 2022























    I


    リモートエンド
    HTTPリクエスト











    HTTPレスポンス
    Command
    WebDriver
    Devtools Protocol
    規定のエンドポイントを叩くと

    Command実行
    JSON RPC via WebSocket
    実行できるMethodはProtocolで定義


    I










    iframe
    Railsで学ぶWebの基礎
    別プロトコルだけど、指定の形式でリクエストするのは同じ
    他言語実装を

    参考にしてみる
    RailsのE2Eで馴染みのあるSelenium
    With Ruby

    View full-size slide

  73. kaigi on rails 2022
    With
    With
    Ruby

    Rails

    View full-size slide

  74. kaigi on rails 2022
    PR
    Extra Chapter

    View full-size slide

  75. kaigi on rails 2022
    やさしいフィンテックを。
    テクノロジーの力で、 新しいお金の流れをつくる。

    View full-size slide

  76. kaigi on rails 2022
    ぜひお話ししましょう!

    View full-size slide

  77. kaigi on rails 2022
    ありがとうございました!

    View full-size slide

  78. 参考
    kaigi on rails 2022
    ・WebDriver - W3C: https://www.w3.org/TR/webdriver/

    ・Chrome Devtools Protocol: https://chromedevtools.github.io/devtools-protocol/

    ・Cypress: https://www.cypress.io/

    ・Contributing to Chrome DevTools Protocol: https://onl.la/JEzM2cp

    ・getting-started-with-cdp: https://onl.la/kfLHLxE

    ・pdlgen: https://github.com/chromedp/pdlgen

    ・chrome-remote-interface: https://github.com/cyrus-and/chrome-remote-interface

    ・ferrum: https://github.com/rubycdp/ferrum

    ・Cypress vs Other Test Runners: https://onl.la/cNnSNsc

    View full-size slide