giftee Tech Blog

ギフティの開発を支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信しています。

Docker で Cypress を実行して Mac で GUI を操作する

こんにちは、ギフティでエンジニアをしている @megane42 といいます。社内では主に B2B2C な Web アプリの開発と運用をしています。

概要

Web アプリの E2E テストを Cypress で書いてみようと思ったのですが、テスト対象の Web アプリが JS 製ではないので、JS の実行環境を整える代わりに Docker 上で実行できるようにしてみました。さらに、Cypress には GUI のデバッグツールが備わっていて、それがとても便利そうだったので、Cypress 自体は Docker コンテナ内で動かしつつ、GUI は Mac から触れるような環境を整えました。

・・・といっても、Docker イメージは公式のものがありますし、GUI 周りを含めた環境構築についても Cypress 公式ブログ で丁寧に解説されています。ただし、一部そのままだと起動できないところがあったり、日本語で書かれた情報があまり見当たらなかったので、今回改めて記事にしてみました。

環境

  • macOS 11.2.1
  • docker desktop 3.1.0

戦略

  • Mac に X11 サーバーをインストールし、コンテナ上で動く Cypress のウィンドウを Mac 上に表示させます
    • X11 とは
      • 古から使われる、ウィンドウを描画・管理するためのソフトウェアです(ざっくり)
      • サーバークライアントモデルになっており、あるマシンの上で動いているプログラムの GUI を、ネットワーク上の別のマシンの画面上に表示することができます
        • 今回でいうと、コンテナ上で Cypress を動かし、そのウィンドウを同じネットワーク上の Mac に表示させる形になります
        • 直感と逆に感じられるかもしれませんが、Mac 側で起動するのが X サーバーで、コンテナ上で動く Cypress が X クライアントと呼ばれます
    • こと Mac においては、XQuarts という X11 実装が存在するので、それを使います

手順

XQuartz をインストール

(初回のみ) リモートマシンから X サーバーへの通信を許可

  • 前述の通り、今回はコンテナというリモートマシンから Mac 上の X サーバーに通信が来るという構造になります
  • しかし、XQuartz はデフォルト設定だとリモートマシンからの通信を受け付けません
  • そこで、下記のコマンドでローカル IP からの通信を許可しておきます
IP=$(ipconfig getifaddr en0)
/usr/X11/bin/xhost + $IP
  • あわせて、Mac のアプリケーション -> ユーティリティから XQuartz.app を開き、環境設定 -> セキュリティから ネットワーク・クライアントからの接続を許可 にチェックを入れます
    • XQuartz.app を再起動しないと反映されないので再起動します

XQuartz を起動

  • Mac のアプリケーション -> ユーティリティから XQuartz.app を起動しておきます
    • 起動時に白いターミナルが出てきますが、これは使わないのですぐ閉じて OK です

Cypress コンテナを起動

  • 下記のコマンドで Cypress コンテナを起動します
    • 公式ブログで紹介されているオプションそのままだと起動できなかったので、一部修正しています
    • ちなみに冒頭の DISPLAY=$IP:0 は X11 が定める環境変数で、X クライアント (= Cypress) がどこに画面を描画すべきかを指定するものです
      • 本来は DISPLAY=<XServer ホスト名 or アドレス>:<ディスプレイ番号>.<スクリーン番号> という形式なのですが、スクリーン番号が省略されています
DISPLAY=$IP:0
docker run \
  -it \
  --rm \
  --network host \
  -v ~/.Xauthority:/root/.Xauthority:ro \
  -v $PWD:/e2e \
  -w /e2e \
  -e DISPLAY \
  --entrypoint  cypress \
  cypress/included:3.2.0 open --project .
  • うまくいけば、記事冒頭のように Cypress の GUI ウィンドウが表示されます

まとめ

というわけで、Docker コンテナ内で Cypress を動かしつつ GUI も使えるような環境を用意してみました。

実は後で気づいたのですが、Cypress は初めから十分 self-contained ですし(ブラウザすら内蔵されている)、テストを実行したいだけであれば 実行ファイルを直接ダウンロード することで npm すら入れずに起動できるので、Docker 化する利点は比較的少ないかもしれません・・・。とはいえ、普段 Node.js を使わない開発チームにおいてはより手軽に環境を整えられますし、なにより X11 でネットワーク越しに GUI を操作するのはちょっと楽しかったです。ギフティでは、技術を楽しみながら一緒にプロダクトを育てていく仲間を 絶賛募集中 です!

参考