swift-snapshot-testing の画像差分表示を GitHub Actions + reg-cli + GitHub Pages で 実現する

こちらは、「[GENDA Advent Calendar 2024](https://qiita.com/advent-calendar/2024/genda)」 17日目の記事です。

https://qiita.com/advent-calendar/2024/genda
## はじめに

`swift-snapshot-testing` は、UIや画像ベースのテストを簡単に行える便利なスナップショットテストライブラリです。しかし、テストが失敗した際に画像の差分をわかりやすく表示する仕組みが標準で備わっていません。

そこで本記事では、`reg-cli` を使って差分レポートを作成し、それを `GitHub Pages` 上で簡単に確認できる仕組みを構築する方法を紹介します。

## 動作環境

- GitHub Actions
- GitHub Pages

が使える環境

## GitHub Actions で swift-snapshot-testing を実行

まず、`GitHub Actions` で `swift-snapshot-testing` を実行するワークフローを作成します。
※ `swift-snapshot-testing` の導入については省略します。


1. `.github/workflows/vrt.yml` を作成します
    ``` .github/workflows/vrt.yml
        name: vrt
        on:
          push:
            branches: [develop]
          pull_request:
          workflow_dispatch:
        
        env:
          DEVELOPER_DIR: "/Applications/Xcode_16.1.0.app/Contents/Developer"
          DEVICE_NAME: "iPhone 16 Pro,OS=18.1"
          APP_NAME: VrtApp
          SCHEME_NAME: VrtAppTest
        
        jobs:
          test:
            name: Run tests
            runs-on: macOS-14
            env:
              RESULTS_PATH: ${{ github.workspace }}/TestResults
              FAILURE_PATH: ${{ github.workspace }}/VrtAppTests/SnapshotTesting/__Snapshots__/Failure
              EXPECTED_PATH: ${{ github.workspace }}/VrtAppTests/SnapshotTesting/__Snapshots__
              EXPECTED_DIFF_PATH: ${{ github.workspace }}/.vrt/expected
              ACUTUAL_DIFF_PATH: ${{ github.workspace }}/.vrt/actual
            outputs:
              vrt_failure: ${{ steps.vrt.outputs.vrt_failure }}
            steps:
              - name: Checkout
                uses: actions/checkout@v4
        
              - name: Run tests
                run: xcodebuild test -project $APP_NAME.xcodeproj -resultBundlePath ${{ env.RESULTS_PATH }} -scheme $SCHEME_NAME -sdk iphonesimulator -destination "platform=iOS Simulator,name=$DEVICE_NAME"
    ```

2. このままだとスナップショットテストが失敗したことしかわからないので、`reg-cli` で差分レポートを生成し、`Artifacts` にアップロードする部分を追加します

    ``` .github/workflows/vrt.yml
          - name: Copy diffable directories
            id: vrt
            shell: bash
            run: >
              if [ -z "$(ls ${{ env.FAILURE_PATH }})" ]; then
                echo "Failure snapshots not found."
                exit 0
              fi  
    
              echo "vrt_failure=true" >> $GITHUB_OUTPUT
    
              mkdir -p ${{ env.EXPECTED_DIFF_PATH }}
              mkdir -p ${{ env.ACUTUAL_DIFF_PATH }}
    
              for dir in ${{ env.FAILURE_PATH }}/*/; do
                if [ -d "$dir" ]; then
                  dir_name=$(basename "$dir")
                  cp -r "${{ env.EXPECTED_PATH }}/$dir_name" "${{ env.EXPECTED_DIFF_PATH }}/$dir_name"
                  cp -r "${{ env.FAILURE_PATH }}/$dir_name" "${{ env.ACUTUAL_DIFF_PATH }}/$dir_name"
                fi
              done
    
          - name: Generate reg-cli report
            shell: bash
            run: >
              npx reg-cli \
              ${{ env.ACUTUAL_DIFF_PATH }} \
              ${{ env.EXPECTED_DIFF_PATH }} \
              .vrt/diff \
              -R .vrt/index.html \
              -J .vrt/index.json \
              --ignoreChange
    
          - name: Upload pages
            uses: actions/upload-pages-artifact@v3
            with:
              path: .vrt
    ```

3. `Artifacts` から ダウンロードして差分レポートを確認できるようになりました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221749/e19b48f9-6871-b79e-6624-78e56f677101.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221749/15601130-cfb6-a504-09b0-7e21e36f94ed.png)


## GitHub Pages で表示する

差分レポートを毎回ダウンロードする手間を省くため、差分レポートを `GitHub Pages` にホスティングします。

1. `GitHub Actions` から デプロイできるように `GitHub Pages` の設定を変更します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221749/fba24cde-820b-aa21-b2e3-b4478d9f0542.png)

2. `GitHub Pages` にデプロイするワークフローを追加します
    ``` .github/workflows/vrt.yml
      deploy:
        needs: vrt
        permissions:
          pages: write
          id-token: write
        environment:
          name: github-pages
          url: ${{ steps.deployment.outputs.page_url }}
        runs-on: ubuntu-latest
        if: failure()
        steps:
          - name: Configure Pages
            uses: actions/configure-pages@v4
          - name: Deploy to GitHub Pages
            if: ${{ needs.test.outputs.vrt_failure == 'true' }}
            id: deployment
            uses: actions/deploy-pages@v4
            with:
              preview: true
    ```


## 差分レポート表示

`reg-cli` の機能を使って様々な方法で差分表示できるようになりました:v:
![reg-cli-all.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221749/e5d2cf97-6290-879f-1d41-f5b67208e1a2.png)


![combined_image_horizontal.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221749/951560fd-3906-f35d-1223-d914aec5b8c0.jpeg)


良いお年を🎄✨

## 参考
https://github.com/pointfreeco/swift-snapshot-testing

https://github.com/reg-viz/reg-cli

https://github.blog/changelog/2022-07-27-github-pages-custom-github-actions-workflows-beta/

https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages