◆ WebDriver (Selenium) 系と WebDriver を使わないもの

ふと思いつきでたまには E2E テストでもしてみようかと思いました
jasmine とか jest とか使ってやる単体テストじゃなくて 実際にブラウザで input に文字を入れたりボタン押したりして DOM がどうなってるかを確認したりするやつです

有名なのは WebDriver を使った Selenium 系です
しかし 個人的に Selenium 嫌いなので気が進みません
以前 Selenium を使わずに同じことをするというすごくレアなライブラリを見かけて期待していたのですが それも更新されず非推奨になりました
そのときに TestCafe に移行するといいよ みたいなことが書かれてましたが 結局 TestCafe もほぼ使わずいつか使うカテゴリに入って放置でした

それから何年か経ってるのでまた調べてみましたが そこまで種類は多くないようです
やはり WebDriver (Selenium) を使ったものが多く 新しいものが出ててもこれ系です

異なる仕組みを使ってるものをまとめるとこういう感じです


WebDriver (Selenium)

一番有名でこれを使ったテストライブラリが多いです

自動テストではブラウザで文字を入力したりボタンを押したりといったことを自動でする必要があります
これをユーザが直接操作せずに外部から自動で行うために WebDriver というものを使います
これは各ブラウザ共通の API でブラウザごとのドライバがブラウザを操作して自動でボタンを押したりということができます

この WebDriver と通信するのが Selenium です
ブラウザを操作したい各言語で Selenium のクライアントライブラリをインストールします
Selenium クライアントから Selenium サーバに命令を送って Selenium サーバが WebDriver と通信します
Node.js だったり Python だったりの言語は Selenium サーバに命令を送るライブラリがあればブラウザを操作できることになります

ただこの Selenium サーバは Java なので Java の準備が必要ですし 手間が多くあんまり気軽に使えません
もっと楽でシンプルに扱えるのがいいんですけどね
一応最近だと Selenium サーバなしで直接 WebDriver と通信するものもあるみたいなことを聞いたりしましたが 使ってないのでよくわかりません

外部からブラウザを操作するツールなので テスト専用というわけではないです
自動テストは利用方法のひとつですね

TestCafe

Selenium を使わないものとして(たぶん)有名なやつです
最初は独自に WebDriver と通信するものかなと思ってましたが WebDriver すら使わないものでした

公式サイトに説明がありますが URL-rewriting proxy というプロキシを使います
https://github.com/DevExpress/testcafe-hammerhead

ブラウザ → プロキシ → サーバ

という通信になっています
プロキシではサーバから受け取ったレスポンスの HTML や JavaScript のコードを書き換えます
テストをするためのスクリプトが追加されたりして 文字を入力したり ボタンを押したりといった操作はページ内の JavaScript で行われます

どんなページがテスト対象かわからないのに ページ内の処理と同じ空間の JavaScript レベルでやるのは変な問題起きないのか不安もありますが 実際にさまざまなページで使われてるわけですし そこはうまくいくように考えられてるんでしょう
そこで問題がないなら ページ内 JavaScript だからこそできる WebDriver にはできないこともあるはずですしメリットもあります

JavaScript でやる以上 event オブジェクトの isTrusted が false になるのは避けられないと思って試してみたら false でした
ユーザの操作で発生した event の場合は true になります
WebDriver の場合は試していませんが ユーザ操作と同じように外部からなら true になるのかもしれません
それか ユーザ操作ではないので意図的に false にしたりしてるのでしょうか?
false になるからと言って 実際にこのプロパティを使うことはまずないと思うので 問題にはならないと思います

JavaScript で操作するのだと closed な ShadowDOM はアクセスできないなぁとか思いましたが この辺は WebDriver だろうとセレクタで要素を取得するならどちらも一緒かと思います
どのツールを使うにしても WebComponents 関連はやりづらそうな印象です


TestCafe では ブラウザがアクセスする URL は起動時が

http://192.168.1.107:63466/browser/connect/ujuBjiP

テスト開始時が

http://192.168.1.107:63466/IwgwPYRGq/http://fedora-server/test08/10.html

でした

テスト対象のサーバへアクセスするのはプロキシで ブラウザが開くのはプロキシのページなので URL はプロキシのものになります
localhost の IP アドレスでポートと識別子はランダムなものになってます
テスト中の URL には「http://fedora-server/test08/10.html」のようにテスト対象のページのアドレスがそのまま含まれるので開いてるページはわかりやすいです

これらのページ自体はテストを実行すると勝手に開かれるので気にしなくもいいやつです

Cypress

TestCafe とよく比較されるツールです
名前的にもしかして某エージェント系?と思いました (Cysharp みたいな会社も作ってましたし) が 特に関係ないアメリカの会社でした

インストールすると cypress フォルダができて色々入ってます
integration フォルダがテストコードを入れるところで examples フォルダに例が用意されています

Cypress を起動すると electron アプリが起動してテストファイルのリストが見れます
実体は integration フォルダ内のファイルです
integration フォルダに test1.js を追加するとリストにも追加されます

画面からテストしたい項目をクリックするとブラウザが起動してテスト画面が表示されます
ブラウザは Chrome 以外も選べます

TestCafe ではテスト画面の表示はテスト対象のページそのものでしたが Cypress では専用のテスト画面があります
ページの左側に開いたテストファイルのテスト項目一覧があって 右側にテスト対象のページが表示されます
devtools で見てみると テスト対象のページは iframe で表示していて iframe の src は直接テスト対象のサーバの URL でした
TestCafe のようにプロキシで書き換えはしていないようです

どうやって外部から操作してるのか調べてみると Cypress から起動した Chrome には Cypress の拡張機能が入っていました
拡張機能の content script 機能で iframe のページに JavaScript を追加しています
TestCafe のプロキシで HTML や JavaScript 書き換える方法より安心感がある気はします
拡張機能がインストールされるのはテスト用に開かれた Chrome ウィンドウだけで普段使いの方には影響なしです

テスト時にブラウザで開くページの URL は

http://localhost:64266/__/#/tests/integration\test1.js

でした
Windows だからか \ 区切りになってます

Puppeteer

Chrome を外部から操作するライブラリです
WebDriver ではなく Devtools Protocol を使います
デフォルトはヘッドレスで画面が表示されません
ページのクロールや PDF 作成とかに使えます
Chrome を使うなら WebDriver よりこっちの方が扱いやすくてよく使われてると思います

できることが WebDriver と被りますが プロジェクトの README の FAQ にも書かれていますが WebDriver を置き換えるものではないです
WebDriver はブラウザ間で共通の API で どのブラウザでも使えます
それに対してこれは Chrome 専用です
その分 WebDriver よりも使いやすさや高機能・信頼性などを追求しています

Chrome 以外のブラウザでもテストが必要なら複数のブラウザを扱える WebDriver などを使うほうがいいです
しかし Chrome だけでいいなら Puppeteer を使えばいいと思います
一応実験的に Firefox も対応していたはずですし 安定してるなら使えるケースが増えるかもしれません
そうなると Safari さえなければと思わざるをえないです
変にシェアが多いところまで第二の IE だからタチが悪いです
逆に Firefox はシェアが減りすぎて対応ブラウザに含まれないことが増えてるとか
リリース直後の最新機能とか使ってなければ Chrome で動くならほぼ動くので問題なさそうですけど

これも WebDriver と同じくテスト専用というわけではないので テストに使うなら内部で Puppeteer を使ったテストツールを使ったほうが便利です

まとめ

TestCafe や Cypress はブラウザを操作する仕組みとテストのためのツールの両方が入っていて これだけあればテストが行えるものです
Node.js ツールなのでテストの処理は JavaScript で書くことになります

WebDriver や Puppeteer はブラウザを操作する仕組みだけで テストのためのツールは含まれません
これらを内部で使うテストツールが色々あるので基本的にそれらを使います

Puppeteer は Node.js なので JavaScript で書くことになりますが Chrome を操作するための CDP は他の多くの言語で使えます
なので Node.js 以外の言語でも Puppeteer のようなライブラリはあると思います
それを内部で使うテストツールまであるかはわかりませんが あれば Node.js 以外の言語でテスト処理を書くことは可能です

WebDriver の Selenium クライアントも多くの言語で対応しています
Node.js 以外の言語で E2E テストの処理を書くならこれになると思います