うどんてっくメモ

技術的なメモをまったりと

【Unity】Build Profileのコンパイルテスト

はじめに

検証環境は以下になります。バージョンが違う場合には動作しない場合がありますので、ご留意ください。

  • Unity6000.0.34f1

Build Profileのコンパイルテスト

この記事で紹介されているプロジェクトのコンパイルテストについて、Build Profileでのテストのサンプルを作りました。

qiita.com

  • 現在のBuild Profileでのテスト
  • すべてのBuild Profileでのテスト

の簡単な実装を紹介します。

まずはPlayerBuildInterface.CompilePlayerScriptsにBuild Profileの情報を流し込みます。

#if UNITY_EDITOR
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Build.Player;
using UnityEditor.Build.Profile;

public static class BuildProfileCompileTestUtility
{
    /// <summary>
    /// コンパイルテスト
    /// </summary>
    public static ScriptCompilationResult Compile(BuildProfile profile, string output)
    {
        var option = new ScriptCompilationSettings
        {
            target = GetBuildTarget(profile),
            extraScriptingDefines = profile.scriptingDefines
        };

        return PlayerBuildInterface.CompilePlayerScripts(option, output);
    }

    /// <summary>
    /// リフレクション経由でのBuildTarget参照
    /// </summary>
    private static BuildTarget GetBuildTarget(BuildProfile profile)
    {
        var buildProfileType = typeof(BuildProfile);
        var buildProfileBuildTargetObject = buildProfileType
            .GetProperty("buildTarget", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
            ?.GetValue(profile);
        var buildTarget = (BuildTarget)buildProfileBuildTargetObject;
        
        Assert.IsNotNull(buildTarget);
        return buildTarget;
    }
}
#endif

Build Profileが本記事のUnityのバージョンではおおむねinternalでプロパティやメソッドが実装されているため、今回はリフレクションのパワーでBuildTargetを取得しています。

続いて、この処理を用いてテストを実装します。

#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Build.Profile;

public static class BuildProfileCompileTest
{
    private const string OutputPath = "Temp/BuildProfileCompileTest";
    
    /// <summary>
    /// 現在のBuildProfileでテスト
    /// </summary>
    [Test]
    public static void 現在のBuildProfileコンパイルテスト()
    {
        BuildProfileCompileTestUtility.Compile(BuildProfile.GetActiveBuildProfile(), OutputPath);
    }
    
    /// <summary>
    /// 管理しているすべてのBuildProfileでテスト
    /// </summary>
    [TestCaseSource(nameof(GetAllBuildProfiles))]
    public static void 全部のBuildProfileコンパイルテスト(BuildProfile profile)
    {
        BuildProfileCompileTestUtility.Compile(profile, OutputPath);
    }

    /// <summary>
    /// 管理しているBuildProfileの取得、今回はテンプレのディレクトリにまとまっている想定
    /// </summary>
    private static IEnumerable<BuildProfile> GetAllBuildProfiles()
    {
        var path = "Assets/Settings/Build Profiles";
        return AssetDatabase
            .FindAssets("t: BuildProfile", new[] { path })
            .Select(AssetDatabase.GUIDToAssetPath)
            .Select(AssetDatabase.LoadAssetAtPath<BuildProfile>);
    }
}

#endif

網羅的にBuild Profileのコンパイルを行う処理については、Build Profileがデフォルトだと「Assets/Settings/Build Profiles」に保存されるため、それらを取得してテストする方式を取りました。

テストするためのサンプルのBuild Profileを作ります。今回はPlatform2種類とScripting Defineを設定した1種類を用意しました。テストが通る前提のBuild ProfileとなるAndroidの何も設定していないBuild ProfileにSwitchします。

スクリプトは以下のサンプルを用意しました。

namespace Temp
{
    public class Sample
    {
#if UNITY_IOS || TEST_DEFINE
        // iOSプラットフォームかTEST_DEFINEが有効の際にエラーになる
        error;
#endif
    }
}

これを実行すると、狙い通りiOSのBuild ProfileとTEST_DEFINEをScripting Defineに設定したBuild Profileでテストがコケます。

Unity6からはこのようなテストを常設していくと、捗りそうです。