Skip to content
This repository has been archived by the owner on Mar 8, 2023. It is now read-only.

Commit

Permalink
insert test run support
Browse files Browse the repository at this point in the history
  • Loading branch information
KleinerHacker committed Jan 26, 2022
1 parent 8d5b91b commit 8f5c947
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 50 deletions.
9 changes: 9 additions & 0 deletions Scripts/Runtime/Assets/BuildingSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public static BuildingSettings Singleton
[SerializeField]
private bool showFolder = true;

[SerializeField]
private bool runTests = true;

[FormerlySerializedAs("targetName")]
[SerializeField]
private string appName;
Expand Down Expand Up @@ -86,6 +89,12 @@ public bool ShowFolder
internal set => showFolder = value;
}

public bool RunTests
{
get => runTests;
internal set => runTests = value;
}

#endregion

#region Builtin Methods
Expand Down
8 changes: 4 additions & 4 deletions Scripts/Runtime/Provider/BuildingToolbar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ static void OnToolbarGUI()

GUILayout.Space(5f);

BuildingSettings.Clean = GUILayout.Toggle(BuildingSettings.Clean, new GUIContent("Clean", "Clean complete build cache"), ToolbarStyles.toggleStyle);

BuildingSettings.Clean = GUILayout.Toggle(BuildingSettings.Clean, new GUIContent(EditorGUIUtility.IconContent("Grid.EraserTool").image, "Clean complete build cache"), ToolbarStyles.commandButtonStyle);
BuildingSettings.ShowFolder = GUILayout.Toggle(BuildingSettings.ShowFolder, new GUIContent(EditorGUIUtility.IconContent("d_FolderOpened Icon").image, "Open the build folder"), ToolbarStyles.commandButtonStyle);
BuildingSettings.RunTests = GUILayout.Toggle(BuildingSettings.RunTests, new GUIContent(EditorGUIUtility.IconContent("FilterSelectedOnly").image, "Run tests before build starts"), ToolbarStyles.commandButtonStyle);

GUILayout.Space(5f);

BuildingSettings.ShowFolder = GUILayout.Toggle(BuildingSettings.ShowFolder, new GUIContent("Show Folder", "Open the build folder"), ToolbarStyles.toggleStyle);

if (GUILayout.Button(new GUIContent("", (Texture2D)EditorGUIUtility.IconContent("d_Settings").image, "Build the project"), ToolbarStyles.commandButtonStyle))
{
BuildMenu.ShowAsContext();
Expand Down
112 changes: 68 additions & 44 deletions Scripts/Runtime/Utils/UnityBuilding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Linq;
using UnityBuildTooling.Editor.build_tooling.Scripts.Runtime.Assets;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;

namespace UnityBuildTooling.Editor.build_tooling.Scripts.Runtime.Utils
Expand All @@ -13,69 +12,94 @@ internal static class UnityBuilding
private const string TargetKey = "${TARGET}";
internal const string DefaultTargetPath = "Builds/" + TargetKey;

public static void Build(BuildingGroup @group)
public static void Build(BuildingGroup @group, bool runTest = true)
{
foreach (var item in group.Items)
if (runTest && BuildingSettings.Singleton.RunTests)
{
Build(BuildBehavior.BuildOnly, item);
UnityTesting.RunTests(@group);
}
else
{
RunBuild();
}

void RunBuild()
{
foreach (var item in @group.Items)
{
Build(BuildBehavior.BuildOnly, item, false);
}
}
}

public static void Build(BuildBehavior behavior, BuildingData overwriteData = null)
public static void Build(BuildBehavior behavior, BuildingData overwriteData = null, bool runTest = true)
{
var buildingSettings = BuildingSettings.Singleton;
var buildingData = overwriteData ?? buildingSettings.BuildingData;
var buildingType = buildingSettings.TypeItems[buildingData.BuildType];

var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(buildingData.BuildTarget);
var cppCompilerConfiguration = CalculateConfiguration(buildingType);
if (cppCompilerConfiguration.HasValue)
if (runTest && buildingSettings.RunTests)
{
PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.IL2CPP);
PlayerSettings.SetIl2CppCompilerConfiguration(buildTargetGroup, cppCompilerConfiguration.Value);
PlayerSettings.SetIncrementalIl2CppBuild(buildTargetGroup, buildingType.CppIncrementalBuild);
#if UNITY_2021_2_OR_NEWER
EditorUserBuildSettings.il2CppCodeGeneration = buildingType.CppCodeGeneration;
#endif
UnityTesting.RunTests(behavior, overwriteData);
}
else
{
PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.Mono2x);
RunBuild();
}

PlayerSettings.Android.targetArchitectures = buildingType.AndroidArchitecture;
void RunBuild()
{
var buildingData = overwriteData ?? buildingSettings.BuildingData;
var buildingType = buildingSettings.TypeItems[buildingData.BuildType];

var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(buildingData.BuildTarget);
var cppCompilerConfiguration = CalculateConfiguration(buildingType);
if (cppCompilerConfiguration.HasValue)
{
PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.IL2CPP);
PlayerSettings.SetIl2CppCompilerConfiguration(buildTargetGroup, cppCompilerConfiguration.Value);
PlayerSettings.SetIncrementalIl2CppBuild(buildTargetGroup, buildingType.CppIncrementalBuild);
#if UNITY_2021_2_OR_NEWER
EditorUserBuildSettings.il2CppCodeGeneration = buildingType.CppCodeGeneration;
#endif
}
else
{
PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.Mono2x);
}

EditorUserBuildSettings.buildAppBundle = buildingType.BuildAppBundle;
PlayerSettings.Android.targetArchitectures = buildingType.AndroidArchitecture;

var targetPath = DefaultTargetPath.Replace(TargetKey, buildingData.BuildTarget.ToString()) + "/" + buildingType.TargetPath;
var appName = buildingSettings.AppName + GetExtension(buildingData.BuildTarget);
var options = new BuildPlayerOptions
{
scenes = KnownScenes,
target = buildingData.BuildTarget,
locationPathName = targetPath + "/" + appName,
options = CalculateOptions(buildingType, buildingData.BuildExtras, behavior, buildingSettings.Clean, buildingSettings.ShowFolder),
extraScriptingDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup).Split(',').Concat(buildingType.Defines).Where(x => !string.IsNullOrWhiteSpace(x)).ToArray()
};
EditorUserBuildSettings.buildAppBundle = buildingType.BuildAppBundle;

if (buildingSettings.Clean && Directory.Exists(targetPath))
{
Directory.Delete(targetPath, true);
}
var targetPath = DefaultTargetPath.Replace(TargetKey, buildingData.BuildTarget.ToString()) + "/" + buildingType.TargetPath;
var appName = buildingSettings.AppName + GetExtension(buildingData.BuildTarget);
var options = new BuildPlayerOptions
{
scenes = KnownScenes,
target = buildingData.BuildTarget,
locationPathName = targetPath + "/" + appName,
options = CalculateOptions(buildingType, buildingData.BuildExtras, behavior, buildingSettings.Clean, buildingSettings.ShowFolder),
extraScriptingDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup).Split(',').Concat(buildingType.Defines).Where(x => !string.IsNullOrWhiteSpace(x)).ToArray()
};

if (buildingSettings.Clean && Directory.Exists(targetPath))
{
Directory.Delete(targetPath, true);
}

var oldBuildTarget = EditorUserBuildSettings.activeBuildTarget;
var oldBuildGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
try
{
var buildReport = BuildPipeline.BuildPlayer(options);
if (buildReport.summary.result != BuildResult.Succeeded)
var oldBuildTarget = EditorUserBuildSettings.activeBuildTarget;
var oldBuildGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
try
{
EditorUtility.DisplayDialog("Build", "Build has failed", "OK");
var buildReport = BuildPipeline.BuildPlayer(options);
if (buildReport.summary.result != BuildResult.Succeeded)
{
EditorUtility.DisplayDialog("Build", "Build has failed", "OK");
}
}
finally
{
EditorUserBuildSettings.SwitchActiveBuildTarget(oldBuildGroup, oldBuildTarget);
}
}
finally
{
EditorUserBuildSettings.SwitchActiveBuildTarget(oldBuildGroup, oldBuildTarget);
}
}

Expand Down
174 changes: 174 additions & 0 deletions Scripts/Runtime/Utils/UnityTesting.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
using System;
using System.IO;
using UnityBuildTooling.Editor.build_tooling.Scripts.Runtime.Assets;
using UnityEditor;
using UnityEditor.TestTools.TestRunner.Api;
using UnityEngine;

namespace UnityBuildTooling.Editor.build_tooling.Scripts.Runtime.Utils
{
[InitializeOnLoad]
internal static class UnityTesting
{
private const string GroupFileName = "group.dat";
private const string BaseFileName = "base.dat";

private static TestRunnerApi _testRunnerApi;
private static readonly CallbackHandler _callbackHandler = new CallbackHandler();

static UnityTesting()
{
InitTest();
}

public static void InitTest()
{
if (_testRunnerApi == null)
{
_testRunnerApi = ScriptableObject.CreateInstance<TestRunnerApi>();
_testRunnerApi.RegisterCallbacks(_callbackHandler);
}
}

public static void RunTests(BuildingGroup @group)
{
Debug.Log("Start tests");

StoreGroup(@group);
InitTest();

_testRunnerApi.Execute(new ExecutionSettings(new Filter { testMode = TestMode.PlayMode }));
}

public static void RunTests(UnityBuilding.BuildBehavior behavior, BuildingData data)
{
Debug.Log("Start tests");

StoreBase(behavior, data);
InitTest();

_testRunnerApi.Execute(new ExecutionSettings(new Filter { testMode = TestMode.PlayMode }));
}

private static void StoreGroup(BuildingGroup @group)
{
var fileName = Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "/" + GroupFileName;
using (var stream = new FileStream(fileName, FileMode.Create))
{
using (var writer = new StreamWriter(stream))
{
writer.WriteLine(JsonUtility.ToJson(@group));
}
}
}

private static bool LoadGroup(out BuildingGroup @group)
{
@group = null;
var fileName = Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "/" + GroupFileName;

if (!File.Exists(fileName))
return false;

try
{
using (var stream = new FileStream(fileName, FileMode.Open))
{
using (var reader = new StreamReader(stream))
{
@group = JsonUtility.FromJson<BuildingGroup>(reader.ReadLine());
}
}
}
finally
{
File.Delete(fileName);
}

return true;
}

private static void StoreBase(UnityBuilding.BuildBehavior behavior, BuildingData overwriteData)
{
var fileName = Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "/" + BaseFileName;
using (var stream = new FileStream(fileName, FileMode.Create))
{
using (var writer = new StreamWriter(stream))
{
writer.WriteLine(JsonUtility.ToJson(behavior));
writer.WriteLine(JsonUtility.ToJson(overwriteData));
}
}
}

private static bool LoadBase(out UnityBuilding.BuildBehavior behavior, out BuildingData overwriteData)
{
behavior = UnityBuilding.BuildBehavior.BuildOnly;
overwriteData = null;

var fileName = Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "/" + BaseFileName;

if (!File.Exists(fileName))
return false;

try
{
using (var stream = new FileStream(fileName, FileMode.Open))
{
using (var reader = new StreamReader(stream))
{
behavior = JsonUtility.FromJson<UnityBuilding.BuildBehavior>(reader.ReadLine());
overwriteData = JsonUtility.FromJson<BuildingData>(reader.ReadLine());
}
}
}
finally
{
File.Delete(fileName);
}

return true;
}

private sealed class CallbackHandler : ICallbacks
{
public void RunStarted(ITestAdaptor testsToRun)
{
EditorUtility.DisplayProgressBar("Run Tests", "Test is running now", -1f);
}

public void RunFinished(ITestResultAdaptor result)
{
EditorUtility.ClearProgressBar();

Debug.Log("Finished test with success: " + result.PassCount + ", skipped: " + result.SkipCount + ", failed: " + result.FailCount);
if (result.TestStatus == TestStatus.Failed)
{
EditorUtility.DisplayDialog("Test failures", "There are test failures: " + result.TestStatus, "OK");
return;
}

if (LoadGroup(out var @group))
{
UnityBuilding.Build(@group, false);
}
else if (LoadBase(out var behavior, out var overwriteData))
{
UnityBuilding.Build(behavior, overwriteData, false);
}
else
{
Debug.LogError("Unable to find base or group file for build execution!");
}
}

public void TestStarted(ITestAdaptor test)
{
}

public void TestFinished(ITestResultAdaptor result)
{
}
}
}
}
3 changes: 3 additions & 0 deletions Scripts/Runtime/Utils/UnityTesting.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "org.pcsoft.build-tooling",
"version": "1.3.5",
"version": "1.4.0",
"displayName": "Build Tooling",
"description": "Add a build toolbar into unity to create and run build very easy.",
"unity": "2021.1",
Expand All @@ -12,7 +12,7 @@
],
"dependencies": {
"com.marijnzwemmer.unity-toolbar-extender": "1.4.1",
"org.pcsoft.editor-ex": "1.1.2"
"org.pcsoft.editor-ex": "1.1.6"
},
"author": {
"name": "Pfeiffer C Soft",
Expand Down

0 comments on commit 8f5c947

Please sign in to comment.