📷

Next.js+Storybook+StoryShotsでスナップショットイメージによるUIテストを実現する

2022/10/09に公開

StoryShotsにおけるフロントエンド(UI)テスト

StoryShotsとは、コンポーネントの自動スナップショットテストを実現できるStorybookのアドオンです。予期しないUI変更を確認できるため、複数人で行う中規模以上のフロントエンド開発等で特に有効だと思われます。

ただし、CSS Modulesを利用している場合、StoryShotsのデフォルト設定で行うテストだと、CSSの変更を検知できず、コンポーネントの見た目が予期せず変わってしまったとしても、エラーを出してくれません。

上記問題を解決するために、また、実際にUIが変更されていないか、キャプチャー(画像)を通して確認したい場合は@storybook/addon-storyshots-puppeteerを利用したスナップショットイメージによるUIテストを行うことで、実現することができます。

スナップショットイメージによるUIテストを実現する

実際に、@storybook/addon-storyshots-puppeteerを導入する手順を紹介します。
StorybookやStoryShotsの導入に関しては、事前に下記記事で確認してください。
https://zenn.dev/toono_f/articles/4d1dc926c4e041

@storybook/addon-storyshots-puppeteerの導入

  1. 以下コマンドを実行し、必要なプラグインをインストールする
yarn add -D puppeteer @storybook/addon-storyshots-puppeteer
  1. package.jsonに以下記述を追加する
package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build && next export",
    "start": "next start",
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook",
    "storyshots": "jest --config ./jest.config.storyshots.js",
+   "storyshots:image": "jest --config ./jest.config.storyshotsImage.js",
  },
  "resolutions": {
    "react-test-renderer": "18.1.0"
  },
}
  1. jest.config.storyshotsImage.jsを作成する
jest.config.storyshotsImage.js
const nextJest = require("next/jest");

const createJestConfig = nextJest({
  dir: "./",
});

const customJestConfig = {
  displayName: "storyshots",
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1", // tsconfig.jsonのcompilerOptions>pathsの定義に合わせる
  },
  testEnvironment: "jest-environment-jsdom",
  testMatch: ["<rootDir>/src/tests/jest.storyshotsImage.ts"],
};

module.exports = createJestConfig(customJestConfig);
  1. jest.storyshotsImage.tsを作成する(配置先は上記にあるtestMatchの設定に合わせる)
src/tests/jest.storyshotsImage.ts
import initStoryshots from "@storybook/addon-storyshots";
import { imageSnapshot } from "@storybook/addon-storyshots-puppeteer";

initStoryshots({
  test: imageSnapshot(),
});

StoryShots(スナップショットイメージテスト)を実行する

本テストを行う前に、storybookのローカルサーバーを事前に立ち上げる必要があります。

yarn storybook

開発環境が立ち上がったら、以下コマンドを実行し、テストを実行します。

yarn storyshots:image

jest.storyshotsImage.tsの配置先に新規作成された__image_snapshots__ディレクトリ下に、コンポーネントごとのスナップショットイメージのファイルが存在すれば、実行成功です✨

差分がなければ、以下のようなログが表示されるはずです。

差分が発生している場合は、以下のようなログが表示されます。

上記ボタンコンポーネントのborder-radius10pxから0に変更しただけですが、以前のUI(見た目)とは0.011666666666666667%の違いがあるとエラーを出してくれるようです。

スナップショットイメージ(画像ファイル)も新たに生成され、目で差分を確認できます。

意図的な差分の場合、下記コマンドを実行することでスナップショットを更新できます。

yarn storyshots:image -u

エラー関連

@storybook/addon-storyshots-puppeteer を用いたスナップショットテストを行う際、ローカルのGoogle Chromeのバージョンが古い場合に以下のようなエラーが発生する可能性があります。

Could not find expected browser (chrome) locally. Run `npm install` to download the correct Chromium revision (1045629).

その場合、プロジェクトディレクトリ内のnode_modulesを削除した後に、npm installもしくはyarnを実行し、パッケージを再度インストールし直してください。

補足

Storybookに登録されているコンポーネントで画像が読み込まれている場合、事前に立ち上げたローカルサーバーにおけるstorybookの画面をブラウザで表示させておかないと、正しく画像が表示されない状態でスナップショットが行われる可能性があります。

事前にyarn build-storybookでビルドした静的ファイルを参照してスナップショットを行う設定もできますので、詳細は下記ドキュメントをご確認ください。
https://storybook.js.org/addons/@storybook/addon-storyshots-puppeteer

今回は以上になります。

より良いフロントエンド開発が行えるように、願っています👮

LCL Engineers

Discussion