Reactのテストはスナップショットじゃなくてスクリーンショットで


Reactのテスト書いてますか?
スナップショットテストが一般的ですが、GitHubのPullRequestではどうも差分が分かりづらい。もしスクリーンショットを自動的に撮って差分を画像ファイルとして比較できたらなぁと思っていたところ良さそうなパッケージを見つけました。react-screenshot-testというパッケージなのですが、以下のように差分を画像ファイルとして確認できる素晴らしいツールです。

早速試してみます。まずはインストールから

$ yarn add -D react-screenshot-test

次に設定ファイルを作成します。

jest.screenshot.config.js
module.exports = {
  testEnvironment: "node",
  globalSetup: "react-screenshot-test/global-setup",
  globalTeardown: "react-screenshot-test/global-teardown",
  testMatch: ["**/?(*.)+(screenshot).[jt]s?(x)"],
  transform: {
    "^.+\\.[t|j]sx?$": "babel-jest", // or ts-jest
    "^.+\\.css$": "react-screenshot-test/css-transform",
    "^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
      "react-screenshot-test/asset-transform"
  }
};

babelを使うようなので以下ファイルも用意しておきます。ちなみに今回作成したサンプルアプリケーションは create-react-appを使用しています。

babel.config.js
module.exports = {
  presets: ["babel-preset-react-app"]
};

スナップショットを作成するコードはこんな感じになるようです。デスクトップとiPhoneXのそれぞれの場合でスクリーンショットを撮ります。

App.screenshot.jsx
import React from "react";
import { ReactScreenshotTest } from "react-screenshot-test";
import "./index.css";
import App from "./App";

ReactScreenshotTest.create("App")
  .viewport("Desktop", {
    width: 1024,
    height: 768
  })
  .viewport("iPhone X", {
    width: 375,
    height: 812,
    deviceScaleFactor: 3,
    isMobile: true,
    hasTouch: true,
    isLandscape: false
  })
  .shoot("app", <App />)
  .run();

あとは以下のコマンドを実行して作成するようです。npmスクリプトに登録しておきましょう。

$ jest -c jest.screenshot.config.js -u

実行すると以下のエラーが発生しました。どうやら必要なdockerイメージがあるようです。

$ yarn test:screenshot
yarn run v1.21.1
$ jest -c jest.screenshot.config.js -u
Error: It looks like you're missing the Docker image required to render screenshots.

Please run the following command:

$ docker pull fwouts/chrome-screenshot:1.0.0


    at ensureDockerImagePresent (/Users/daisuke/work/react/screenshot.lesson/node_modules/react-screenshot-test/dist/lib/screenshot-server/DockerizedScreenshotServer.js:50:15)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async DockerizedScreenshotServer.start (/Users/daisuke/work/react/screenshot.lesson/node_modules/react-screenshot-test/dist/lib/screenshot-server/DockerizedScreenshotServer.js:28:9)
    at async setUpScreenshotServer (/Users/daisuke/work/react/screenshot.lesson/node_modules/react-screenshot-test/dist/lib/global-setup.js:26:9)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

dockerイメージをpullしてから再チャレンジします。

$ yarn test:screenshot
yarn run v1.21.1
$ jest -c jest.screenshot.config.js -u
 PASS  src/App.screenshot.jsx (7.325s)
  App
    Desktop
      ✓ app (643ms)
    iPhone X
      ✓ app (680ms)

 › 2 snapshots written.
Snapshot Summary
 › 2 snapshots written from 1 test suite.

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   2 written, 2 total
Time:        7.384s
Ran all test suites.
✨  Done in 9.85s.

できました。きちんとデスクトップとiPhoneXの2種類のスクリーンショットが取得できていますね。

なかなか深掘りできそうな良いツールを見つけてしまった。まずは取り急ぎ書き留める。