PuPHPeteerとは

Puppeteerは、なんて発音するの?

Wikiには「パペッティア」と書いてあるけど、発音は「パペティア」に聞こえるわね

PuPHPeteerは、なんて発音するの?

パピィエイチペッティアかしら?

話すときは「ピー・ユー・ピー・エイチ・ピー・ティア」のほうがわかりやすいかもね
WebアプリケーションのE2Eテストフレームワークの一つに、Puppeteer(パペッティア)があります。Puppeteerはブラウザを起動し、ブラウザを操作してE2Eテストをします。
Puppeteerは、npmでインストールして、Node.jsで記述します。素でSelenium WebDriverを使うよりも導入が簡単なので、人気が高いようです。
PuPHPeteerは、PHPからPuppeteerを使うためのライブラリです。
npmとcomposerでインストールします。npmでPuPHPeteerをインストールすると、Puppeteerもインストールされます。続けて、composerでもPuPHPeteerをインストールします。
PuPHPeteerのAPIドキュメントはありませんので、puppeteerのAPIドキュメントを調べます。
PuPHPeteerで書いたE2Eテストのサンプルを見ていきましょう。初期化処理は省略します。
URLを指定して、表示します。
$page->goto('https://example.jp');
Code language: PHP (php)
リンクやボタン、ラジオボタン、チェックボックスをクリックします。
$page->click('#button');
Code language: PHP (php)
<input type="text">
や<textarea>
の入力欄に入力します。
$page->type('#username', 'taro');
Code language: PHP (php)
DOM要素の内容を取得します。$elがnullかどうかで、そのDOM要素があるかどうかを判断できます。
$el = $page->querySelector('.error-message');
if ($el !== null) {
$text = $el->getProperty('textContent')->jsonValue();
$text = ltrim(rtrim($text));
}
Code language: PHP (php)
DOM要素の指定は、CSSセレクターを指定します。DOM idがあれば確実です。
DOM idを指定していない場合、Google ChromeのDeveloper toolで、HTML要素を探して、右クリック>コピー>CSSセレクターでわかります。
このように、人間がブラウザで操作することを、コツコツとプログラムとして記述していきます。
そして、ブラウザ操作やアサーションを書いていくと、すぐに数百行のメソッドになってしまいます。
そこで、E2Eテストのデザインパターンとして、Page Object Modelが考え出されました。
E2Eテストツールの元祖であるSeleniumのサイトに、E2Eテストのデザインパターンとして、Page Object Modelが紹介されています。
インストール
まず、npmでPuPHPeteerをインストールします。
$ npm init
$ npm install @nesk/puphpeteer
Code language: Bash (bash)
次に、composerでPuPHPeteerをインストールします。
$ composer init
$ composer require nesk/puphpeteer
Code language: Bash (bash)
Puppeteerオプション
コンストラクタオプションは、PuPHPeteer独自のオプションです。APIドキュメント
<?php
$puppeteer = new Puppeteer(
[
'idle_timeout' => 600,
]
);
Code language: PHP (php)
idle_timeout: 長時間放置してもブラウザを閉じないようにする
例えば「1分間操作をしなかったら、メッセージを表示をすること」を検証したいとき、次のように sleep();
で待ちたいのですが、
$page->click('#foo');
sleep(61);
$el = $page->querySelector('#help-message');
$this->assertTrue(el !== null);
Code language: PHP (php)
デフォルトでは30秒間ブラウザ操作をしないと、例外をスローしてブラウザを閉じてしまいます。
そこで、Puppeteerのコンストラクタオプションに、
'idle_timeout' => 600,
を追加します。この例では、600秒、10分に設定しています。
launchオプション
$launchOptions = [
'executablePath' => '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'headless' => false,
'ignoreHTTPSErrors' => true,
'slowMo' => 50,
'args' => [
'--no-sandbox',
'--disable-setuid-sandbox',
"--window-size=1280,1024",
],
];
$puppeteer->launch($launchOptions);
Code language: PHP (php)
executablePath: ブラウザの実行パス
Puppeteerは、Chromiumをnode_modules下にダウンロードして、デフォルトのブラウザとしてChromiumを使います。
macOSnode_modules/puppeteer/.local-chromium/mac-818858/chrome-mac/Chromium.app
Ubuntu 18node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome
ところが、macOSで実行すると、PuPHPeteerがブラウザを起動するたびに、次のダイアログが表示されました。
アプリケーション"Chromium.app"へのネットワーク受信接続を許可しますか

Google Chrome.app?

似ているけど、Chromium.app よ
許可をクリックしても、また表示されます。
システム環境設定>セキュリティ>ファイヤーウォールの一覧にはChromium.appがあるので、許可されていると思うのですが...
Chromium.appが/Applications/下ではないからなのでしょうか。
解決方法がわからず、macOSの場合は、インストール済みのGoogle Chromeを使うことにしました。
'executablePath' => '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
次のコードは、macOSかどうかの判別ではなく、Chrome.appがあるかどうかで判別する例です。
$macosChromePath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
if (file_exists($macosChromePath)) {
$launchOptions['executablePath'] = $macosChromePath;
}
Code language: PHP (php)
headless: ブラウザの表示/非表示
デフォルトは、'headless' => true で、ブラウザを表示しません。
ブラウザを表示しないことには、E2Eテストを作成するのは難しいので、
'headless' => false,
を追加して、ブラウザを表示します。
環境変数や .env
(dotenv)の設定で切り替えられるようにしておくと便利です。
ignoreHTTPSErrors: 証明書エラーの無視
テスト用サーバの証明書期限が切れていたり、オレオレ証明書だったりすると、証明書エラーでページを開けません。
net::ERR_CERT_AUTHORITY_INVALID
launchオプションに、
'ignoreHTTPSErrors' => true,
を追加します。
slowMo: 操作速度の調整
デフォルトでは、いきおいよくタイプしたり、クリックして、次々に画面が変わっていきます。
いきおいがよすぎて、期待通りの操作をできないとき、clickやtypeの後に usleep(100000);
をいれて調整してもいいのですが、slowMoでも設定できます。
// usleepで調整するよりも $page->click('#fooButton'); usleep(100000);
slowMoを50〜100にすると、人間の操作感に近いそうです。
// slowMoで設定できるよ 'slowMo' => 50,

テストに通りやすくなったけど、時間もかかるようになるよ
args.--window-size: ブラウザ外枠のウィンドウサイズ
args
は、Chromium/Chromeの起動オプションです。
ブラウザ外枠のウィンドウサイズを設定します。
'args' => [ "--window-size=1280,1024",
これとは別に、ブラウザウィンドウ内の各タブ($pageが該当)のViewport設定もします。
$pages = $browser->pages();
$page = $pages[0];
//または
$page = $browser->newPage();
$size = [
'width' => 1280,
'height' => 1024,
];
$page->setViewport($size);
Code language: PHP (php)
widthもheightも0にすると、ウィンドウ内を最大に使います。
$size = [
'width' => 0,
'height' => 0,
];
$page->setViewport($size);
Code language: PHP (php)