アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

Amplify ConsoleのE2Eテストを導入してみた

morishitaです。

Nuxt.js で作っている SPA を Amplify Console で運用していることはこれまで数本のエントリで紹介してきました。

tech.actindi.net

tech.actindi.net

その Amplify ConsoleCypress によるE2Eテストがサポートされたという発表が2019年の10月にありました。

aws.amazon.com

その時から気になっていたのですが、ついに導入したので紹介します。

結論から言うと、Preview 機能と併用するとむちゃくちゃ便利です。
更にDependabotを組み合わせるとライブラリのアップデートもサクサク進みます!

Amplify ConsoleのE2Eテスト

次の手順で、E2E テストを追加できます。

  • Cypressの導入
  • テストの実装
  • Amplify.yml への Test ステップの追加

Cypress の導入

まずは Cypress を追加します。

> yarn add -D cypress

追加できたら次のコマンドを実行します。

> cypress open

すると cypress ディレクトリが作成され、サンプルコードが生成されます。
と同時にCypressのテストランナーウィンドウが開きます。
初回だと次のようなダイアログが表示されます。
サンプルコードを追加したので試してみろって書いてありますね。

Cypress初回起動
Cypress初回起動

とりあえず、OKボタンをクリックで閉じます。 ダイアログが閉じて次のように表示されます。

Cypressウィンドウ
Cypressウィンドウ

先程のダイアログのメッセージにあったサンプルのテストコードが表示されていると思います。
右上の Run All specs をクリックすると新たにブラウザが開いて、サンプルのテストが実行されます。

Cypressテスト実行
Cypressテスト実行

パタパタと画面が進んでなかなか見ていて楽しいです。
うまく動けば、Cypressのインストールは成功です。

テストの実装

自分のアプリケーションのテストコードは cypress/integration ディレクトリに追加していきます。

*.ts ファイルでも実装できますが、特にトランスパイルされて実行されるわけではなく、JSとして解釈され実行されるようです。なので、TSならではの型アノテーション等を実装するとエラーとなります。

きちんとトランスパイルために次のサイトに紹介されている通りに設定していきます。

typescript-jp.gitbook.io

次のコマンドで @cypress/webpack-preprocessor をインストールします。
トランスパイルには Webpackts-loader も使うのですが、SPAアプリケーションのプロジェクトに追加するならすでにインストール済みだと思うので足りないものだけインストールします。

> yarn add -D @cypress/webpack-preprocessor

そして次のように cypress/plugins/index.js を実装します。

const wp = require('@cypress/webpack-preprocessor');
module.exports = (on) => {
  const options = {
    webpackOptions: {
      resolve: {
        extensions: ['.ts', '.tsx', '.js'],
      },
      module: {
        rules: [
          {
            test: /\.tsx?$/,
            loader: 'ts-loader',
            options: { transpileOnly: true },
          },
        ],
      },
    },
  };
  on('file:preprocessor', wp(options));
};

さて、あとは自分のアプリケーションに合わせてテストを書いていきます。
例えば、サイトトップにアクセスして、タイトルに特定の文字列(例では「ページタイトル」)が含まれるかを確認するテストは次のとおりです。

describe('Top Page', () => {
  beforeEach(() => {
    cy.viewport('iphone-x');
    cy.visit('/');
  });
  it('Title is valid', () => {
    cy.title().should('to.match', /ページタイトル/);
  });
});

ページを操作するコマンドや、テストに利用するアサーションは多数用意されています。
詳しいドキュメントがあるので、それを参考にテストを実装していきます。

docs.cypress.io

amplify.yml の設定

Cypressでテストが実装できたら、Testステップをamplify.yml に追加します。

そうすると次のように Amplify Console にテスト結果が表示されるようになります。
Preview機能を利用していると、プルリクエストを作ると自動的に実行されるので手間いらずです。

Amplify Consoleテスト結果表示
Amplify Consoleテスト結果表示

テストフェーズの前のビルドフェーズの実行結果がそのまま残っているので、テストフェーズでは改めてNuxtアプリケーションをビルドしたりする必要はありません。
E2Eテストを実行するためには次のように amplify.yml に追加します。

test:
  phases:
    preTest:
      commands:
        - mkdir noto # ① 日本語 Fonts のインストール [ここから]
        - curl -O -L https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip
        - unzip NotoSansCJKjp-hinted.zip -d ./noto
        - mkdir -p ~/.fonts/noto
        - cp ./noto/*.otf ~/.fonts/noto/
        - chmod 644 ~/.fonts/noto/*.otf
        - fc-cache -fv # ① 日本語 Fonts のインストール [ここまで]
        - nvm use $VERSION_NODE_12 # ② Nodeバージョンの変更
        - yarn install
        - yarn add wait-on
        # ③ mocha のインストール ↓
        - yarn add mocha@~7.1.1 mochawesome@~5.0.0 mochawesome-merge@~4.0.3 mochawesome-report-generator@~4.1.0 
        - 'yarn start & npx wait-on http://localhost:3000'
    test:
      commands:
        - 'npx cypress run --reporter mochawesome --reporter-options "reportDir=cypress/report/mochawesome-report,overwrite=false,html=false,json=true,timestamp=mmddyyyy_HHMMss"'
    postTest:
      commands:
        - npx mochawesome-merge cypress/report/mochawesome-report/mochawesome_*.json > cypress/report/mochawesome.json
        # ④ HTMLファイルの生成 ↓
        - ./node_modules/.bin/marge cypress/report/mochawesome.json -o cypress/report/html 
  artifacts:
    baseDirectory: cypress
    configFilePath: '**/mochawesome.json'
    files:
      - '**/*.png'
      - '**/*.mp4'
      - '**/mochawesome.json'
      - 'report/html/**/*' # ④ HTMLファイルの生成

上記の設定は次の AWS Amplify のドキュメントほぼそのままですが、丸数字でコメントしている部分を変更しています。

docs.aws.amazon.com

以下にそのポイントを説明します。

ポイント① 日本語Fonts のインストール

Amplify Console の実行環境には日本語フォントがインストールされていません。
テスト実行時にテスト実行の様子が自動的にビデオが作成されます。エラーが発生するとその画面のスナップショットが取られます。しかし、そのままでは日本語部分に文字が表示されません。それではエラーが起こった際になんだかよくわからず、デバッグに役立ちません。
なので日本語フォントをインストールしておきます。ここでは Google Noto Fonts をインストールしています。

ポイント② Nodeバージョンの変更

Amplify Consoleの実行環境では複数のNode.jsのバージョン管理にnvmを使っているようです。
ということは、nvm use で Nodeバージョンを切り替えられます。

次の環境変数に利用可能なNode.jsのバージョンが設定されています。

  • VERSION_NODE_10=10.16.0
  • VERSION_NODE_12=12
  • VERSION_NODE_8=8.12.0
  • VERSION_NODE_DEFAULT=10.16.0

指定しなければ、 VERSION_NODE_DEFAULT10.16.0 で動作します。
今となってはちょっと古めなので、VERSION_NODE_12 を指定したほうがいいかと思います。
VERSION_NODE_12はメジャーバージョンしか指定されていませんが、2020年3月の時点では 12.8.1 がインストールされます。

ポイント③ mocha 関連モジュールのインストール

テスト結果を mochawesome 形式で整形したいので、関連モジュールをインストールします。
前述したAWSのドキュメントだと、mocha@5.2.0が指定されています。
これはE2Eテストサポートがリリースされた当初、mochawesomemocha のバージョン5系にしか対応していなかったためです。
今は最新の mochamochawesome が対応しているのでバージョン指定なしでも構わないのですが、この先のアップデートで依存関係が壊れてエラーになっても嫌なのでバージョンを指定しています。

ポイント④ HTMLファイルの生成

結果は mochawesome 形式で出力され、Amplify Consoleではそれを使って表示が作られます。エラーが発生したときにはもっと見やすい詳細結果がほしいので、HTML形式の結果も出力しています。
アーティファクトにも含めておけば、ダウンロードして次のようなファイルで結果が確認できます。

HTML形式のテスト結果
HTML形式のテスト結果

注意点

既存のAmplify Consoleのアプリケーションにテストステップを追加しても、CIフロー内で実行はしてくれるのですが、Web Console上てテストフェーズが表示されないことがあります。
その場合は、アプリケーションを作り直してやると、Test が認識され Web Console上で反映されます。
まあ、独自ドメインの設定等をしていると作り直し自体が結構厄介なのですが...。

次のように Amplify Console のアプリの設定でフレームワークとして Cypress と表示されていれば、Web Console上でちゃんと表示されます。

Amplify Console アプリの設定
Amplify Console アプリの設定

まとめ

Amplify ConsoleのE2Eテストについて紹介しました。
この機能について紹介しているサイトはいくつかありますが、あまり触れられていない次の項目についても紹介しました。

  • 日本語対応
  • Nodeのバージョン指定
  • HTML形式の結果出力

Amplify Consoleでは Preview という超便利な機能があります(参考:Amplify Console の Preview は超便利)。 設定しておくとプルリクエスト毎にプレビュー環境を作成する際に、E2Eテストも実行してくれます。
更にGithubのリポジトリにDependabotを設定しておくと、Dependabotが作ったプルリクエストでも同様にE2Eテストを実行してくれます。
NPMパッケージのアップデートは結構頻繁に行われるのですが、しっかりE2Eテストを作っておくと自信を持ってマージでき、面倒なライブラリのアップデートがサクサク片付きます。

最後に

アクトインディではエンジニアを募集しています。 actindi.net