reg-cliとMagic PodでE2Eテスト画像差分チェック

2020/07/13
EyeCatch

こんにちは、伊藤(@ito_nozomi)です。

ビジュアルリグレッションテストツールreg-cliを使って、E2E自動テストクラウドサービスMagic Podのテスト結果画像が正解画像と一致するかチェックする仕組みを、先日社内に構築したので、今日はそのやり方を紹介します。

reg-cliとは

reg-cliは、ビジュアルリグレッションテスト(画像回帰テスト、画像差分比較テスト)のためのツールです。同じようなツールでreg-suitというものもあり1 、reg-suitの内部ではreg-cliが利用されています。2つの違いとしては、

  • reg-cli: 2つの画像ディレクトリを指定して実行すると、分かりやすい差分HTMLレポートを生成してくれるコマンドラインツールです。
  • reg-suit: reg-cliの進化系で、画像比較だけでなく、正解データや差分レポートをAmazon S3などのクラウドストレージに保存したり、GitHubと連携してPull Requestに対する差分レポートを表示したりしてくれます。
図1 reg-suitのWebページ

比較したい画像の取得自体はreg-cliやreg-suitでは行ってくれない代わりに、色々なツールと組み合わせて使うことができます。Storybookと組み合わせたUIコンポーネント単位の画像差分をチェックする使い方が多いようですが、今回はE2Eテストで取得した画像の差分チェックに使ってみます。

Magic Podとは

Magic Podは、弊社が運営している、AI技術を活用したE2E自動テストクラウドサービスです。Webサイトとモバイルアプリのテストに対応しています。

どんなツールかは、こちらの動画を見ていただくと分かりやすいと思います。

図2 Magic Podのテストケース(モバイルアプリ)

reg-cli + Magic Pod

Magic PodもWebサービスなので、その開発にはテストが必要です。Magic PodのE2E自動テストに使っているのは .... もちろんMagic Podです2 。Magic Pod自体の画面のテストも、Magic Podで実施しています3

図3 Magic PodによるMagic PodのためのMagic Podブラウザテスト

今回は、この社内Magic Podテストの結果画像をWeb APIで取得して、取得した画像に対しreg-cliを実行することで、Magic Pod開発時のデザイン崩れを自動検出できる仕組みをCircleCI上に構築しました。(図4)

図4 Magic Podテスト実行結果をreg-cliで画像差分チェック

CircleCIからMagic Podのテストを実行し(①)、Magic PodのWeb APIを使って、最新のテスト結果画面キャプチャ(②)と、正解画像に使うテスト結果番号(図では「516」)に対応する画面キャプチャ(③)を取得します。2つの画像をreg-cliで比較し(④)、比較結果レポート(⑤)はArtifactsとしてCircleCIに保存します(⑥)。画像比較が失敗した場合はCircleCIのビルドが失敗し、結果がSlackに通知されます。生成される差分レポートは図5のようになります。

図5 reg-cliの差分レポート

差分のあった画像は、図6のように、ハイライト付きで差分を確認できます。

図6 reg-cliでの画像Diff確認

ポイントは以下の2点で、これにより構成が非常にシンプルになります。

  • 正解画像は、個々の画像ファイルではなくMagic Podのテスト結果番号で管理し、画像ファイルは比較時に毎回Magic Podからダウンロードします。これにより正解画像の管理が簡単になります。テスト結果番号はCircleCIの設定ファイルに直接記述しておき、正解画像を更新したい場合は、単にテスト結果番号を最新のものに更新します。
  • 結果レポートHTMLも、Amazon S3などの外部クラウドではなく、CircleCIのArtifactstとして保存します。レポートはCircleCIのテスト結果からリンクされているので簡単にたどれます。

現在は、この仕組みを日次で実行し、Magic Podの開発に役立てています。

設定方法

Magic Pod側のテストスクリプト

まずはMagic Podのテストスクリプトを作成します。その際に、画像比較を実施したいポイントで、「画面キャプチャを取得」コマンドを呼び出しておきます。(図7)

図7 「画面キャプチャを取得」コマンド

Magic Podではテスト実行時に全ステップの画面キャプチャを自動的に取得しますが、全部reg-cliの比較にかけると差分が出過ぎて辛いので、「画面キャプチャを取得」で明示的に取得した画像だけを比較することにします。(取得するキャプチャ名は日本語でも良いですが、コマンドラインのunzipコマンドがutf-8を認識できず文字化けする問題にはまりがちなので、ここでは英語にしています。)

これでテストスクリプト側の設定は終了です。ちなみにMagic Podの画面上でテストを一括実行し(図8)、「画面キャプチャを取得コマンドの結果をダウンロード」(図9)で取得した画面キャプチャをダウンロードすると、このあと差分チェックされる画像の内容を確認できます。

図8 テスト一括実行
図9 「画面キャプチャを取得」コマンドの結果をダウンロード

CircleCI側のスクリプト

続いてCircleCIの設定ファイルconfig.ymlの設定は以下の通りです。

....
- run:
    name: run test and generate image comparison report
    command: |
      bash run_e2e_and_visiual_test.sh /tmp/workspace/report_dir
- store_artifacts:
    path: /tmp/workspace/report_dir
    destination: image_diff_report
....

run_e2e_and_visiual_test.shでテスト実行・画面キャプチャダウンロード・画像差分レポートを生成し、store_artifactsで生成されたレポートをCircleCIのArtifactsとして保存します。run_e2e_and_visiual_test.shの中身は以下の通りです。

# run_e2e_and_visiual_test.sh

REPORT_DIR=$1 # 引数で指定されたレポート出力先
set -e # 各コマンドが失敗したらそこで終了

# ------------------------------------
# npmによるreg-cliのインストール
# ------------------------------------
npm init -y
npm install reg-cli # 作業ディレクトリにだけインストール

# ------------------------------------
# Magic Podのテストをコマンドライン一括実行
# ------------------------------------
https://www.trident-qa.com/magic-pod-batch-test-run/ の記事をもとに、環境に応じた設定を行ってください。
ここでは省略します。

# ------------------------------------
# テスト結果ダウンロード
# ------------------------------------
# https://magic-pod.com/accounts/api-token/ からコピー
export MAGIC_POD_API_TOKEN=**********
export MAGIC_POD_ORGANIZATION=TRIDENTDemo # 組織名
export MAGIC_POD_PROJECT=TestProject # プロジェクト名
BASELINE_RUN_NUMBER=516 # 正解画像に対応するテスト結果番号

# 最新のテスト結果番号をmagic-pod-api-clientで取得
ACTUAL_RUN_NUMBER=$(./magic-pod-api-client latest-batch-run-no)

# 最新のテスト結果画像を取得して解凍。
# command_only: 「画面キャプチャを取得」コマンドの画像だけをダウンロード
# auto_increment: デフォルトだとテストケースの行番号がファイル名に入ってファイル名が頻繁に変わってしまうので、auto_incrementで回避
# screenshot_name: 「画面キャプチャを取得」コマンドで指定したファイル名を利用
./magic-pod-api-client get-screenshots \
 --batch_run_number $ACTUAL_RUN_NUMBER \
 --download_path actual.zip \
 --download_type command_only \
 --file_index_type auto_increment \
 --file_name_body_type screenshot_name
unzip -d $REPORT_DIR actual.zip

# 正解画像を取得して解凍
./magic-pod-api-client get-screenshots \
 --batch_run_number $BASELINE_RUN_NUMBER \
 --download_path baseline.zip \
 --download_type command_only \
 --file_index_type auto_increment \
 --file_name_body_type screenshot_name
unzip -d $REPORT_DIR baseline.zip

# ------------------------------------
# 画像比較レポートを生成
# ------------------------------------
# --matchingThreshold 0.01で、見た目には分からない違いは無視
node_modules/.bin/reg-cli \
 ${REPORT_DIR}/${MAGIC_POD_PROJECT}_batch_run_${ACTUAL_RUN_NUMBER} \
 ${REPORT_DIR}/${MAGIC_POD_PROJECT}_batch_run_${BASELINE_RUN_NUMBER} \
 ${REPORT_DIR}/diff --matchingThreshold 0.01 \
 -R ${REPORT_DIR}/report.html
  • Magic PodのWeb API呼び出しはcurlでもできますが、ここではWeb API呼び出しがより簡単になるmagic-pod-api-clientをあらかじめGitレポジトリに入れて利用しています。
  • モバイルアプリの画像の場合、画面上部ステータスバーに日付が表示されるため、普通に画像比較すると毎回必ずエラーが出てしまいます。./magic-pod-api-client get-screenshots--mask_dynamically_changed_areaオプションを指定すれば、ステータスバーを黒塗りした画像がダウンロードされるため、この問題を回避することができます。

課題など

  • テスト実行のたびに毎回変わってしまう日付などの値は画像比較時に無視したいところなのですが、reg-cliではこういった仕組みは無いようです。コンポーネント単位のテストによく使われるreg-cliでは、あまりこうしたニーズは無いのかもしれません。今回はデータを調整したり、日付が含まれる画像は諦めるなどの方法で対処しましたが、今後はAppliToolsなどE2Eテストのビジュアルリグレッションテストにより適したツールとの連携も試してみたいと思います。
  • 画像差分チェックあるあるなのですが、読み込み処理のタイミングやアニメーションの状態により微妙に差分が出ることがあるので、そういった箇所ではページリロードや待ち処理を入れて対処しています4 。キャレット(テキスト入力欄で点滅しているあれ)の表示も問題になると思いきや特にならなかったのですが、Magic Pod(が裏側で使っているSelenium)で取得した画面キャプチャでは、どうやらキャレットは常に表示された状態になるようです。
  • OSのバージョンなど環境が少し違うだけで、フォント差異等で大量に差分が出るので、常に環境を固定できるCIサーバ上で実行しています。
  • Magic Podのブラウザテストでは、「画面キャプチャ範囲」を「ウィンドウ」にするとブラウザウィンドウ全体の画面キャプチャが取得できますが、これも微妙な差分が大量に出てくるので利用しないようにしています。

注釈・出典
  1. たぶんこちらの方が有名です。 []
  2. 歴史的事情によりSeleniumも使っていますが。 []
  3. テスト編集画面のテストをテスト編集画面で編集していたりすると時々よく分からなくなってきますが、ちゃんと使えます。 []
  4. FOLIOの画像回帰テストの裏側の記事にあった、Puppeteerのメトリクスを監視して落ち着いてから画面キャプチャをとる方法は良さそうなので、Magic Podでも今後試してみたいと思います。 []

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です