シャッフル主任の進捗報告

興味のあるものを作ります。進捗を不定期にご報告します。

そうだ、教祖になろう。出エジプト記 第4章8節 クライアントサイドのE2Eテストを実装する

知らず知らず歩いてきた細く長いこの道


すっかり休み気分も抜けた頃ですが、あけましておめでとうございます。
お正月は異教の宗教施設に行ってきました。
やはり、朝の寺社仏閣は心が洗われます。
2020年も新たな気持ちで本ブログに取り組んでいきたいと思います。

f:id:chief-shuffle:20200104095645j:plain

振り返れば遥か遠く 故郷が見える


昨年の第4章7節 クライアントサイドのユニットテストをカバレッジ100%にするでJestでVue.jsのユニットテストを実装しました。
Jestはモジュール単位のテストですが今回はEnd to End Test、つまりブラウザからリクエストを送ったのをシミュレートして、返ってきたレスポンスをアサーションするテストを実装しようと思います。
使うのはNightwatchパッケージです。
まあこれが新年一発目のブログが遅れた理由です。
もちろん、正月ボケもその一因ですが。

Nightwatchは疑似的なサーバから受け取ったレスポンスをブラウザにレンダリングさせます。
Cloud9の実体はEC2インスタンスなのでAmazon Linuxになるわけですが、
GUI関連のライブラリが入っておらず、まずChromeのインストールがひと苦労でした。
試行錯誤をいちいち書いていると長くなりますし、細かいことは忘れてしまったので、要点だけ書き留めます。

まずyarn test:e2eを起動すると「何言ってんだい!うちにゃぁ、Chromeなんてないよ!嫌ならGoogleさんちの子になんな!」と怒られてしまいます。

Error: An error occurred while retrieving a new session: "unknown error: cannot find Chrome binary"

f:id:chief-shuffle:20200115190503j:plain

ああ川の流れのように


まずはChromeを入れるとこからです。
UIを伴わないヘッドレスChromeを導入します。
参考にさせていただだきました。

qiita.com

必要な依存パッケージを全部入れます。

$ sudo yum install -y cups-libs dbus-glib libXrandr libXcursor libXinerama cairo cairo-gobject pango ipa-gothic-fonts ipa-mincho-fonts
$ sudo rpm -ivh --nodeps http://mirror.centos.org/centos/7/os/x86_64/Packages/atk-2.28.1-1.el7.x86_64.rpm
$ sudo rpm -ivh --nodeps http://mirror.centos.org/centos/7/os/x86_64/Packages/at-spi2-atk-2.26.2-1.el7.x86_64.rpm
$ sudo rpm -ivh --nodeps http://mirror.centos.org/centos/7/os/x86_64/Packages/at-spi2-core-2.28.0-1.el7.x86_64.rpm
$ sudo rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/fedora/linux/releases/20/Fedora/x86_64/os/Packages/g/GConf2-3.2.6-7.fc20.x86_64.rpm
$ sudo rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/fedora/linux/releases/20/Fedora/x86_64/os/Packages/l/libXScrnSaver-1.2.2-6.fc20.x86_64.rpm
$ sudo rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/fedora/linux/releases/20/Fedora/x86_64/os/Packages/l/libxkbcommon-0.3.1-1.fc20.x86_64.rpm
$ sudo rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/fedora/linux/releases/20/Fedora/x86_64/os/Packages/l/libwayland-client-1.2.0-3.fc20.x86_64.rpm
$ sudo rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/fedora/linux/releases/20/Fedora/x86_64/os/Packages/l/libwayland-cursor-1.2.0-3.fc20.x86_64.rpm
$ sudo rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/fedora/linux/releases/20/Fedora/x86_64/os/Packages/g/gtk3-3.10.4-1.fc20.x86_64.rpm
$ sudo rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/fedora/linux/releases/16/Fedora/x86_64/os/Packages/gdk-pixbuf2-2.24.0-1.fc16.x86_64.rpm

yumリポジトリGoogleリポジトリを登録。

$ sudo touch /etc/yum.repos.d/google-chrome.repo
$ echo -e "[google-chrome]\nname=google-chrome\nbaseurl=http://dl.google.com/linux/chrome/rpm/stable/\$basearch\nenabled=1\ngpgcheck=1\ngpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub" | sudo tee -a /etc/yum.repos.d/google-chrome.repo
$ cat /etc/yum.repos.d/google-chrome.repo
[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub

Chromeの安定版をインストールします。

$ sudo yumdownloader google-chrome-stable
Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main                                                                                                                                                 | 2.1 kB  00:00:00     
amzn-updates                                                                                                                                              | 2.5 kB  00:00:00     
google-chrome                                                                                                                                             | 1.3 kB  00:00:00     
4668 packages excluded due to repository priority protections
google-chrome-stable-79.0.3945.117-1.x86_64.rpm                                                                                                           |  59 MB  00:00:01     
$ ls -l google-chrome-stable-79.0.3945.117-1.x86_64.rpm
-rw-r--r-- 1 root root 62377282 Jan  6 23:36 google-chrome-stable-79.0.3945.117-1.x86_64.rpm
$ sudo rpm -i --nodeps google-chrome-stable-79.0.3945.117-1.x86_64.rpm
Error: Could not find xdg-icon-resource
warning: %post(google-chrome-stable-79.0.3945.117-1.x86_64) scriptlet failed, exit status 1

xdg-icon-resourceが見つからないという警告が出ますが、ヘッドレスChromeなので構いません。
インストールされたバージョンを確認します。

$ /opt/google/chrome/chrome --version
/opt/google/chrome/chrome: /lib64/libdbus-1.so.3: no version information available (required by /usr/lib64/libatk-bridge-2.0.so.0)
/opt/google/chrome/chrome: /lib64/libdbus-1.so.3: no version information available (required by /usr/lib64/libatspi.so.0)
Google Chrome 79.0.3945.117 unknown

なにやら警告が2行出ていますが、バージョンが出ているのでとりあえずよし。

Googleトップページのスクショを撮ります。

/opt/google/chrome/chrome --headless --disable-gpu --window-size=1024,768 --hide-scrollbars --screenshot='google.png' https://www.google.co.jp/

f:id:chief-shuffle:20200115192449j:plain

たくさんメッセージが出ますが、Written to file google.png.が出てればOK。
PNGファイルを開いてみると、HTTPレスポンスが画像化されています。

f:id:chief-shuffle:20200115192530j:plain

とめどなく空が黄昏に染まるだけ


これで文句ないだろう!とyarn test:e2eを起動すると
「おっとっと、どうやらChromeが起動しなかったみたいだねぇ(ニヤニヤ)」と嫌らしい笑みを浮かべています。
ああ、憎たらしい!
神様、なぜ新年からこのような奴と餅を吸わねばならんのでしょう!

Error: An error occurred while retrieving a new session: "unknown error: Chrome failed to start: exited abnormally"

f:id:chief-shuffle:20200115201939j:plain

しかし、エラーメッセージにヒントがありました。
あぁ、神は我を見放したもうたりはしなかった。

 ERROR  Error: Command failed: /home/ec2-user/environment/test/node_modules/nightwatch/bin/nightwatch --config /home/ec2-user/environment/test/node_modules/@vue/cli-plugin-e2e-nightwatch/nightwatch.config.js --env chrome

/home/ec2-user/environment/test/node_modules/@vue/cli-plugin-e2e-nightwatch/nightwatch.config.jsを見てみると、環境変数からヘッドレスChromeを使うかどうか判断しているようです。

const startHeadless = process.env.VUE_NIGHTWATCH_HEADLESS === '1'if (startHeadless) {
  chromeArgs.push('headless')
  geckoArgs.push('--headless')
}

この環境変数を設定してみます。

$ export VUE_NIGHTWATCH_HEADLESS=1
$ yarn test:e2e

f:id:chief-shuffle:20200115202759j:plain

やっと実行できました!
一発目からこれでは今年のブログライフの先が思いやられますが、これを~/.bashrcに設定しておけば安心です。

ちなみにテストソースは以下のような感じです。
3秒以内にbodyが現れ、メッセージが一致していることを確認しています。

module.exports = {
  'default e2e tests': browser => {
    browser
      .init()
      .waitForElementVisible('#app')
      .assert.elementPresent('div#life')
      .waitForElementVisible('body', 3000)
      .assert.elementPresent('div#life')
      .assert.containsText(
        'div#life ul',
        'あなたはアジアの小国の王様に生まれ変わりました。'
      )
      .end()
  },
}

もっと画面にボタンなどが増えてくれば活躍してくれそうです。
では、本年もご愛顧を賜りますようお願い申し上げます。