Zenn
🌵

Vitest HTML Reporter + Firebase Hosting + GitHub Actionsでテスト結果を出力したい!

2025/02/06に公開
1

こんにちは、Nofiです。

今回はテストカバレッジを視覚的にわかりやすく見られるようにしたお話です。

個人的に作っていたお買い物リストアプリについに単体テストを導入し、GitHub Actionsで自動テストを行なっているのですが、テスト項目をHTMLに出力して見やすくできるときいてやってみました。

単体テストにはVitest + jsdom + Testing Library(React Testing Library、jest-dom、user-event)を使っています。
テストの導入はこちらから↓
https://zenn.dev/nofi/articles/642220a5ae7bab

VitestのHTML Reporter

「テスト項目を外部に出力したい」と思って調べているとVitestのhtml reporterなるものが見つかりました。
JSON形式やHTML、GitHub Actionsでのレポート出力などができるようです。
https://vitest.dev/guide/reporters#html-reporter

今回はHTML出力でやってみました。

@vitest/uiパッケージが必要らしいのでインストールします。
インストールコマンド

pnpm i -D @vitest/ui

HTML出力する

1. アプリ直下に出力用のファイルを作成

例:docs/test-report/index.html

2. vitest.config.tsにレポートの設定を追加

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    reporters: ['default', 'html'],
    outputFile: {
      html: './docs/test-report/index.html' 
    }
  }
});

・reporters: ['default', 'html']で、標準の出力+HTMLを生成
・outputFileをhtmlに設定して、レポートを出力するディレクトリ(例:docs/test-report)を指定

3. Vitest UIのコマンドを実行

vitest --ui

GitHub Pagesにdeployする予定が、privateリポジトリなのでできず

GitHubのリポジトリごとにGitHub Pagesにページをdeployできるのですが、privateリポジトリは課金が必要なので諦めました。

Firebaseで複数サイトHostingをやってみることに

今回のアプリはFirebaseでHostingしているため、同じプロジェクトから複数Hostingできればいいなあと思っていたら、できました!

公式の案内はこちらから↓
https://firebase.google.com/docs/hosting/multisites?hl=ja

以下、Firebaseのプロジェクト内で複数のサイトをHostingする手順です。

1. 既存サイトのSITE_IDを確認

SITE_IDは、Firebase Hostingの一意の識別子です。複数のホスティングサイトを管理する際に使用します。デフォルトはFirebaseプロジェクトIDです。(例: todo-list-1234)。
下記のコマンドで既存サイトのSITE_IDを確認できます。

firebase hosting:sites:list


このように、まずはデフォルトのFirebaseプロジェクトのIDが出ました。

2. 新しいSITE_IDを作成

下記のコマンドでテスト結果表示ページのSITE_IDを作成します。(例:test-result-1234

firebase hosting:sites:create SITE_ID

自分でわかりやすいSITE_IDを決めていいのですが、SITE_IDには次の要件があります。
・有効なホスト名ラベルであること(._ などを含めることはできない)
・30 文字以下
・Firebase内でグローバルに一意

作成できているかは、最初に使ったこちらのコマンドで確認できます。

firebase hosting:sites:list


ここまでで2つ目のサイトのSITE_IDができています。

3. 作成したSITE_IDにTARGET_NAMEを適用

TARGET_NAMEとは、Firebase CLI内で使用する任意の識別名で、自由に命名可能(例: "app""test-result")。
下記のコマンドでSITE_ID(例:test-result-1234)にTARGET_NAME(test-result)を適用します。

firebase target:apply hosting TARGET_NAME SITE_ID

※ここでデフォルトのFirebaseプロジェクト名に任意のTARGET_NAMEを設定しておくと、分けてHostingするときに便利です。

4. firebase.json にテスト結果ページのターゲット設定がされているか確認

"hosting"の中が配列になっていて、targrtがデフォルトのFirebaseプロジェクトとテスト結果用の2つ設定されているか確認します。
"public"にはdeployするファイルがあるディレクトリを指定します。ディレクトリを間違うとdeployできなかったりエラーになるのでよく確認してください。

{
  "hosting": [
    {
      "target": "todo-list-1234",
      "public": "./app"]
    },
    {
      "target": "test-results",
      "public": "./docs/test-report",
      "ignore": ["**/.*", "**/node_modules/**"]
    }
  ]
}

実際のfirebase.json

5. .firebasercも2つのターゲットが指定されているか確認

{
  "projects": {
    "default": "todo-list-1234"
  },
  "targets": {
    "todo-list-1234": {
      "hosting": {
        "todo-list": ["todo-list-1234"]**,
        "test-result": ["test-result-1234"]**
      }
    }
  }
}

実際の.firebaserc

6. デプロイ

どのtargetをデプロイするか指定してコマンドを実行すると、テストファイルの方だけをdeployできます。

firebase deploy --only hosting:TARGET_NAME

デプロイできてもfirebaseエラーが起きていたりします。
私もindex.htmlがないとFirebaseエラーが出てディレクトリ確認してもエラーで悩みましたが、なんとリロードしたら見れました。chromeはキャッシュが強いらしいので修正したらまずハードリロードをした方がいいかもしれません。(切実)

GitHub ActionsのWorkFlowにテストとデプロイを追加

テストを実行してできたテスト結果のファイル(test-result)をデプロイしたい!というところで悩みましたが、GitHubで提供されている2つのactionで解決できました。

actions/upload-artifact@v4actions/download-artifact@v4でテスト実行の成果物をartifactとしてアップロードおよびダウンロードできます。
これでjob間でテスト結果のファイルを共有できます。

以下はworkflowの例です。

name: Deploy to Firebase Hosting on PR
on: pull_request

permissions: 
  checks: write
  contents: read

jobs:
  build_and_preview:
    if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}'
    runs-on: ubuntu-latest
      
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: v22.13.0
      - uses: pnpm/action-setup@v3
        with:
          version: 9
          run_install: true
      - name: Build
        run: pnpm build

      # Vitest を使ってユニットテストを実行
      - name: Run Vitest
        id: run-vitest
        run: pnpm vitest --ui
        env: 
          CI: true
        continue-on-error: true 

      # ファイルのアップロード
      - name: Upload test results as an artifact
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: docs/test-report

      # ファイルのダウンロード      
      - name: Download a single artifact
        uses: actions/download-artifact@v4
        with:
          name: test-results
          path: docs/test-report

      - name: Show downloaded files (debug)
        run: ls -la docs/test-report
      
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_TODO_LIST_1234 }}'
          projectId: todo-list-1234

1. テストの実行

テストをrun: pnpm vitest --uiで実行し、そのテストが通っても通らなくても出力できるようにcontinue-on-error: true を設定する。

2. actions/upload-artifact@v4によるアップロード

withにjob上で識別するための任意の名前と出力先のパスを設定し、ジョブが終了する前にデータをアップロードする。

3. actions/download-artifact@v4によるダウンロード

アップロードされたartifactをダウンロードできるのは、同じworkflowの実行中だけ。ファイルをダウンロードする際には名前で参照できる。

詳細はこちらを参照してください↓
https://docs.github.com/ja/actions/writing-workflows/choosing-what-your-workflow-does/storing-and-sharing-data-from-a-workflow

デプロイ内容の確認

最後に、CommitをPushした後、GitHubのActionsタブのdeploy Previewからテスト結果ページ(例:test-result)のURLに飛んで、テストのfailedが表示されていたら(もしくは成功/意図した画面になっていれば)完成です。

これで自動でテストしてその結果をデプロイしてくれます!

補足:workflowが落ちたように見せたい

今回はテストが通らなくてもデプロイするため、テスト失敗を一旦無視してworkflowをcontinueしました。
この場合workflowは正常に終了しているため、deploy先でテスト結果を確認できることを知らない人が「テスト通った!」と思う可能性がありますよね。
workflowが落ちたように見せる方法があったのでそちらも追記しました。

workflowの最後に以下を記述します。

- name: If failed unit test, exit 1
        if: steps.run-vitest.outcome == 'failure'
        run: exit 1

テストした時に失敗していたら「exit 1」を実行するフローです。

テストが通らなかった場合GitHub Actionsのマークが赤くなります。

workflowにはこのようにエラーが出ています。

まとめ

これでかなり見やすくなりました。Pushのたびに目を凝らしてどこで落ちたのか探すことがなくなって万々歳です!
エンジニアでない人が見ても、なんのテストがあってどれが失敗しているのかわかりやすくていいですね。

「テスト結果見やすくしたい!」という方や「自動でテスト結果を更新してほしい!」という方の参考になれば幸いです!

1

Discussion

ログインするとコメントできます