【メモ】Docker+Laravel+Duskでブラウザテスト

検索すれば情報はたくさんあるんですけど、トラップが多かったのでメモ代わりに






バージョン

  • Laravel 6.20.44
  • PHP 7.2.34
  • laravel/dusk 6.25.2


諸事情により少々古い環境ですが、基本的には最新版でも変わらないだろうと思います。また、僕のDocker環境は以下のような特徴もあります。


  • nginx で proxy サーバを立てている
  • オレオレ証明書で https 接続
  • コンテナごとにドメインを割り当て



LaravelにおけるブラウザテストはDuskで

Duskよりこっちの方がいいみたいな話もちらほら聞いたんですけど、実はブラウザテストにはあんまり詳しくないのでとうりあえずはドキュメントに載っている「Dusk」を使ってみることにしました。ドキュメントだとこの辺。


Laravel Dusk(ダースク:夕暮れ)は、利用が簡単なブラウザの自動操作/テストAPIを提供します。デフォルトのDuskは皆さんのマシンへ、JDKやSeleniumのインストールを求めません。代わりにDuskはスタンドアローンのChromeDriverを使用します。しかし、好みのSeleniumコンパチドライバも自由に使用することもできます。

Laravel Dusk 6.x Laravel


ドキュメントだとぽちぽちコマンドを打つだけでインストール可能といっているんですが、Dockerで作った僕の環境はちょっとだけ苦労しました。先に最終的な導入手順を書いておきます。



最終的な導入手順

Duskのインストール

  1. 必要なライブラリをインストールするように Dockerfile を更新
  2. Selenium コンテナを作成するための設定を docker-compose.yml に追加
  3. docker-compose up –buiild -d でコンテナを build
  4. composer require –dev laravel/dusk
  5. php artisan dusk:install

Duskを動かすための設定

  1. .env をコピーして .env.dusk.local を作成
  2. .env.dusk.local: APP_ENV=testing に変更
  3. .env.dusk.local: APP_URL=http://localhost を追加 ← ドメインを設定している場合はそのドメイン
  4. .env.dusk.local: DUSK_DRIVER_URL=http://selenium:4444/wd/hub を追加 ← docker-compose.yml で設定したコンテナ名
  5. DuskTestCase.php を設定



補足説明

必要になるライブラリ

最終的に「zip」「libxcb」「libnss3」の3つがないと怒られました。


require ext-zip * -> it is missing from your system. Install or enable PHP's zip extension.
vendor/laravel/dusk/bin/chromedriver-linux: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory
vendor/laravel/dusk/bin/chromedriver-linux: error while loading shared libraries: libxcb.so.1: cannot open shared object file: No such file or directory


Dockerfileに以下を追加します。


RUN apt-get update \
 && apt-get install -yqq --no-install-recommends \
 libnss3 \
 libxcb1-dev

RUN docker-php-ext-install zip


Selenium コンテナに関する設定

途中でメモリ不足で怒られたのでそれも確実に設定しておきます。docker-compose.yml での記述は以下の通り。ネットワーク部分は環境に応じて変えてください。


selenium:
 image: selenium/standalone-chrome-debug
 container_name: selenium
 shm_size: '2gb'
 restart: always
 ports:
   - 4444:4444
   - 5900:5900
 privileged: true
 networks:
   - proxy-network
   - service-network



DuskTestCase.php の設定

このままテストを実行するとSSL関連が上手く処理出来なくて以下のエラーが出ます。


SSL certificate problem: unable to get local issuer certificate


今回はローカル間での接続ですしSSLの問題は無視して構わないので、DuskTestCase.php に以下を追加します。


$options = (new ChromeOptions)->addArguments(collect([
   $this->shouldStartMaximized() ? '--start-maximized' : '--window-size=1920,1080',
])->unless($this->hasHeadlessDisabled(), function ($items) {
   return $items->merge([
       '--disable-gpu',
       '--headless',
       '--ignore-certificate-errors', // これを追加
   ]);
})->all());


以上で、ブラウザテストが実行出来るようになります。



まとめ:これからがブラウザテストだ

というわけで苦労の末、ブラウザテストが動くようになったわけですが、なにぶんこれまで書いたことがないので、


  • どんなアサーションを用意すれば良いのか
  • ページに対してどこまでテストを用意すれば良いのか
  • 全ての動作(クリックなど)を網羅すべきなのか
  • Seleniumで他にどんな良いことが出来るのか


などなどわからないことだらけですが、その辺のノウハウは誰かわかる人に聞きつつ良い感じで書いていければと思っています。まあ、基本的な部分はPHPUnitなのでなんとかなるでしょ。なるかな。なるといいな。そんな感じ。