Zenn
👻

C# 自動テストの構築方法 Github Actions x xUnit

2025/03/23に公開

はじめに

C# で単体テストを導入したあと、「Push したタイミングで自動でテストが走ってくれたら便利だな」と思ったことはありませんか?

本記事では、GitHub Actions を使って、xUnit による C# プロジェクトのテストを自動化する方法を、実際のファイル構成や yml 記述例とともに解説します。

  • GitHub 上で CI(継続的インテグレーション)を試してみたい
  • xUnit のテスト実行を自動化したい
  • テスト結果をブラウザで確認できるようにしたい
  • ワークフローファイル yml の具体的な書き方を知りたい

といった方に向けた内容になっています。

筆者自身、C# × GitHub Actions の組み合わせに初めて触れたときは、仮想マシン特有のエラー、レポート出力の設定などにかなり手こずりました。

環境が変わればすぐにエラーが発生するかと思います。

ですので、本記事ではコードの提示だけでなく、個別の解説も丁寧にしてみました。
CI 初心者の方でも安心して導入できる...はず。

解説に使用したコードはこちらで公開しています。

https://github.com/ryuryu333/csharp_ci_sample


xUnit の導入がまだという方は、以下の記事からご覧ください。

https://zenn.dev/trifolium/articles/c2fa1ded4d54ac

前提

  • Visual Studio 2022 を使用し、C# でアプリケーションを開発している
  • xUnit による単体テストの構築が完了している
  • ソースコードは GitHub 上で管理している
  • Windows 向けアプリの開発であり、Windows 環境での CI 実行を想定している

ubuntu-latest など Linux 仮想マシンでも同様の構成は可能ですが、パス記述、依存関係、レポート設定など、環境に合わせた調整が必要になります。

記事内で使用するサンプルソリューションの構成は以下の通りです:

your_repository/
├── .git/
└── MyConsoleApp/

MyConsoleApp/
├── MyConsoleApp/
│   ├── Calculator.cs    // テスト対象のクラス
│   └── Program.cs
└── MyTest/    // xUnit 単体テスト用プロジェクト
     └── CalculatorTest.cs

ソリューション構成

参考サイト

https://docs.github.com/ja/actions/use-cases-and-examples/building-and-testing/building-and-testing-net

https://docs.github.com/ja/actions/writing-workflows/workflow-syntax-for-github-actions

ワークフロー ファイル(yml) の作成

GitHub Actions を使ってテストを自動化するには、.github/workflows/ フォルダにワークフローファイル(test.yml)を作成する必要があります。

以下のようなディレクトリ構成になるように準備しましょう。

your_repository/
├── .git/
├── .github/
│   └── workflows/
│       └── test.yml
└── MyConsoleApp/

解説の進め方

test.yml に記述する内容は少し長くなります。
「セクションごとに個別の解説」→「最後に全体の完成コードを提示」という流れで説明していきます。

1. name: ワークフロー名の定義

GitHub Actions 上で表示されるワークフローの名前を指定します。

test.yml
name: .NET Test

2. on: トリガーの定義

どのタイミングで GitHub Actions を起動させるかを指定します。

多数の設定が用意されているので、使い道が多そうなモノをピックアップして紹介します。

  • main ブランチ、及び、develop/ 以下のブランチに対する push
  • main ブランチに対する pull_request
test.yml
on:
  push:
    branches:
      - main
      - 'develop/**'
  pull_request:
    branches:
      - main
  • C# のコード .cs が含まれる push
test.yml
on:
  push:
    branches:
      - main
    paths:
      - '**.cs'
  • docs ディレクトリ外のファイルが含まれる push
test.yml
on:
  push:
    branches:
      - main
    paths-ignore:
      - 'docs/**'

3. jobs: 実行する処理の定義

実際に行う処理(ビルドやテストなど)を記述するセクションです。
内容が最も長くなる箇所でもあります。

4. build: 実行環境(OS)の定義

どのOSでジョブを動かすかを指定します。
特に理由がなければ ubuntu-latest がおすすめです。

今回は Windows 用のアプリなので、windows-latest を指定します。

test.yml
jobs:
  build:
    runs-on: windows-latest

2025年3月現在、指定可能な環境:

OS タグ名
Linux ubuntu-latestubuntu-24.04ubuntu-22.04ubuntu-20.04
Windows windows-latestwindows-2025(プレビュー)、windows-2022
macOS macos-13macos-14macos-15(Apple Silicon)

https://docs.github.com/ja/actions/writing-workflows/workflow-syntax-for-github-actions#プライベート-リポジトリの標準の-github-でホストされたランナー

5. steps: 実行ステップの定義

step に処理を記述します。
- name: が処理の区切り・説明となります。

test.yml
steps:
  - name: 処理の説明(任意)
    uses: または run: を指定

5-1. コードのチェックアウト

GitHub のリポジトリ内容を仮想マシンに取り込みます。ほぼ全てのワークフローで必要です。

test.yml
- name: Checkout repository
  uses: actions/checkout@v3

5-2. .NET SDK のセットアップ

開発に使っているバージョンに合わせて dotnet-version を指定します。

test.yml
- name: Setup .NET 5.x
  uses: actions/setup-dotnet@v4
  with:
    dotnet-version: '5.x'

5-3. 依存関係のインストール

*.csproj に記載された NuGet パッケージを復元します。

working-directory: にて ソリューションファイル .sln があるディレクトリを指定しています。

test.yml
- name: Restore dependencies
  run: dotnet restore
  working-directory: ./MyConsoleApp

5-4. ビルド

事前に dotnet restore で依存関係を解決しているため、ここでは --no-restore を付けてビルドのみを実行します。

test.yml
- name: Build
  run: dotnet build --no-restore
  working-directory: ./MyConsoleApp

5-5. テストの実行

xUnit で単体テストを行い、結果を XML で出力させます。
ここで出力される test_result.xml は、次のステップで GitHub Actions 上に表示するための元データになります。

working-directory: にて テスト用のプロジェクトファイル .csproj があるディレクトリを指定しています。

test.yml
- name: Run xUnit tests
  run: dotnet test --no-build --logger:"xunit;LogFilePath=test_result.xml"
  working-directory: ./MyConsoleApp/MyTest

5-6. テスト結果の出力

前のステップで出力した test_result.xml をもとに、GitHub Actions 上にテスト結果を可視化します。
GitHub Actions の「チェック」画面上にテストの成功・失敗状況を表示できるようにします。

if: always() をつけることで、テストが失敗してもレポート出力がスキップされないようにします。

test.yml
- name: Publish test results as GitHub report
  uses: EnricoMi/publish-unit-test-result-action/windows@v2
  if: always()
  with:
      files: ./MyConsoleApp/MyTest/test_result.xml

https://github.com/EnricoMi/publish-unit-test-result-action

test.yml 全体の完成形

test.yml
name: .NET Test

on:
  push:
    branches:
      - main
      - 'develop/**'
    paths:
      - '**.cs'
      - '**.yml'
  pull_request:
    branches:
      - main

jobs:
  build:
    runs-on: windows-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Setup .NET 5.x
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '5.x'

      - name: Restore dependencies
        run: dotnet restore
        working-directory: ./MyConsoleApp

      - name: Build
        run: dotnet build --no-restore
        working-directory: ./MyConsoleApp

      - name: Run xUnit tests
        run: dotnet test --no-build --logger:"xunit;LogFilePath=test_result.xml"
        working-directory: ./MyConsoleApp/MyTest
      
      - name: Publish test results as GitHub report
        uses: EnricoMi/publish-unit-test-result-action/windows@v2
        if: always()
        with:
          files: ./MyConsoleApp/MyTest/test_result.xml

自動テストを行う前に

1. テスト結果のレポートについて

GitHub Actions のブラウザ上でテスト結果を可視化するため、先ほどの yml 設定ではレポート出力のステップを追加しました。

https://github.com/EnricoMi/publish-unit-test-result-action

今回は Windows 仮想マシンですので、マルチプラットフォーム(Windows / Linux / macOS)かつ複数言語をサポートしていた publish-unit-test-result-action を選びました。

他のレポート方法

以下の記事では、他のテストレポート出力手段についても紹介されています。

https://zenn.dev/bsyo/articles/73501b57355274

注意点:

  • 一部のツールは Ubuntu 専用 など、仮想マシンの種類に依存することがあります
  • 使用する言語(C#, Python, JavaScriptなど)やテストフレームワークに応じて、ロガーの指定や出力形式が異なります

2. ロガーの準備

publish-unit-test-result-action を使って xUnit のテスト結果を GitHub Actions に表示するには、XunitXml.TestLogger というロガーが必要です。

このロガーは、xUnit プロジェクトのテンプレートには含まれていないため、手動で追加インストールする必要があります。

インストール方法(Visual Studio 2022)

Visual Studio 2022 にてターミナルを開きます。

ターミナルの開き方

テスト用のプロジェクトに移動し、インストールコマンドを実行します。

PowerShell
your_repository\MyConsoleApp> cd MyTest
your_repository\MyConsoleApp\MyTest> dotnet add package XunitXml.TestLogger --version 6.1.0

https://www.nuget.org/packages/XunitXml.TestLogger

3. 権限設定

なぜ権限設定が必要か

GitHub Actions でテスト結果をブラウザ上に表示するには、GitHub が自動で発行するトークン(GITHUB_TOKEN)に「書き込み権限」が必要です。

この設定をしておかないと、テスト結果を表示しようとしても「403 Forbidden」エラーで失敗してしまいます。

そのため、あらかじめリポジトリの設定から 権限を Read and write に変更しておく必要があります。

設定方法

GitHub のリポジトリページを開いたら、上部の Settings タブをクリックします。

Actions > General をクリックします。

設定画面へのアクセス

下にスクロールし、Workflow permissions を探します。

Read and write permissions を選択し、Save を押します。

権限の設定

4. ビルドエラー対策

仮想マシンと日本語の相性が悪いです。

.cs のコード中に Console.WriteLine("日本語のログ"); があるとビルドエラーが起こります。

  • ログ出力には英語を使う
    • Console.WriteLine("This is Log");
  • 日本語の説明が必要な場合はコメントに記述する
    • // これは日本語の説明です は大丈夫です
具体的にどんなエラーが起きるのか?

Build 工程(Run dotnet build --no-restore)でエラーが発生します。

MyTest\CalculatorTest.cs(26,39): error CS1009: Unrecognized escape sequence

仮想マシンでコードがどのように認識されているかを確認してみます。

test.yml
- name: Show CalculatorTest.cs contents
  run: type MyTest\CalculatorTest.cs
  working-directory: ./MyConsoleApp

エラーが出ていた行を抜き出します。

出力
[Fact]
public void AddTestLog()
{
    Assert.Equal(3, _calculator.Add(1, 2));
    _output.WriteLine("���O��\���ł��܂�");
    Console.WriteLine("�������͕\������Ȃ�");
}

Console.WriteLine に記載した日本語が文字化けしています。

  • ログを表示できます
  • -> ���O��\���ł��܂�

ここに含まれている \Unrecognized escape sequence の原因だと思われます。

自動テストの実行

yml ファイルや各種コードを main ブランチに push してくだい。

テスト結果の確認

Actions から確認

GitHub のリポジトリページを開いたら、上部の Actions タブをクリックします。

Actionsの場所

ページには、直近で実行されたワークフロー(test.yml の処理)一覧が表示されます。

  • 正常終了:✅ 緑のチェックマーク
  • エラーあり:❌ 赤いバツ印

今回は、コミットメッセージが XunitXml.TestLoggerをインストール のものをクリックしてみます。

ワークフロー実行結果一覧画面

次の画面では、test.ymljobs: セクションで定義した build: が表示されます。
ここをクリックすると、その中で実行された各 steps: の詳細が確認できます。

ワークフロー画面

publish-unit-test-result-action を使用している場合、左側メニューに Test Results という項目が表示されます。
これをクリックすると、GitHub Actions 上でテスト結果を可視化することができます。

jobsの詳細画面

テストの実行結果が確認できます。

今回はシンプルな XML ロガーによるレポートを使用していますが、よりリッチな形式(HTML や PR コメントなど)での表示も可能です。

テスト結果画面

コミット欄から確認

テスト結果は Actions タブだけでなく、コミット一覧の画面からも確認できます。

    1. GitHub のリポジトリ画面で、Code タブを開きます
    1. 画面上部にある最新のコミット一覧から、確認したいコミットを見つけます
    1. コミットメッセージの下にある ☑ 2/2(チェックマークと数値) をクリックします
    • ☑ = ワークフローの成否
    • 2/2 は「2つのジョブ中、2つ成功」を意味しています
    1. 次の画面で、実行されたワークフロー(例:.NET Test build / Test Results (push))が一覧表示されます
    1. Details をクリックすると、GitHub Actions の詳細画面に遷移します
    1. テスト結果や各ステップのログを確認できます

コミット欄から確認

Github Actions 使用料について

プライベート リポジトリの場合、使用制限があります。
GitHub Free アカウントの場合、月当たり 2,000 分 を無料で利用可能です。

なお、パブリック リポジトリは無料です。

プラン 分 (月あたり)
GitHub Free 2,000 分
GitHub Pro 3,000 分
組織の GitHub Free 2,000 分
GitHub Team 3,000 分
GitHub Enterprise Cloud 50,000 分

OS によって実際の稼働時間に倍率がかかります。

オペレーティングシステム 分の倍率
Linux 1
Windows 2
macOS 10

無料枠が十分に大きいので、個人開発なら気にする必要はない気がしますが...。
頭の片隅で、ubuntu の方がコスパが良いと覚えておくと良いかもしれません。

無料枠を超過した場合

無料枠がリセット(月ごと)されるまで、GitHub Actions が実行されなくなります。

月ごとの請求のお客様の場合、アカウントには既定の使用制限として 0 米ドル (USD) が設定されます。これにより、プライベート リポジトリで、そのアカウントに含まれる容量を超える追加の時間 (分) やストレージが使われるのを防ぐことができます。 アカウントを請求書で支払っている場合、そのアカウントの既定の使用制限は無制限となります。

https://docs.github.com/ja/billing/managing-billing-for-your-products/managing-billing-for-github-actions/about-billing-for-github-actions#about-spending-limits

自身の利用状況を確認する方法

Setting を開きます。
Billing & Licensing > Overview をクリックします。

こちらの画面で使用料金が確認できます。

Settingの場所

Actionsの利用状況画面

Current included usageMore Details をクリックすると、残りの無料枠を確認できます。

無料枠の確認

おわりに

本記事では、C# プロジェクトに GitHub Actions を導入し、xUnit テストを自動実行・レポート出力する方法を解説しました。

CI による自動テストが導入できると、

  • プルリクエスト時に自動でテストが走り、安心してレビューできる
  • 小さなバグにもすぐ気づける
  • チームでの開発でも品質を保ちやすくなる

など、開発体験がぐっと良くなります。

今回ご紹介した構成は、必要最小限なものです。

  • テスト結果の HTML レポート化
  • カバレッジの可視化や PR コメントへの出力
  • 複数のターゲットフレームワークに対する並列テスト実行

などを組み合わせることで、より柔軟でパワフルな CI 構成へと拡張していくこともできます。

「まずは試してみたい」という方にとって、本記事がその第一歩になれば幸いです。

Discussion

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