LoginSignup
14
11

More than 3 years have passed since last update.

GitLab CI/CD + Storybook + Storycap + reg-suit で画像回帰テストを行う

Posted at

はじめに

UI のデグレを防ぐため、Vue App に画像回帰テストを導入しました。

CI 環境はGitlab CI/CDを利用しました。

本記事は Gitlab CI/CD を用いた画像回帰テストの導入が主眼であり、Vue, Storybook の導入・作成については触れません。

構成

gitlab (1).png

環境

GitLab: GitLab Community Edition 13.6.1

package.json
{
  "vue": "^2.6.12",
  "@storybook/vue": "^5.3.19",

  "storycap": "^3.0.3",
  "puppeteer": "^5.5.0",

  "reg-suit": "^0.10.10",
  "reg-keygen-git-hash-plugin": "^0.10.11",
  "reg-notify-gitlab-plugin": "^0.10.11",
  "reg-notify-slack-plugin": "^0.10.10",
  "reg-publish-s3-plugin": "^0.10.10"
}

前提

前述したとおり、アプリ、Storybook は作成済みとします。

手順

  1. Storycap のインストール
  2. Storycap の設定
  3. reg-suit の導入
  4. Gitlab CI/CD の設定

1. Storycap のインストール

今回は Storybook からスクリーンショットを生成するためのツールとして、Storycap を採用しました。
こちらは、storybook-chrome-screenshotzisuiと呼ばれるツールの後継となります。
reg-suitと製作者が同一です。

さて、こちらを参考に、Storycap をインストールします。

yarn add -D reg-suit storycap puppeteer

Chromium を制御するツールとして、Puppeteer も一緒にインストールしています。
v3.0.0 以降、Storycap は Puppeteer を直接使用しません。
そのため、Puppeteer を使用したい場合は明示的にインストールする必要があります。

2. Storycap の設定

こちらを参考に、package.json に scripts を追加します。
※ Storybook 起動時の timed out を避けるため、serverTimeout を追加しています。

package.json
{
  "scripts": {
    "storybook": "start-storybook -p 6006 -s public",
    "storycap": "storycap --serverCmd \"yarn storybook\" http://localhost:6006 --serverTimeout 600000"
  }
}
__screenshots__

この状態で yarn storycap を行うと、デフォルトの __screenshots__ ディレクトリにスクリーンショットが格納されます。

3. reg-suit の導入

インストール後、初期設定を行います。

yarn add -D reg-suit
# pluginのインストール時、yarnを使う場合は --use-yarn を指定する
yarn run reg-suit init --use-yarn
# Answer a few questions...

初期設定では、Plugin のインストールと設定ファイルの生成を行っているようです。
今回は以下の Plugin を選択しました。

  • reg-keygen-git-hash-plugin
    • 各コミットのハッシュ値から、比較対象のコミットを識別するようです。デフォルトで選択済みになっているため、そのまま選択します
  • reg-publish-s3-plugin
    • s3 に画像をアップロードするために使用します
  • reg-notify-gitlab-plugin
    • gitlab 連携に使用します。今回のメインです

また、Directory contains actual images は storycap の出力先である__screenshots__を指定しました。

これにより、以下のようなファイルが生成されます。

regconfig.json
{
  "core": {
    "workingDir": ".reg",
    "actualDir": "__screenshots__",
    "thresholdRate": 0,
    "ximgdiff": {
      "invocationType": "client"
    }
  },
  "plugins": {
    "reg-keygen-git-hash-plugin": true,
    "reg-notify-gitlab-plugin": {
      "privateToken": "xxxxxxxxxxxxxxxx",
    },
    "reg-publish-s3-plugin": {
      "bucketName": "reg-publish-bucket-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    }
  }
}

package.json に reg-suit run コマンドを追加します。

package.json
{
  "scripts": {
    "reg-suit": "reg-suit run",
  }
}

この状態で yarn reg-suit を行うと、現行の__screenshots__に存在する画像群がアップロードされます。

4. Gitlab CI/CD の設定

さて、本題です。

4.1. projectId の取得

まずはじめに projectId を取得します。
https://user-domain/your-name/your-project-name/editにアクセスすると、取得できます。

4.2. access token の取得

次に、Gitlab 連携に必要なトークンを取得します。

  1. http://user-domain/-/profile/personal_access_tokensにアクセス
  2. 任意の Name, Expires at を入力
  3. Scopes に apiを選択
    • ※スコープの指定は特にありませんでしたが、apiのみを指定してみたところ、問題なく動作しました。
  4. Create personal access tokenをクリック
  5. 画面上部に表示されたトークンをregconfig.jsonprivateTokenに指定

これらの値を使い、regconfig.json を以下のように変更しました。

regconfig.json
    "reg-notify-gitlab-plugin": {
      "projectId": "1234",
      "privateToken": "abcdef1234567890",
      "gitlabUrl": "http://user-domain"
    },

4.3. Gitlab CI/CD の環境変数の設定

Gitlab CI/CD で AWS のコマンドを使用するために環境変数の設定行います。
こちらを参考に 3 つの環境変数を指定すれば OK です。

image.png

4.4. .gitlab-ci.yml の作成

最後に、reg-suit のサンプルpuppeteer のサンプルを参考に、Alpine image を使用してビルドを書いていきます。

gitlab-ci.yml
image: alpine:edge

cache:
  paths:
    - node_modules

# Tell Puppeteer to skip installing Chrome. We'll be using the installed package.
# Ref. https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine
variables:
  PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true"
  PUPPETEER_EXECUTABLE_PATH: "/usr/bin/chromium-browser"

test:
  # Add AWS CLI
  # Ref. https://stackoverflow.com/questions/61918972/how-to-install-aws-cli-on-alpine#:~:text=1%2Dalpine%20.,69%20etc.
  # Add Puppeteer
  # Ref. https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine
  before_script:
    - apk update
    - |
      apk add --no-cache \
              python3 \
              py3-pip \
              git \
              chromium \
              nss \
              freetype \
              freetype-dev \
              harfbuzz \
              ca-certificates \
              ttf-freefont \
              nodejs \
              yarn \
              npm \
          && pip3 install --upgrade pip \
          && pip3 install \
              awscli \
          && rm -rf /var/cache/apk/*
    # Used by reg-keygen-git-hash-plugin
    - git checkout $CI_COMMIT_REF_NAME || git checkout -b $CI_COMMIT_REF_NAME && git pull
    - yarn

  script:
    - yarn run storycap
    - yarn run reg-suit

この状態で Push を行うと、無事画像がアップロードされます。

$ yarn run reg-suit
yarn run v1.22.10
$ reg-suit run
[reg-suit] info version: 0.10.10
[reg-suit] info Detected the previous snapshot key: '6397a389f4e7b0c5ff39961e967bc8537fab9cde'
[reg-suit] info Comparison Complete
[reg-suit] info    Changed items: 0
[reg-suit] info    New items: 59
[reg-suit] info    Deleted items: 0
[reg-suit] info    Passed items: 0
[reg-suit] info The current snapshot key: 'd78704895f5175f7e193e6ff22c50bfdcf096d78'
[reg-publish-s3-plugin] info Upload 63 files to reg-publish-bucket-xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx.
[reg-suit] info Published snapshot 'd78704895f5175f7e193e6ff22c50bfdcf096d78' successfully.
[reg-suit] info Report URL: https://reg-publish-bucket-xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx.s3.amazonaws.com/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.html
[reg-notify-gitlab-plugin] warn There's no opened merge requests including the commit d78704895f5175f7e193e6ff22c50bfdcf096d78 ...
Done in 22.26s.
Saving cache for successful job
01:28
Creating cache default...
node_modules: found 225385 matching files and directories
Uploading cache.zip to https://development-infra-gitlab-ci-cache-master.s3.dualstack.ap-northeast-1.amazonaws.com/project/1111/default
Created cache
Cleaning up file based variables
00:01
Job succeeded

ブランチ切り替え後、適当にファイルを変更して再度 Push すると、以下のように変化しました。うまく差分比較できているようです。

[reg-suit] info Comparison Complete
[reg-suit] info    Changed items: 7
[reg-suit] info    New items: 0
[reg-suit] info    Deleted items: 0
[reg-suit] info    Passed items: 52

Gitlab の MR のコメントはこの通り。

comment.png

※Gitlab CI/CD に不慣れなため、これが限界でした。
※よりよい方法があればご教示いただけますと幸いです。

トラブルシューティング

1. timed out

$ yarn storycap
yarn run v1.22.0
$ storycap --serverCmd "start-storybook -p 6006" http://localhost:6006
info Wait for connecting storybook server http://localhost:6006.
error Timed out waiting for: http-get://localhost:6006
Error: Timed out waiting for: http-get://localhost:6006
    at MergeMapSubscriber.project (/mnt/c/Users/works/my_repo/node_modules/wait-on/lib/wait-on.js:130:25)
    at MergeMapSubscriber._tryNext (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/operators/mergeMap.js:67:27)
    at MergeMapSubscriber._next (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/operators/mergeMap.js:57:18)
    at MergeMapSubscriber.Subscriber.next (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/Subscriber.js:66:18)
    at AsyncAction.dispatch (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/observable/timer.js:31:16)
    at AsyncAction._execute (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/scheduler/AsyncAction.js:71:18)
    at AsyncAction.execute (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/scheduler/AsyncAction.js:59:26)
    at AsyncScheduler.flush (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/scheduler/AsyncScheduler.js:52:32)
    at listOnTimeout (internal/timers.js:549:17)
    at processTimers (internal/timers.js:492:7)
error Command failed with exit code 1.

Puppeteer の起動に時間がかかっている模様です。
serverTimeout オプションを追加しました。
デフォルトが20000(20 秒)なので、60000(60 秒)に。

2. WSL で storycap が実行できない

$ yarn storycap
yarn run v1.22.0
$ storycap --serverCmd "start-storybook -p 6006" http://localhost:6006 --serverTimeout 60000
info Wait for connecting storybook server http://localhost:6006.
error Failed to launch the browser process!
/mnt/c/Users/works/my_repo/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome: error while loading shared libraries: libxkbcommon.so.0: cannot open shared object file: No such file or directory


TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md

Error: Failed to launch the browser process!
/mnt/c/Users/works/my_repo/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome: error while loading shared libraries: libxkbcommon.so.0: cannot open shared object file: No such file or directory


TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md

    at onClose (/mnt/c/Users/works/my_repo/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:193:20)
    at Interface.<anonymous> (/mnt/c/Users/works/my_repo/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:183:68)
    at Interface.emit (events.js:327:22)
    at Interface.close (readline.js:416:8)
    at Socket.onend (readline.js:194:10)
    at Socket.emit (events.js:327:22)
    at endReadableNT (_stream_readable.js:1221:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

WSL(Windows Subsystem Linux)だと Puppeteer の名前解決ができない模様。
Powershell で実行したらいけました。

3. Powershell でreg-suit runが動かない

>  yarn reg-suit
yarn run v1.22.0
$ reg-suit run
[reg-suit] info version: 0.10.10
'grep' �́A�����R�}���h�܂��}���h�A
����\�ȃv���܂��̓o�b�` �t�@�C�������Ă��܂���B
[reg-keygen-git-hash-plugin] error Command failed: git branch | grep "^\*" | cut -b 3-
'grep' �́A�����R�}���h�܂��}���h�A
����\�ȃv���܂��̓o�b�` �t�@�C�������Ă��܂���B

[reg-suit] warn Failed to detect the previous snapshot key
[reg-suit] info Skipped to fetch the expected data because expected key is null.
[reg-suit] info Comparison Complete
[reg-suit] info    Changed items: 0
[reg-suit] info    New items: 60
[reg-suit] info    Deleted items: 0
[reg-suit] info    Passed items: 0
Error: Fail to detect the current branch.
    at CommitExplorer.getCurrentCommitHash (C:\Users\works\my_repo\node_modules\reg-keygen-git-hash-plugin\lib\commit-explorer.js:43:19)
    at GitHashKeyGenPlugin.getActualKey (C:\Users\works\my_repo\node_modules\reg-keygen-git-hash-plugin\lib\index.js:33:47)
    at RegProcessor.getActualKey (C:\Users\works\my_repo\node_modules\reg-suit-core\lib\processor.js:105:18)
    at C:\Users\works\my_repo\node_modules\reg-suit-core\lib\processor.js:27:31
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

原因は不明。WSL で実行できたため、それで良しとします。

4. Gitlab CI/CD で yarn run storycap 実行時に puppeteer のエラー

$ yarn run storycap
yarn run v1.22.10
$ storycap --serverCmd "yarn storybook" http://localhost:6006 --serverTimeout 600000
info Wait for connecting storybook server http://localhost:6006.
error Failed to launch the browser process! spawn /builds/project/my_repo/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome ENOENT
TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
Error: Failed to launch the browser process! spawn /builds/project/my_repo/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome ENOENT
TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
    at onClose (/builds/project/my_repo/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:193:20)
    at ChildProcess.<anonymous> (/builds/project/my_repo/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:185:85)
    at ChildProcess.emit (events.js:315:20)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)
    at onErrorNT (internal/child_process.js:465:16)
    at processTicksAndRejections (internal/process/task_queues.js:80:21)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Cleaning up file based variables
00:00
ERROR: Job failed: exit code 1

こちらを参考に、インストール済みの Chrome を使うように設定します。

variables:
  PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true"
  PUPPETEER_EXECUTABLE_PATH: "/usr/bin/chromium-browser"

5. Gitlab CI/CD で yarn run reg-suit 実行時に Plugin のエラー

$ yarn run reg-suit
yarn run v1.22.10
$ reg-suit run
[reg-suit] info version: 0.10.10
[reg-keygen-git-hash-plugin] error Can't detect branch name because HEAD is on detached commit node.
[reg-suit] warn Failed to detect the previous snapshot key
[reg-suit] info Skipped to fetch the expected data because expected key is null.
[reg-suit] info Comparison Complete
[reg-suit] info    Changed items: 0
[reg-suit] info    New items: 59
[reg-suit] info    Deleted items: 0
[reg-suit] info    Passed items: 0
Error: Fail to detect the current branch.
    at CommitExplorer.getCurrentCommitHash (/builds/project/my_repo/node_modules/reg-keygen-git-hash-plugin/lib/commit-explorer.js:43:19)
    at GitHashKeyGenPlugin.getActualKey (/builds/project/my_repo/node_modules/reg-keygen-git-hash-plugin/lib/index.js:33:47)
    at RegProcessor.getActualKey (/builds/project/my_repo/node_modules/reg-suit-core/lib/processor.js:105:18)
    at /builds/project/my_repo/node_modules/reg-suit-core/lib/processor.js:27:31
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

ブランチ名が検出できない模様。
こちらを参考に、git checkout $CI_COMMIT_REF_NAME || git checkout -b $CI_COMMIT_REF_NAME && git pull を追加することで解消しました。

14
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
11