test
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96c503bf059df984c86eecf572370347
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
namespace UnityEditor.TestTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Ignore attributes dedicated to Asset Import Pipeline backend version handling.
|
||||
/// </summary>
|
||||
internal static class AssetPipelineIgnore
|
||||
{
|
||||
internal enum AssetPipelineBackend
|
||||
{
|
||||
V1,
|
||||
V2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ignore the test when running with the legacy Asset Import Pipeline V1 backend.
|
||||
/// </summary>
|
||||
internal class IgnoreInV1 : AssetPipelineIgnoreAttribute
|
||||
{
|
||||
public IgnoreInV1(string ignoreReason) : base(AssetPipelineBackend.V1, ignoreReason) {}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ignore the test when running with the latest Asset Import Pipeline V2 backend.
|
||||
/// </summary>
|
||||
internal class IgnoreInV2 : AssetPipelineIgnoreAttribute
|
||||
{
|
||||
public IgnoreInV2(string ignoreReason) : base(AssetPipelineBackend.V2, ignoreReason) {}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
|
||||
internal class AssetPipelineIgnoreAttribute : NUnitAttribute, IApplyToTest
|
||||
{
|
||||
private readonly string m_IgnoreReason;
|
||||
private readonly AssetPipelineBackend m_IgnoredBackend;
|
||||
private static readonly AssetPipelineBackend k_ActiveBackend = AssetDatabase.IsV2Enabled()
|
||||
? AssetPipelineBackend.V2
|
||||
: AssetPipelineBackend.V1;
|
||||
|
||||
private static string ActiveBackendName = Enum.GetName(typeof(AssetPipelineBackend), k_ActiveBackend);
|
||||
|
||||
public AssetPipelineIgnoreAttribute(AssetPipelineBackend backend, string ignoreReason)
|
||||
{
|
||||
m_IgnoredBackend = backend;
|
||||
m_IgnoreReason = ignoreReason;
|
||||
}
|
||||
|
||||
public void ApplyToTest(Test test)
|
||||
{
|
||||
if (k_ActiveBackend == m_IgnoredBackend)
|
||||
{
|
||||
test.RunState = RunState.Ignored;
|
||||
var skipReason = string.Format("Not supported by asset pipeline {0} backend {1}", ActiveBackendName, m_IgnoreReason);
|
||||
test.Properties.Add(PropertyNames.SkipReason, skipReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b88caca58e05ee74486d86fb404c48e2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.TestTools
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface for a callback modifying the <see cref="BuildPlayerOptions"/> when building a player for running tests in the runtime.
|
||||
/// </summary>
|
||||
public interface ITestPlayerBuildModifier
|
||||
{
|
||||
/// <summary>
|
||||
/// A callback to modify the <see cref="BuildPlayerOptions"/> when building a player for test run. Return the modified version of the provided build options.
|
||||
/// </summary>
|
||||
/// <param name="playerOptions">The unmodified BuildPlayerOptions.</param>
|
||||
/// <returns>The modified BuildPlayerOptions.</returns>
|
||||
BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d2f47eae5f447748892c46848956d5f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.TestTools
|
||||
{
|
||||
/// <summary>
|
||||
/// You can use the ```TestPlayerBuildModifier``` attribute to accomplish a couple of different scenarios.
|
||||
/// ## Modify the Player build options for Play Mode tests
|
||||
///
|
||||
/// It is possible to change the [BuildPlayerOptions](https://docs.unity3d.com/ScriptReference/BuildPlayerOptions.html) for the test **Player**, to achieve custom behavior when running **Play Mode** tests. Modifying the build options allows for changing the target location of the build as well as changing [BuildOptions](https://docs.unity3d.com/ScriptReference/BuildOptions.html).
|
||||
///
|
||||
/// To modify the `BuildPlayerOptions`, do the following:
|
||||
///
|
||||
/// * Implement the `ITestPlayerBuildModifier`
|
||||
/// * Reference the implementation type in a `TestPlayerBuildModifier` attribute on an assembly level.
|
||||
///
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// using UnityEditor;
|
||||
/// using UnityEditor.TestTools;
|
||||
///
|
||||
/// [assembly:TestPlayerBuildModifier(typeof(BuildModifier))]
|
||||
/// public class BuildModifier : ITestPlayerBuildModifier
|
||||
/// {
|
||||
/// public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions)
|
||||
/// {
|
||||
/// if (playerOptions.target == BuildTarget.iOS)
|
||||
/// {
|
||||
/// playerOptions.options |= BuildOptions.SymlinkLibraries; // Enable symlink libraries when running on iOS
|
||||
/// }
|
||||
///
|
||||
/// playerOptions.options |= BuildOptions.AllowDebugging; // Enable allow Debugging flag on the test Player.
|
||||
/// return playerOptions;
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
///
|
||||
///
|
||||
/// > **Note:** When building the Player, it includes all `TestPlayerBuildModifier` attributes across all loaded assemblies, independent of the currently used test filter. As the implementation references the `UnityEditor` namespace, the code is typically implemented in an Editor only assembly, as the `UnityEditor` namespace is not available otherwise.
|
||||
///
|
||||
/// ## Split build and run
|
||||
/// It is possible to use the Unity Editor for building the Player with tests, without [running the tests](./workflow-run-playmode-test-standalone.md). This allows for running the Player on e.g. another machine. In this case, it is necessary to modify the Player to build and implement a custom handling of the test result.
|
||||
/// By using `TestPlayerBuildModifier`, you can alter the `BuildOptions` to not start the Player after the build as well as build the Player at a specific location. Combined with [PostBuildCleanup](./reference-setup-and-cleanup.md#prebuildsetup-and-postbuildcleanup), you can automatically exit the Editor on completion of the build.
|
||||
///
|
||||
///
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// using System;
|
||||
/// using System.IO;
|
||||
/// using System.Linq;
|
||||
/// using Tests;
|
||||
/// using UnityEditor;
|
||||
/// using UnityEditor.TestTools;
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.TestTools;
|
||||
///
|
||||
/// [assembly:TestPlayerBuildModifier(typeof(HeadlessPlayModeSetup))]
|
||||
/// [assembly:PostBuildCleanup(typeof(HeadlessPlayModeSetup))]
|
||||
///
|
||||
/// namespace Tests
|
||||
/// {
|
||||
/// public class HeadlessPlayModeSetup : ITestPlayerBuildModifier, IPostBuildCleanup
|
||||
/// {
|
||||
/// private static bool s_RunningPlayerTests;
|
||||
/// public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions)
|
||||
/// {
|
||||
/// // Do not launch the player after the build completes.
|
||||
/// playerOptions.options &= ~BuildOptions.AutoRunPlayer;
|
||||
///
|
||||
/// // Set the headlessBuildLocation to the output directory you desire. It does not need to be inside the project.
|
||||
/// var headlessBuildLocation = Path.GetFullPath(Path.Combine(Application.dataPath, ".//..//PlayModeTestPlayer"));
|
||||
/// var fileName = Path.GetFileName(playerOptions.locationPathName);
|
||||
/// if (!string.IsNullOrEmpty(fileName))
|
||||
/// {
|
||||
/// headlessBuildLocation = Path.Combine(headlessBuildLocation, fileName);
|
||||
/// }
|
||||
/// playerOptions.locationPathName = headlessBuildLocation;
|
||||
///
|
||||
/// // Instruct the cleanup to exit the Editor if the run came from the command line.
|
||||
/// // The variable is static because the cleanup is being invoked in a new instance of the class.
|
||||
/// s_RunningPlayerTests = true;
|
||||
/// return playerOptions;
|
||||
/// }
|
||||
///
|
||||
/// public void Cleanup()
|
||||
/// {
|
||||
/// if (s_RunningPlayerTests && IsRunningTestsFromCommandLine())
|
||||
/// {
|
||||
/// // Exit the Editor on the next update, allowing for other PostBuildCleanup steps to run.
|
||||
/// EditorApplication.update += () => { EditorApplication.Exit(0); };
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// private static bool IsRunningTestsFromCommandLine()
|
||||
/// {
|
||||
/// var commandLineArgs = Environment.GetCommandLineArgs();
|
||||
/// return commandLineArgs.Any(value => value == "-runTests");
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
///
|
||||
/// If the Editor is still running after the Play Mode tests have run, the Player tries to report the results back, using [PlayerConnection](https://docs.unity3d.com/ScriptReference/Networking.PlayerConnection.PlayerConnection.html), which has a reference to the IP address of the Editor machine, when built.
|
||||
///
|
||||
/// To implement a custom way of reporting the results of the test run, let one of the assemblies in the Player include a `TestRunCallbackAttribute`. At `RunFinished`, it is possible to get the full test report as XML from the [NUnit](http://www.nunit.org/) test result by calling `result.ToXml(true)`. You can save the result and then save it on the device or send it to another machine as needed.
|
||||
///
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly)]
|
||||
public class TestPlayerBuildModifierAttribute : Attribute
|
||||
{
|
||||
private Type m_Type;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of TestPlayerBuildModifierAttribute or throws an <see cref="ArgumentException"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">A target type that implements ITestPlayerBuildModifier.</param>
|
||||
/// <exception cref="ArgumentException">Throws a <see cref="ArgumentException"/> if the type provided does not implemented the `ITestPlayerBuildModifier` interface. </exception>
|
||||
public TestPlayerBuildModifierAttribute(Type type)
|
||||
{
|
||||
var interfaceType = typeof(ITestPlayerBuildModifier);
|
||||
if (!interfaceType.IsAssignableFrom(type))
|
||||
{
|
||||
throw new ArgumentException(string.Format("Type provided to {0} does not implement {1}", GetType().Name, interfaceType.Name));
|
||||
}
|
||||
m_Type = type;
|
||||
}
|
||||
|
||||
internal ITestPlayerBuildModifier ConstructModifier()
|
||||
{
|
||||
return Activator.CreateInstance(m_Type) as ITestPlayerBuildModifier;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd57b1176859fc84e93586103d3b5f73
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
using UnityEngine.TestTools.Logging;
|
||||
using UnityEngine.TestTools.NUnitExtensions;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner
|
||||
{
|
||||
[Serializable]
|
||||
internal class TestRunnerStateSerializer : IStateSerializer
|
||||
{
|
||||
private const BindingFlags Flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy;
|
||||
|
||||
[SerializeField]
|
||||
private HideFlags m_OriginalHideFlags;
|
||||
|
||||
[SerializeField]
|
||||
private bool m_ShouldRestore;
|
||||
|
||||
[SerializeField]
|
||||
private string m_TestObjectTypeName;
|
||||
|
||||
[SerializeField]
|
||||
private ScriptableObject m_TestObject;
|
||||
|
||||
[SerializeField]
|
||||
private string m_TestObjectTxt;
|
||||
|
||||
[SerializeField]
|
||||
private long StartTicks;
|
||||
|
||||
[SerializeField]
|
||||
private double StartTimeOA;
|
||||
|
||||
[SerializeField]
|
||||
private string output;
|
||||
|
||||
[SerializeField]
|
||||
private LogMatch[] m_ExpectedLogs;
|
||||
|
||||
public bool ShouldRestore()
|
||||
{
|
||||
return m_ShouldRestore;
|
||||
}
|
||||
|
||||
public void SaveContext()
|
||||
{
|
||||
var currentContext = UnityTestExecutionContext.CurrentContext;
|
||||
|
||||
if (currentContext.TestObject != null)
|
||||
{
|
||||
m_TestObjectTypeName = currentContext.TestObject.GetType().AssemblyQualifiedName;
|
||||
m_TestObject = null;
|
||||
m_TestObjectTxt = null;
|
||||
if (currentContext.TestObject is ScriptableObject)
|
||||
{
|
||||
m_TestObject = currentContext.TestObject as ScriptableObject;
|
||||
m_OriginalHideFlags = m_TestObject.hideFlags;
|
||||
m_TestObject.hideFlags |= HideFlags.DontSave;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_TestObjectTxt = JsonUtility.ToJson(currentContext.TestObject);
|
||||
}
|
||||
}
|
||||
|
||||
output = currentContext.CurrentResult.Output;
|
||||
StartTicks = currentContext.StartTicks;
|
||||
StartTimeOA = currentContext.StartTime.ToOADate();
|
||||
if (LogScope.HasCurrentLogScope())
|
||||
{
|
||||
m_ExpectedLogs = LogScope.Current.ExpectedLogs.ToArray();
|
||||
}
|
||||
|
||||
m_ShouldRestore = true;
|
||||
}
|
||||
|
||||
public void RestoreContext()
|
||||
{
|
||||
var currentContext = UnityTestExecutionContext.CurrentContext;
|
||||
|
||||
var outputProp = currentContext.CurrentResult.GetType().BaseType.GetField("_output", Flags);
|
||||
(outputProp.GetValue(currentContext.CurrentResult) as StringBuilder).Append(output);
|
||||
|
||||
currentContext.StartTicks = StartTicks;
|
||||
currentContext.StartTime = DateTime.FromOADate(StartTimeOA);
|
||||
if (LogScope.HasCurrentLogScope())
|
||||
{
|
||||
LogScope.Current.ExpectedLogs = new Queue<LogMatch>(m_ExpectedLogs);
|
||||
}
|
||||
|
||||
m_ShouldRestore = false;
|
||||
}
|
||||
|
||||
public bool CanRestoreFromScriptableObject(Type requestedType)
|
||||
{
|
||||
if (m_TestObject == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return m_TestObjectTypeName == requestedType.AssemblyQualifiedName;
|
||||
}
|
||||
|
||||
public ScriptableObject RestoreScriptableObjectInstance()
|
||||
{
|
||||
if (m_TestObject == null)
|
||||
{
|
||||
Debug.LogError("No object to restore");
|
||||
return null;
|
||||
}
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
var temp = m_TestObject;
|
||||
m_TestObject = null;
|
||||
m_TestObjectTypeName = null;
|
||||
return temp;
|
||||
}
|
||||
|
||||
public bool CanRestoreFromJson(Type requestedType)
|
||||
{
|
||||
if (string.IsNullOrEmpty(m_TestObjectTxt))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return m_TestObjectTypeName == requestedType.AssemblyQualifiedName;
|
||||
}
|
||||
|
||||
public void RestoreClassFromJson(ref object instance)
|
||||
{
|
||||
if (string.IsNullOrEmpty(m_TestObjectTxt))
|
||||
{
|
||||
Debug.LogWarning("No JSON representation to restore");
|
||||
return;
|
||||
}
|
||||
JsonUtility.FromJsonOverwrite(m_TestObjectTxt, instance);
|
||||
m_TestObjectTxt = null;
|
||||
m_TestObjectTypeName = null;
|
||||
}
|
||||
|
||||
private void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
if (m_TestObject == null)
|
||||
{
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
return;
|
||||
}
|
||||
|
||||
//We set the DontSave flag here because the ScriptableObject would be nulled right before entering EditMode
|
||||
if (state == PlayModeStateChange.ExitingPlayMode)
|
||||
{
|
||||
m_TestObject.hideFlags |= HideFlags.DontSave;
|
||||
}
|
||||
else if (state == PlayModeStateChange.EnteredEditMode)
|
||||
{
|
||||
m_TestObject.hideFlags = m_OriginalHideFlags;
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 124533853216377448d786fd7c725701
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user