Nuxt on Dockerにtestcafeを導入する


こんにちは。@asatoです。
いま盛り上がっているTwitterスペース、気になるトピックを語っているTwitterスペースなどをかんたんに見つけられるspaces.bzというプロダクトを友人と運営しています。

https://spaces.bz

特に開発初期段階なので、機能追加も頻繁に行っており、勇気と自信をもってプロダクトションへのデプロイを繰り返すためには、やはりテストの自動化が必要です。
spaces.bzはNuxt.js on Dockerで開発しており、今回はTestCafeでテスト自動化を導入しています。
TestCafeは、クロスブラウザに対応しており、テストコードも非常にわかりやすく書けるのが特徴です。
今回は「Headless Chromeでテストがしたいなー」というのと、テストコードにあまり馴染みのない友人と一緒に開発しているので「わかりやすいテストコード」だと良いなーと思っており、TestCafeはまさにピッタリでした。

この記事では、Nuxt on Dockerの環境でTestCafeを導入し、かんたんなテストを実行するところまでをまとめていきます!💪

準備

Dockerfiledocker-compose.ymlは以下のようなものを想定しています。

Dockerfile
FROM  node
ENV   HOME=/app \
      HOST=0.0.0.0

WORKDIR ${HOME}

COPY  package.json ${HOME}
COPY  yarn.lock ${HOME}
RUN   yarn install
COPY  . ${HOME}

EXPOSE  3000
CMD     ["yarn", "dev"]
docker-compose.yml
version: "3"

services:
  app:
    build: .
    volumes:
      - .:/app
    ports:
      - 3000:3000

TestCafeをインストールする

TestCafeのパッケージをインストールします。今回はyarnを使っているので、

$ docker compose run app yarn add --dev testcafe

です。☕

DockerfileでChromeをインストールする

今回はHeadless Chromeを使ってテストをしたいので、DockerコンテナでChromeを起動できる状態にしておく必要があります。

Dockerfile
  ...略...
  WORKDIR ${HOME}

+ RUN   wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
+       sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' && \
+       apt-get update && \
+       apt-get install -y google-chrome-stable && \
+       apt-get install -yq fonts-noto-cjk

  COPY  package.json ${HOME}
  COPY  yarn.lock ${HOME}
  RUN   yarn install
  COPY  . ${HOME}
  ...略...

ChromeのStable版と、日本語のフォントを表示するためにfonts-noto-cjkをインストールするように追記しました。
追記ができたらビルドして、Dockerイメージを作成しましょう。

$ docker compose build

コマンドでTestCafeを起動できるようにする

次はコンテナでTestCafeを起動するコマンドの準備をしていきます。コンテナでyarn testのコマンドを実行したときにTestCafeが動くようにしましょう。

package.json
  ...略...
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
-   "generate": "nuxt generate"
+   "generage": "nuxt generate",
+   "test": "testcafe chrome:headless"
  },
  ...略...

testcafeの後ろにchrome:headlessを与えることでコンテナ内でHeadless Chromeを起動してテストしようとしてくれるんですね。
詳しくはこのへんに書いてます。

テストコードを書く

いよいよテストコードです。まずはテスト用のディレクトリとファイルを作っておきましょう。

$ mkdir tests
$ touch tests/sample.test.js

テストの内容は「トップページにアクセスして、<h1>タグで"Hello World!!"と表示されていること」を検証してみましょう。

tests/sample.test.js
import { Selector } from 'testcafe'

fixture('Sample')
  .page('http://localhost:3000')

test('トップページに<h1>タグで"Hello World!!"と表示されていること', async t => {
  await t
    .expect(Selector('h1').innerText).eql('Hello World!!')
})

なんか読みやすそうじゃないですか?😃
fixtureでテスト全体に関する設定とかを行っています。このテストファイルはSampleって名前で、http://localhost:3000にアクセスするところから始まるよって感じです。
testでその後の操作や検証を書いていきます。testは1ファイルに複数書けます。
今回は.expect(A).eql(B)を使ってABが一緒であることを検証してみます。
Aの方はSelector('h1').innerTextと書きました。最初に現れたh1タグのinnerTextを取得してます。こんな感じで使い慣れたjavascriptさんも使えるんですね。
Bの方にHello World!!の文字列を書けば、「最初に現れたh1タグのinnerTextHello World!!と一致すればテスト成功」となります。

ページを編集

このままテストを実行しても失敗するので、ページも編集しておきます。
TDDでやってみたい場合は、この時点で一度テストを実行してFailになることを確認してもOKです😆

pages/index.vue
<template>
  <div>
    <h1>Hello World!!</h1>
  </div>
</template>

テストを実行する

ではテストを実行しましょう・v・
テストを実行する前にコンテナを起動させておきます。

$ docker compose up -d

そして、execを使って起動したコンテナ内でTestCafeを実行します。

$ docker compose exec app yarn test tests/sample.test.js

yarn run v1.22.5
$ testcafe chrome:headless tests/sample.test.js
 Running tests in:
 - Chrome 93.0.4577.82 / Linux 0.0

 Sample
 ✓ トップページに<h1>タグで"Hello World!!"と表示されていること

 1 passed (2s)
Done in 31.12s.

PASS!!出力も非常にわかりやすいですね!

まとめ

この記事では、Nuxt on DockerにTestCafeを導入して、かんたんな自動テストを書いてみました。
自動テストがあれば、機能追加を頻繁に行なう環境でも勇気と自信を持ってデプロイできます!
そして、TestCafeはとても直感的なテストコードを書け、クロスブラウザにも対応しているすぐれものでした。
最後に、こんな自動テストを導入して開発しているspaces.bzもよろしくおねがいします!🤞