はじめに
みなさんはE2Eテストを行う時にはライブラリに何を使用していますでしょうか?
僕は普段Google謹製のPuppeteerを利用しているのですが、ちょっと前に話題になってから常に動向を気にしていたPlaywrightが最近バージョン1.0.0のメジャーリリースが行われたということもあって、これは実際に触ってみたい!と思い触ってみましたので、備忘録としてここに記そうと思います。
Playwrightとは
PlaywrightとはMicrosoftが提供しているChrome、Safari、Firefoxに対して、CLI上で実行できるNodeのライブラリです。
かなり簡単な記述で対象ページに対してテストを実施することができます。
後述するコードを見てもらえるとすぐわかるかもしれませんがPuppeteerを知っている人はほぼ同じなので読みやすいかもしれません。
もともとPuppeteerを開発していたGoogleの開発チームがMicrosoftに移動して作成したライブラリのようなので、非常に似ているのかもしれないです。
公式github: Playwright
公式ページ: https://playwright.dev/
Puppeteerとの違い
書きかたは先ほど記載した通り、ほとんどPuppeteerもPlaywrightも変わらないです。違う点としては実行可能なブラウザがPuppeteerと比べて多いのが特徴です。
最近Puppeteerのv2.1がリリースされたタイミングでChromeだけでなくFirefoxも実行できるようになりましたが、Playwrightはそれに加えてwebkitでの実行が可能なライブラリなので、対象ブラウザだけ見るとぱっと見上位互換感があります。
Installation
インストールするにはnpmが利用できる環境化で以下のコマンドを実行するたけです。
$ npm i playwright
使い方
簡単なテストコード
簡単なテストコードの例としてChrome、Firefox、Safariで使用しているブラウザがわかるサイトのスクリーンショットを撮るテストコードを記載します。
今回はこちらのページにアクセスして現在使用しているブラウザを確認してみようと思います。
constplaywright=require('playwright');(async()=>{for(constbrowserTypeof['chromium','firefox','webkit']){// ここのbrowserTypeを変えることで、対象のブラウザを変更することができます。constbrowser=awaitplaywright[browserType].launch();constcontext=awaitbrowser.newContext();constpage=awaitcontext.newPage();awaitpage.goto('https://yourbrowser.is/');awaitpage.screenshot({path:`example-${browserType}.png`});awaitbrowser.close();}})();
constbrowser=awaitplaywright[browserType].launch();
の部分で立ち上げるブラウザを決定しています。
constcontext=awaitbrowser.newContext();
上記newContextで引数に設定を渡すことでUA偽装などを行うことができます。
今回は特にないので、引数なしで実行しています。
constpage=awaitcontext.newPage();
上記部分で立ち上げたブラウザでタブを作成しているイメージです。
基本的にここで立ち上げたpageに対してページ遷移をさせたりなどの動作を実行していきます。
テスト実行方法
通常通り、$ node $(ファイル名)
で実行可能です。
$ node example.js
上記コマンドを実行すると、上記テストコードに記載された通りに実行され、スクリーンショットが同一リポジトリに保存されていると思います。
中身を改めてもらうと、example-chromium.png
ではchromeを使用していたり、example-firefox.png
ではfirefoxを使用しているのが確認できると思います。
Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.
ヘッドレスモードを解除したいとき
デフォルトでヘッドレスモードでのテスト実行がされますが、実際にブラウザが立ち上がって動作するのが見たい場合にはblowserをlaunchする際に以下のように{ headless: false}
を引数にわたして実行します。
constbrowser=awaitplaywright[browserType].launch({headless:false});
デバイスを変更したい時
playwrightではデバイスを変更してテストすることも可能です。
対象デバイスはこちらで確認することができます。
constplaywright=require('playwright');//playwrightのdevicesにhttps://github.com/microsoft/playwright/blob/master/src/deviceDescriptors.tsの任意のものを指定することで、デバイスを取得できる。constiphone11=playwright.devices['iPhone 11'];(async()=>{for(constbrowserTypeof['chromium','firefox','webkit']){constbrowser=awaitplaywright[browserType].launch();// newContextの引数にiphone11を渡してあげることで、デバイスを偽造できる。constcontext=awaitbrowser.newContext({...iphone11});constpage=awaitcontext.newPage();awaitpage.goto('https://yourbrowser.is/');awaitpage.screenshot({path:`example-${browserType}.png`,fullPage:true});awaitbrowser.close();}})();
デバイスの取得は以下のように取得することができます。
constiphone11=playwright.devices['iPhone 11'];
上記で取得したiphone11のオブジェクトをそのまま、newContextの引数として渡してあげることで、テストをiphone11で実施したのと同じ状態で動かすことができます。
constcontext=awaitbrowser.newContext({...iphone11});
このテストコードは一番最初に行なった現在のブラウザやOSを確認するページにアクセスしてスクリーンショットを取得するテストなので、画像を確認してもらえれば、デバイスがiOSになっていることを確認できるかと思います。
Image may be NSFW.
Clik here to view.
よく使うやつ
ページ遷移
// ページに移動awaitpage.goto('https:/example.com/');
form入力
テキストインプットはfillによって実施をできます。
対象selectorに対して、第二引数の文字列を入力します。
awaitpage.fill('input[name="q"]','query');
クリック
ボタンやリンクのセレクタを指定することでクリックできます。
awaitpage.click('input[name="btnK"]');
セレクタがレンダリングされるまで待たせる
テストケースの中で、入力→submit→結果をスクリーンショットみたいなテストを行うときに、submit→結果をスクリーンショットのところがsubmitしてすぐスクリーンショットを撮ってしまうため、遷移する前にスクリーンショットをしてしまうのでうまくテストできないことがあります。そういう場合に遷移後のページのセレクタをwaitForSelectorで設定することで、セレクタが現れるまで待たせ、ちょっとスクリーンショットのタイミングを遅らせることができます。
ページ遷移系が含まれる時はかなり使います。
// Wait for #search to appear in the DOM.awaitpage.waitForSelector('#result-stats',{state:'attached'});
domの選択
// page.$(セレクタ)awaitpage.$('#something_id');awaitpage.$('.something_cls');awaitpage.$('input[name="hoge"]');
domの選択(複数)
// page.$$(セレクタ)awaitpage.$$('.something_cls');awaitpage.$$('p');
要素の抽出
page.evaluateメソッドを使うことで通常のJavaScript記述で処理できます。
constresult=awaitpage.evaluate(()=>{constnl=document.querySelectorAll('p');returnnl;});
スクリーンショットを撮る
//スクリーンショットを撮るawaitpage.screenshot({path:`example.png`});//スクリーンショットをフルページで撮るawaitpage.screenshot({path:`example.png`,fullPage:true});
特定のリクエスト以外を無視する
page.routeとpage.continueとpage.abortを組み合わせて不必要なリクエストを無視させテストスピードを早めることができる。
例1)画像をどうにか排除
awaitpage.route('**/*.{png,jpg,jpeg}',route=>route.abort());awaitpage.route('**/*',route=>{returnroute.request().resourceType()==='image'?route.abort():route.continue();});//上の設定をした後でページ遷移awaitpage.goto('https://example.com');
例2)対象のURL以外は無視
awaitpage.route('**/*',route=>{if(route.url()==targetUrl)route.continue();elseroute.abort();});//上の設定をした後でページ遷移awaitpage.goto('https://example.com');
HTTP Authentication
constcontext=awaitbrowser.newContext({httpCredentials:{username:'hoge',password:'fugafuga',},});constpage=awaitcontext.newPage();awaitpage.goto('https://example.com');
まとめ
ほぼほぼPuppeteerと同様の記述ができるので簡単にテストコードを作成できる上かなり豊富なAPIを用意してくれているので、やりたいことはかなりやれるかなという印象でした。
複数のブラウザに対してテストしたい場面はかなりあると思うので、その時の手段の一つとして考えておきたいですね。
PuppeteerもPlaywrightもそれぞれ強みを活かしていくことになると思うので、それぞれの動向を確認しつつ、場面にあったライブラリを選択するのが良いと思います。
参考
公式github: Playwright
公式ページ: https://playwright.dev/