フロントエンド

storycap+reg-suitを利用したビジュアルリグレッションテストをCodeBuild上で実行する

jp

ビジュアルリグレッションテストとは

ビジュアルリグレッションテストとは、アプリケーションのスクリーンショット画像の差分をチェックすることで予期せぬ画面の崩れなどを検知することを目的としたテストのことです。基本的にはmainやdevelopなどの開発ブランチとfeatureやbugfixなどの各種機能開発/バグ修正ブランチの差分をチェックする運用になることが多いのではないでしょうか。

似たようなテスト形式としてスナップショットテストがあります。ビジュアルリグレッションテストの場合、スタイルシートの変更による差分も検知しやすくなるメリットがあります。

Webアプリケーションに対してビジュアルリグレッションテストを実行するためのツールにはいくつか選択肢があります。

例:

  • PlaywrightやCypressなどのe2eテストフレームワークを使用
  • Storybook + Chromatic(有料)
  • Storybook + Loki

今回はstorycapを用いてStorybookのスクリーンショットを生成し、reg-suitで画像差分チェックを行う工程をAWS CodeBuild上で実行し、Slack上にそのテスト結果とレポートが通知されるところまでを検証した内容を共有させていただきます。

手順

サンプルアプリ作成~Storybook作成

今回はVue3+Viteをベースにしたサンプルアプリを作成します。
npx sb initを実行すると自動的に最適化された形でStorybookの設定が導入されます。そのため今回はStorybookのビルドツールも自動的にViteになります。

$ npm init vue@latest

$ npx sb init

Storybookの設定(.storybook/main.js)でVueアプリケーション用のvite.config.jsの設定を再利用するように指定します。

const path = require("path")
const { mergeConfig, loadConfigFromFile } = require("vite")

module.exports = {
  // 一部省略
  async viteFinal(config, { configType }) {
    const { config: userConfig } = await loadConfigFromFile(
        path.resolve(__dirname, "../vite.config.ts")
    );
    return mergeConfig(config, {
      ...userConfig,
      plugins: [],
    });
  },
}

生成したサンプルアプリのうち一部のコンポーネントをStorybookにします。
Storybookでの見せ方を調整する意図でmarginを設定しています。

import TheWelcome from './TheWelcome.vue';
import  '../assets/base.css'
import type { Meta } from '@storybook/vue3';

export default {
    title: 'TheWelcome',
    component: TheWelcome,
    decorators: [() => ({ template: '<div style="margin: 3em;"><story /></div>' })],
} as Meta<typeof TheWelcome>;

export const Sample = () => ({
    components: { TheWelcome },
    template: '<TheWelcome> </TheWelcome>',
});

ここまでで、Storybookが作成されるところまで出来ました。

storycap導入

次にstorycapをインストールして、Storybookのスクリーンショットを撮影できるようにします。

$ npm i -D storycap

試しに実行すると、スクリーンショットが生成されます。

$ npx storycap --serverCmd "npx start-storybook -p 6060 --ci" http://localhost:6060
info Wait for connecting storybook server http://localhost:6060.
info Executable Chromium path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
info Storycap runs with simple mode
info Found 1 stories.
info Screenshot stored: __screenshots__/TheWelcome/Sample.png in 657 msec.
info Screenshot was ended successfully in 60326 msec capturing 1 PNGs.

実際に以下のような画像が生成されました。

reg-suit導入

reg-suitを導入することで、スクリーンショットの差分をチェックできるようになります。

$ npm install -D reg-suit

併せて、以下のプラグインを使用します

  • reg-simple-keygen-plugin: スクリーンショットの差分となるexpected(期待値)とactual(実際値)をGitコミットハッシュ値で指定する機能
  • reg-publish-s3-plugin: スクリーンショットやテスト結果のレポートをAWS S3に格納してくれる機能
  • reg-notify-slack-plugin: テスト結果をSlackに通知してくれる機能
$ npm i reg-simple-keygen-plugin -D
$ npm i reg-keygen-git-hash-plugin -D
$ npm i reg-notify-slack-plugin -D

reg-suitの設定(regconfig.json)では以下のように後ほどCodeBuild上で実行することを踏まえて、環境変数で指定する形式で記述します。
また、regconfig.jsonに直接記述する方法以外にも、npx reg-suit initコマンドを実行すると対話形式で設定を決定していくこともできます。

{
  "core": {
    "workingDir": ".reg",
    "actualDir": "__screenshots__",
    "thresholdRate": 0,
    "addIgnore": true,
    "ximgdiff": {
      "invocationType": "client"
    }
  },
  "plugins": {
    "reg-notify-slack-plugin": {
      "webhookUrl": "$SLACK_WEBHOOK_URL"
    },
    "reg-publish-s3-plugin": {
      "bucketName": "$S3_BUCKET_NAME"
    },
    "reg-simple-keygen-plugin": {
      "expectedKey": "$EXPECTED_KEY",
      "actualKey": "$ACTUAL_KEY"
    }
  }
}

S3バケットは手動で作成していただいても構いませんし、npx reg-suit prepare -p publish-s3コマンドで自動で作成していただくことも可能です。

環境変数を設定した上で手元のローカル環境で実行すると、以下のようなレポートが生成されます。

 $ npx reg-suit run

Slackにも通知が来ています

CodeBuild設定

最後にローカルで実行できたstorycap+reg-suitの操作をCodeBuild上で実行できるようにしていきます。今回はマネージド型イメージのUbuntuを使用します。また、CodeBuildのサービスロール上でS3へのアップロードを許可する必要があります。

以下のようにbuildspec.ymlを記述します。CodeBuild上でStorybookをHeadlessモードで起動しています。また、Chromeをインストールする必要があります。
reg-simple-keygen-pluginの実際値(actual)Gitコミットハッシュ値として、CodeBuildに予め用意されている環境変数を指定しています。

version: 0.2

env:
  variables:
    EXPECTED_KEY: ""
    ACTUAL_KEY: ""

phases:
  install:
    runtime-versions:
      nodejs: latest
    commands:
      # install node.js
      - npm i -g npm@latest
      - npm pkg get engines.node | sed 's/"//g' | xargs n
      # install packages
      - npm ci
      # chrome
      - curl -sS -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
      - echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list
      - apt-get -y update
      - apt-get -y install google-chrome-stable
  pre_build:
    commands:
      - npx storycap --serverCmd "npx start-storybook -p 6060 --ci" http://localhost:6060
      - EXPECTED_KEY=$(git rev-parse origin/main)
      - ACTUAL_KEY=$CODEBUILD_RESOLVED_SOURCE_VERSION
      - npm run reg-suit

AWSコンソール上でS3バケット名とSlackのWebHookURL(いずれも定数)の環境変数をセットします。

試しに意図的に差分を発生させた状態でソースをpush後、CodeBuildのビルドを実行すると、手元のローカル環境で実行した時と同様にレポートが作成され、Slackに通知されました。


出力されたレポート上でスクリーンショットの差分を視覚的に確認することができます。

Slackにも同様に通知されています。

実際の運用ではCode4兄弟でCI/CDを完結させる前提でビジュアルリグレッションテストを導入する場合は任意のブランチでビルドが実行できるように追加の作業が発生することを考慮するとより便利になるのではないでしょうか。

参考

https://gist.github.com/vinaymavi/d17f690c90a9434489fd74f40862c1cf

AUTHOR
jp
jp
記事URLをコピーしました