【Unity】効率よくアセットバリデーションを作成するためのTestRunnerの活用法


地味に時間のかかるアセットバリデーション開発。本記事ではUnityが無料で提供するTestRunnerを使えば効率よく作れるのではないか?という自分的にも挑戦的な記事になっています。

準備

  1. Test Frameworkのインストール
  2. バリデーションするアセットの用意

1.Test Frameworkのインストール

TestRunnerを使用するために、PackageManagerからTest Frameworkをインストールしておきます。

コンパイルが成功したらWindow > General > Test Runner > Test RunnerでTest Runnerウィンドウを表示しておきます。

2.バリデーションするアセットの用意

今回は200個のScriptableObject(1001.asset~1200.asset)がバリデーション対象です。
格納先はどこでも良いですが、Assets/AssetBundlesフォルダ配下に追加します。(フォルダ名に制限はありません)

これで準備は完了です。

バリデーション処理の流れ

  1. System.IO.Directory.GetFilesメソッドでアセットパスの配列を取得
  2. AssetDatabase.LoadAssetAtPathメソッドでアセットを1つずつロード
  3. ロードしたアセットをバリデーション処理に通す
Assert.IsNotNull(obj, "Invalid obj is null.");

上のサンプルコードのようにバリデーションに引っかかったら(失敗したら)、その理由をAssertの第2引数で出力します。

実際のコード

  • TestRunnerから呼ばれるエントリーポイント
  • バリデーション処理を記述したメソッド

上記の2つの構成になっています。

TestRunnerから呼ばれるエントリーポイント

AssetTest.cs
/// <summary>
/// TestRunnerから呼ばれるエントリーポイント
/// </summary>
[Test]
public void AssetValidate()
{
    // Assertで処理を止めないようにする
    Assert.raiseExceptions = false;

    var assetDirectoryPath = "Assets/AssetBundles/";
    var filePaths = Directory.GetFiles(assetDirectoryPath, "*.asset");

    foreach (var path in filePaths)
    {
        Validate(path);
    }
}

バリデーション処理を記述したメソッド

AssetTest.cs
/// <summary>
/// 各ファイルごとに実行するバリデーション処理
/// </summary>
/// <param name="path">ファイルパス</param>
/// <returns>falseなら失敗 / trueなら成功</returns>
private void Validate(string path)
{
    var fileName = Path.GetFileName(path);
    // アセットをロード
    var asset = AssetDatabase.LoadAssetAtPath<QuestAsset>(path);

    // アセット存在テスト
    Assert.IsNotNull(asset, $"{fileName} => asset is null");

    // ID未記入テスト
    Assert.IsFalse(string.IsNullOrEmpty(asset.id),
        $"{fileName} => ID is null or empty");

    // 命名規則テスト
    Assert.IsFalse(asset.id.IndexOf("A", StringComparison.Ordinal) != 0,
        $"{fileName} => The naming conventions are different. : {asset.id}");
}
  • アセット存在テスト
  • ID未記入テスト
  • 命名規則テスト

3種類のバリデーションを用意しました。
Assertの各メソッドの第2引数は失敗時に出力されます。
失敗時の理由を丁寧に書くことで、その後の修正作業の効率が上がります。

TestRunnerから実行

Run AllまたはRun SelectedをクリックしてTestRunnerを実行します。


失敗したテストに関しては、事前に書いておいた失敗の理由が出力されます。

TestRunnerを使うメリット

  • [Test]アトリビュートを定義するだけで簡単にTestRunnerウィンドウにテストを追加でき、簡単にテストを実行することが出来る
  • バリデーションをTestRunnerに共通化しておくと後からジョインしたメンバーが把握しやすい
  • TestRunner自体がPackageなので簡単にインストール可
  • テストをコマンドラインから実行できるのでワークフローが組みやすい(GithubActionsなど)

個人的には上記のようなメリットがあると考えています。

Assertを使用するときの注意点

TestRunnerでよく使用されるAssertメソッドをバリデーション処理側に使用すると、デフォルト状態ではテストの失敗時に後続処理が止まります。

これではテスト結果の全貌が見えなくなり開発効率が低下しますので、以下の1行を追加すると良いです。

Assert.raiseExceptions = false;

こうするとテストに失敗しても処理は継続されます。

まとめ

TestRunnerを使って簡単なアセットバリデーションを作ってみました。
成功・失敗(+失敗の理由)をログ出力する程度のバリデーションであれば、記述するコード量を減らす1ことができ、開発の効率化観点でTestRunnerは有用だと思いました。

TestRunnerはバッチモードで実行できますので、例えばジェンキンスでバリデーションを走らせて結果をSlack通知させるという活用が可能です。

今回は簡易的なバリデーションでしたが、実践では複雑な実装になります。
いかにバリデーションをし易くするかということを考えて設計・実装することが大事になります。
これはTestRunnerを使用するしないに関わらず必要な視点です。

環境

  • Unity2019.4.4f1
  • Test Framework 1.1.14

今回のサンプル全ソースは以下にアップしています。
https://github.com/baobao/unity-test-runner-asset-test-shortcode


  1. EditorWindowの記述やテスト判定のView処理を書く工数は下げられそうという意味