概要
この記事には、GitHub Actions で Unity のテストを自動化する方法・特定のブランチはテストが通らないとマージできないようにする方法が書いてあります。また、おまけとして unitypackage をコマンドラインで作る方法も載せています。
背景
kumaS-nu/NuGet-importer-for-Unity
↑のプロジェクトを作ると決めた際、しっかりしたプロジェクトにしたいよね。と思い、自動テストを組み込むことにしました。また、このプロジェクトは以下の記事で宣伝しています。
Unity のプロジェクトに NuGet のパッケージをインポートするエディタ拡張を作ったよ
事前準備
GitHub Actions で Unity のテストを自動化するからには、Unity Test Framework を用いたテストがあるリポジトリを用意します。
Unity Test Framework
Unity2018 では Unity Test Runner と呼ばれていましたが、Unity2019 以降では Unity Test Framework というパッケージとなっています。どちらも(たぶん)変わりません。
ここに関しては本題ではないので軽く説明するだけに留めておきます。
モード
Unity Test には Editor Mode Test と Play Mode Test があります。これはそのまんまで、Play Mode Test では Unity を再生してテストをし、Editor Mode Test はエディタ上でテストをします。Play Mode Test は再生モードに移行するタイムラグがあるため、Editor Mode Test に比べて遅いため Editor Mode Test で充分なテストは Editor Mode Test でした方がよいです。
テストを作る
テストはデフォルトでないアセンブリ(Assembly-CSharp や Assembly-CSharp-Editor でない)に書いてないといけません。といっても、Unity Test Runner のウィンドウの Create ** Test Assembly Folder をクリックすればいいだけですが。作ったフォルダの中に以下のようなテスト作ります。
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
public class SampleTest
{
[OneTimeSetUp]
public void SetUp()
{
//このクラスが作られるときに一度だけ実行される。
}
[UnityTest]
public void SampleTest1()
{
//ここにテストを書く
var actualString = "Test string";
Assert.That(actualString, Is.EqualTo("Test string"));
}
[UnityTest]
public IEnumerator FindRequiredPackagesTest01()
{
//複数フレーム間にわたりそうなときはこちらを使う。非同期はこちらをうまく使う。
var waitSecond = 1;
yield return new WaitForSeconds(1);
Assert.That(waitSecond, Is.EqualTo(1));
}
[OneTimeTearDown]
public void TearDown()
{
//このクラスが削除されるときに一度だけ実行される。
}
}
実際にテストを作るときは以下の参考資料を元にすればいいと思います。
参考資料
- 【Unity】Unity Test Runner(Test Framework)入門 - インストールから基本的な使い方・注意点まとめ
- About Unity Test Framework - Unity 公式
- NUnit Documentation Site - NUnit 公式
GitHub Actions で Unity のテストをできるようにする
では本題です。といっても実は GitHub Actions のマーケットプレースに Unity のテストをするアクションを公開されているのでその使い方の説明です。今回使うのは以下の二つです。(なお、どちらも Unity 公式ではないです。また、この記事を書いてる時点でバージョン 2 のプリリリースがあるのですぐ使い方が変わりそうで不安。)
Unity - Request Activation File
Unity は使うのにライセンス認証が必須です。これは Unity をアクティベーションするためのファイルを作ってくれるアクションです。この一連のアクションを開発している Game-CI は v2 以降は game-ci/docker を使用していているとのことですが、それ以前は、その前のプロジェクトのものを使用しているため、使える Unity のバージョンに制限があることがあります。
プライペートなリポジトリでも作って、以下のような Action を作成します。
name: Acquire activation file
on: [push]
jobs:
activation:
name: Request manual activation file
runs-on: ubuntu-latest
steps:
- name: Request manual activation file
id: getManualLicenseFile
uses: webbertakken/unity-request-manual-activation-file@v1.2
with:
#テストで使用する Unity のバージョンを指定。デフォルトは2019.2.11f1。v2未満は 2019.4 系は 14f1 までしかなかった。
unityVersion: 2019.4.14f1
- name: Expose as artifact
uses: actions/upload-artifact@v2.2.2
with:
name: ${{ steps.getManualLicenseFile.outputs.filePath }}
path: ${{ steps.getManualLicenseFile.outputs.filePath }}
これを Actions に登録(コミット)すると、そのプッシュによってこの Action が走り、しばらくするとアーティファクトとして .alf ファイルがアップロードされます。そのファイルをダウンロードし、https://license.unity3d.com/manual にて手動アクティベートをして生成された .ulf ファイルをダウンロードします。
これらのファイルはライセンス情報を含むので、公開しないように。(・`ω´・@)<ダメ!情報漏洩!
公式のドキュメントはこちら Activation - Game CI
Unity - Test runner
このアクションを使用して Unity のテストを走らせます。
Unity のアクティベーションファイルを設定する
先駆者たちはこの部分でどう安全するかと苦労していましたが、このアクションは非常に簡単です。
以下のように、リポジトリの Settings の Secrets にある New repository secret というボタンをクリックします。
そして、Name になんかいい感じの名前(私は UNITY_LICENSE にしたけど)を入れ、Value に .ulfファイルの中身をコピペします。
これで Action からしか見えず、暗号化されたライセンスが安全に追加できます。
テストを走らせるアクションを作る
以下のようなアクションを作ると、テストを走らせれます。
name: Test
on:
# プルリクが作られた・更新されたとき
pull_request:
types: [opened, synchronize]
# mainブランチがプッシュされたとき
push: { branches: [main] }
env:
# さっき決めたいい感じの Secrets の名前
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
jobs:
testAllModes:
name: Test in ${{ matrix.testMode }} on version ${{ matrix.unityVersion }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
projectPath:
# 走らせるプロジェクトのパス
- NuGetImporterForUnity
unityVersion:
# 使う Unity のバージョン
- 2019.4.14f1
testMode:
# 実行するテストのモード
- editmode
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}
restore-keys: |
Library-
- uses: webbertakken/unity-test-runner@v1.7
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
id: tests
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: ${{ matrix.testMode }}
artifactsPath: ${{ matrix.testMode }}-artifacts
もし、テストがすべて通ったら Action は成功したという風になり、失敗したものがあれば Action は失敗したという風になります。また、これには書きませんでしたがアーティファクトをアップロードするようにすればテストの結果を見ることができます。
公式のドキュメントはこちら Test runner - Game CI
テストを通らないとマージできないようにする
プルリクエストに関係するアクションを作るだけでプルリクエストを作ったときにいい感じにテスト結果を出してくれるのですが、せっかくテストを作ってもテスト結果を無視してマージされたら意味ないです。(どっかのうっかりさんはときどきやるんです (๑´ڡ`๑)<てへ//)
なので、ブランチの保護もしておくとよりよいです。ということでその説明をします。
以下のように、リポジトリの Settings の Secrets にある New repository secret というボタンをクリックします。
そして、branch name pattern に保護したいブランチの名前を入れ、Require status checks to pass before merging・Require branches to be up to date before merging・そしてパスしなければならないテストにチェックを入れ、下の方にある Create ボタンをクリックするとブランチの保護ができます。
参考資料
おまけ
リリースする前に少し確認したかったので、私は Actions で unitypackage を作りませんでしたが、以下のようなコマンドで作ることができます。
path/to/Unity/Editor.exe -projectPath path/to/your/project -batchmode -nographics -exportPackage "path/your/want/to/export" "path/to/export" -quit
なお、-exportPackage
の後の二つのパスは、-projectPath
からの相対パスです。
また、GitHub Actions でビルドしたければ Builder - Game CI を使うといいと思います。私は使ってないので何も言えないですが。