業務でE2Eテストの導入を進めており、ブラウザ自動化のためのツールに関して調べる必要があったので備忘録的に書き残しておく。
自分のブラウザ自動化周りの知識といえばはるか昔に大学生のころインターンでSeleniumを用いたテストの自動化をやったくらいで止まっており、その頃の記憶からブラウザの自動化はあまり信頼のおけない挙動ばっかりする... というイメージがあった。
とはいえ、現在は当時よりも様々な選択肢があるらしいので、少しづつ過去の歴史に触れつつキャッチアップしてみる。
Selenium Remote Control (Selenium 1)
おそらく自分が大学生のときに触ったのはこのRCの世代だと思われる。
Selenium 1はブラウザ上での動作を実行するSelenium Coreとそれに対して操作処理を送信するRemote Controlから構成され、RCサーバがHTTPリクエストを用いてCoreに命令を送信し、Coreがそれを解釈しブラウザ上でJSを実行する形でブラウザの操作を行う。
Selenium WebDriver (Selenium 2)
それまでSelenium RCとして実現されていたリモート・コントロールのプロトコルを抽象化/標準化したものがW3C WebDriverであり、それを用いたのがこのSelenium WebDriver (Selenium 2)である。
基本的なメカニズムとしてはSelenium 1とほぼ変わらず、HTTPリクエストによってWebDriverプロトコルを実装したブラウザのドライバの操作が行われる。よって、1と2の違いはWebDriverという通信プロトコルを使うようになったくらいだと思われる。
WebDriverに関しては以下の記事が参考になった。ちょっと古いが、情報は多い。 vividcode.hatenablog.com
CypressとWebDriver
E2Eテスト界隈でそこそこ話題になったCypressはテスト実行においてWebDriverを使っていないため、テストの不安定性(flakiness)が低いとされている。
これは、Cypressのテストがブラウザ上で実行されるひとつのアプリケーションとして動作するため。
そもそもブラウザ自動化においてWebDriverとは抽象化されたブラウザとの通信プロトコルでしかない。
WebDriverを使っている限りブラウザとの通信には必ずHTTP通信が必要であり、そのオーバーヘッドがない分Cypressのテスト実行は安定する。もちろん、安定性と引き換えにブラウザ毎のWebDriver実装は使えないため、自前でテストの実行エンジンを実装するしかないわけだが、そこはとにかく実装で頑張っているんだろう*1と思われる。Cypressと同様のアーキテクチャを採用しているのはTestCafeというE2Eツールだが、こちらはIEもサポートしていて結構頑張っているっぽい。
なお、CypressはWebDriverとは異なりひとつのJavaScriptアプリケーションとして動くため、それ相応の制限を受ける。たとえばタブの操作やiframeに対する操作などがそれにあたり、これはCypressのアーキテクチャに由来する制限である。
Chrome Devtools Protocol (CDP)とChromeDriver
ChromeDriverというのはその名の通りChromeのためのWebDriver実装にあたるが、内部的にはWebDriverのプロトコルで送られてきた操作をChrome Devtools Protocol (CDP)へ変換することでWebDriverを実装している。
Chrome Devtools Protocolとはその名の通りChromiumやChromeなどBlinkベースのブラウザを外部から操作するためのAPIであり、WebDriverと異なりWebSocketで通信を行う。WebDriverと比べて取得できるデータや操作の種類が多くWebSocketで双方向的に通信ができるため、WebDriverよりも複雑な自動化操作を行えるようなった。詳しくはCDPのAPIドキュメントを見るといろいろ分かる。 chromedevtools.github.io
PuppeteerとPlaywright
ここ最近はブラウザ自動化といえばPuppeteerだ! みたいな記事を見かけることが多い気がするが、その理由はPuppeteerが内部的にWebDriverを使わずCDPを用いて直接ブラウザを操作するからだと思われる。ChromeDriverは テストツール --(WebDriver)--> ChromeDriver --(CDP)--> Chrome
という経路で操作を行うため諸々のオーバーヘッドが大きかったが、これがCDPだけになればHTTP通信分のオーバーヘッドがなくなり処理が安定化する。つまりWebDriverよりCDPをメインで操作する自動化ツールのほうがいい、ということになる。
PuppeteerとPlaywrightの違いは調べてみたがよくわからなかった。どこで見たか忘れたがPuppeteerの開発者がPlaywrightのほうに移動しているので、これからはPlaywrightのほうがいいぞみたいな記事がRedditにあった気がする。
WebDriver BiDi (BiDirectional)とSelenium 4
WebDriverのように標準化されたプロトコルでありながらもCDPのように自動化だけじゃなくブラウザの情報とかなんかいろいろ取れるようにしたいよね、というポストWebDriverのポジションとしてWebDriver BiDi (BiDirectional)とかいうやつが標準化されようとしているらしい。
まだDraftらしいがSelenium 4は先んじてこれに対応しようとしている。たぶんPlaywrightとかCypressも将来的にはCDPじゃなくてWebDriver BiDiを使うようになるんだろうな。分からんけど。
私見
結論、テスト自動化のツールに何を求めるかによって選び方が変わると思った。
以下の図の分類がめちゃくちゃ分かりやすい。 Browser Automation Tools Protocols - Webdriver vs CDP
基本的にはWebDriverは標準化されているだけでflakyテスト多くてつらいのでCDPを採用しているやつを選ぶべきで、ある程度制限があってもいいならCypressやTestCafeあたりを選ぶのが吉、という感じになるのかな。
上の記事によるとCypressに関してはV7からCDPサポートが入ったらしいので、もしかすると自分が先に書いているような制限は実はもうないのかもしれない。