E2Eテスト自動化ツール「T-DASH」で画像比較のリグレッションテストをやってみた！

本記事は、[『テスト自動化ツールT-DASHの活用方法や事例を記事にしよう！ by T-DASH Advent Calendar 2022』](https://qiita.com/advent-calendar/2022/t-dash02)に参加しています。
よろしくお願いいたします！！
2022/12/4を担当しております。

https://qiita.com/advent-calendar/2022/t-dash02

[『テスト自動化ツールT-DASHの良い点・悪い点をレビューしてみた！ by T-DASH Advent Calendar 2022](https://qiita.com/advent-calendar/2022/t-dash01)』にも参加しております。

https://qiita.com/advent-calendar/2022/t-dash01

T-DASH」の使い方全般の記事はこちら

https://qiita.com/94dango/items/aa302f7bafc0598e8e68

本記事は、「T-DASH」の機能の一つである **画像比較テスト** について試した記事です。

# テスト対象

E2Eテストのリグレッションテストで画像比較テストを検討するケースがあります。
テスト対象要素に対して文字列でのアサーションが難しい場合に用いたりします。
例えば、文字列以外の情報で画面に描画される情報（地図やグラフなど）の新旧バージョンの比較などです。
私も担当しているプロダクトでPDF出力された明細をチェックするリグレッションテストがあり、この自動テストに画像比較テストを用いています。

「T-DASH」はE2Eテストの自動化に特化した自動化ツールですが、画像比較機能が標準機能として装備されています。
今回はこの画像比較機能を試していきます。
「T-DASH」の画像比較機能は、 **一致率を設定** できる特徴があります。
期待画像とテスト画像を照合して、 **画像の n％ が一致すれば「テストOK」** と判断とします。
この n% をテスターのさじ加減で調整できるのはよさそうです。

せっかくですので、毎回同じ操作を行ってもちょこっと違う結果が取得されるWebアプリをテスト対象に据えて試していきたいと思います。
趣味の実益も兼ねて今回は、テーブルトークRPG（TRPG）のダイスロールエンジン「BCDice」様のソースコードをお借りしました。

https://bcdice.org/

「BCDice」のWebAPIにGETリスエストを送信し、そのレスポンスで得られた結果を画像キャプチャーして画像比較していきます。

# 「BCDice」とは

クライアントからサーバーへコマンドを与えると **ダイス（サイコロ）を転がした結果を表示** してくれるWebアプリです。
クラウド環境にデプロイして使います。
`サーバーURL/{version}/game_system/{game_system_id}/roll?` にパラメーター `command` を渡してリスエストします。 

例えば、「v2/game_system/Cthulhu7th/roll?command=1D100」をサーバーへ送信すると、
1個の100面体ダイスを転がした結果を文字列で返してくれます。

```
// リクエスト
v2/game_system/Cthulhu7th/roll?command=1D100

//レスポンス
** (1D100) > 97 ← "97" がダイスを転がした結果です！！
{"ok":true,"text":"(1D100) ＞ 97","secret":false,"success":false,"failure":false,"critical":false,"fumble":false,"rands":[{"kind":"normal","sides":100,"value":97}]}

```

# テスト計画

次のテスト計画に沿って作業を進めます。
大きく分けて、手順（ステップ）は2つです。

1. 期待画像のスクリーンショットを取得するテストケースを作成し、キャプチャーする。
1. 期待画像と、テスト実行で取得したテスト結果画像を比較し、差分を検証する。

# テスト設計

それではテスト設計していきましょう。

## 期待画像のスクリーンショットを取得するテストケースを作成し、キャプチャーする

まずは **画像比較の比較元となる正解の画像（期待する画像）** を用意する必要があります。
「T-DASH」さんのWebサイトにチュートリアルがありますので、興味のある方はご覧ください。

https://service.valtes.co.jp/t-dash/function/tutorial/%e7%94%bb%e5%83%8f%e6%af%94%e8%bc%83%e6%a4%9c%e8%a8%bc%e3%82%92%e3%81%97%e3%82%88%e3%81%86

画像比較を「T-DASH」のテストケース内で検証することになるため、期待画像も「T-DASH」上でスクリーンショットを取得しておくのがよさそうです。
「T-DASH」の動画定義にスクリーンショットを取得する機能がありますので、この機能を使っていきます。

「T-DASH」を起動し、　**プロジェクトを作成** します。
![chrome_zyXRyLI10s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/654524f0-badd-1742-fd25-634660c89688.png)
![chrome_rCs54sRKIq.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/d20a356e-5131-a2cf-637c-c3aa7059386e.png)

テストプロジェクトを選択し、 **テストシナリオを作成** します。
![chrome_Agzi78TlTx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/35ff761f-7ec6-b264-cc03-2ed87a732ec5.png)

テストシナリオを選択し、 **テストケースを作成** します。
![chrome_IzAXeki9m3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/6d45febb-2436-cff9-0439-4797e70e7b30.png)

テストケースはこちらです。
1行目：期待結果画像となるダイスロール結果を表示する画面を（画面名： **「ダイスロール結果」** とします）ブラウザで開きます。
2行目：画面のスクリーンショットを取得します。

![chrome_C0XixU6Scc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/75a1b016-8917-0a5f-6a95-6869c0b95219.png)
![gOjA4vWX12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/e884ce3a-43cd-6e65-1b15-0c0202590dd2.png)
![chrome_2OlkqL5DtD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/22722553-2078-3a03-dd1a-cf4e7e324a80.png)

テストケースを入力したら保存します。
次に **画面定義を設定** していきます。
「画面定義」をクリックし、画面名：　**「ダイスロール結果」** を選択します。
**「URL」** に **WebAPIのURL（リスクエスト先URL+ダイスロールパラメーター）を入力** します。
※詳細の説明は割愛しますが、今回はTRPGのゲームシステム「新クトゥルフ神話TRPG（Cthulhu7th）」を指定し、1D100（1個の100面ダイスを転がす）をダイスロールしています。
![chrome_4BVPb6JM3I.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/7643ad39-8c5e-fdf8-3c29-be8c741a165e.png)


画面定義を保存します。
これで期待画像を取得する準備ができました。

さて、それでは **テストケースを実行** していきましょう。
テストシナリオのチェックボックスを有効にして、再生ボタンをクリックするとテストケースが実行されます。
![chrome_aJIl9lveTa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/c75d5c9f-0f7a-46b5-9842-c7906bcf446c.png)

テストが成功したら **テストレポート** を開きます。
![chrome_LNPabZ1Ogg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/f4e2441d-d688-9320-536e-59b2f291b428.png)

ちょっと小さくて見づらいですがテストレポートの下部にスクリーンショットのサムネイルが表示されています。
サムネイルをクリックし、画像を表示して保存（ **「D:\期待画像.png」** ）します。
![chrome_rAYiBSEtae.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/5df20e02-b25f-7858-4437-82fdb89207a6.png)

**◆ 期待画像「D:\期待画像.png」**
![期待画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/a11a45e4-1c0e-66c1-b4f1-b34b401c1a32.png)

これで期待画像の準備が完了です。

## 期待画像と、テスト実行で取得したテスト結果画像を比較し、差分を検証する

それでは **テスト用のテストケースを作成** していきます。
![chrome_qNUFYndDn4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/2e6b2198-2288-ae49-f517-809f6df3f973.png)

テストケースはこちらです。
1行目：テスト対象となるダイスロール結果を表示する画面を（画面名： **「ダイスロール結果」** とします）ブラウザで開きます。（ **「期待画像のスクリーンショットを取得するテストケース」の1行目と同じ** ）
2行目：画面比較の動作を指定し、 **期待画像のパスをフルパス** で指定します。
3行目： **画像比較の一致率を指定** します。 **今回はダイスロールによって結果がコロコロ変化するため、適当に50％** にしてみました。

![chrome_8HEdh9HdxX.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/b4b5283a-7933-70c8-c376-f8e79ad94550.png)
![chrome_DCFuCSf7Zg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/a0b345cb-311e-300a-f809-569bf0ff1eb9.png)

テストケースを設定したら保存します。
**テストケースを実行** していきます。
**「期待結果取得用のテストケース」のチェックをOFF** にして、 **「画像検証のテストケース」をON** にして、テストを実行します。

![chrome_UfWmFgq7UR.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/29be1e68-c2d5-2f8a-3e61-574f737de10d.png)

テストが成功しました。 **テストレポートを開いて確認** します。

![chrome_zsWp5IgD01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/61b2e0b9-48b8-6842-e2a5-de8271287621.png)

テストケースの下部に、 **期待画像、テスト結果画像と、両方の差分画像のサムネイル** が横並びに表示されています。

![chrome_Fv0Wguzu6e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/9e1e00d7-f99a-edc1-fcbb-0e6486a81626.png)

**◆ テスト結果画像**
![テスト結果画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/3cf4166c-95a8-9c3d-5d11-379fb846c2eb.png)

**◆ 差分画像**
![差分画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302008/d0ca6e8b-8423-20c0-f9e4-3d5481745896.png)

テストは成功しましたが、え～っと…差分画像の背景色と文字の色が同系色でよくわからないですね……。
※画像ファイルをダウンロードして拡大表示していただくと差分が確認できます。

# まとめ

今回はE2Eテスト「T-DASH」の画像比較テストについてレポートしてみました。
試してみて、いろいろと発見がありましたらので、まとめていきます。

- 画像比較のテストはできる
- 外部のライブラリに頼らず **標準機能で1時間程度で実装** できたのはスゴイと思う！
- 差分画像の色設定（差分がない箇所は黒の塗りつぶしで、差分箇所は白の塗りつぶし）が出来ないため、 **画像によってはかなり見づらい**
- **フルスクリーンでの比較しか出来ないのは使いづらい。** 画面定義した要素名をターゲットとして比較できないと、ノイズ（テスト対象外の要素）が映り込んでしまう場合があり、テストにならない
    - 今回は画像上部の文字列部分のみ比較検証したかったのですが、フルスクリーンで画像比較しているため、画像一致率はほぼ一致（95%以上は一致するのでは？）する結果になるかと思います。そのため、今回ように **特定領域のみに絞って比較したい場合はには不向き** だと思います。

テストとしては成功したので目的は達成できましたが、 **実用で使えるシーンは限られる** と思いました。
特に最後に記述した特定要素（特定領域）での画像比較ができないとちょっとキツイかもしれません。
**フルスクリーンでノイズが入りこない条件でテスト実行できる場合は活用できる機会がありそうですね。**

画像検証はまだまだ課題が多い分野と思いますので、これからの開発に期待していきたいですね。
最後まで読みくださいましてありがとうございました。