first commit
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
using UnityEngine.TestTools.Logging;
|
||||
using UnityEngine.TestTools.TestRunner;
|
||||
|
||||
namespace UnityEngine.TestTools.NUnitExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// This class delegates actions from the NUnit thread that should be executed on the main thread.
|
||||
/// NUnit thread calls Delegate which blocks the execution on the thread until the action is executed.
|
||||
/// The main thread will poll for awaiting actions (HasAction) and invoke them (Execute).
|
||||
/// Once the action is executed, the main thread releases the lock and executino on the NUnit thread is continued.
|
||||
/// </summary>
|
||||
internal class ActionDelegator : BaseDelegator
|
||||
{
|
||||
private Func<object> m_Action;
|
||||
public object Delegate(Action action)
|
||||
{
|
||||
return Delegate(() => { action(); return null; });
|
||||
}
|
||||
|
||||
public object Delegate(Func<object> action)
|
||||
{
|
||||
if (m_Aborted)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
AssertState();
|
||||
m_Context = UnityTestExecutionContext.CurrentContext;
|
||||
|
||||
m_Signal.Reset();
|
||||
m_Action = action;
|
||||
|
||||
WaitForSignal();
|
||||
|
||||
return HandleResult();
|
||||
}
|
||||
|
||||
private void AssertState()
|
||||
{
|
||||
if (m_Action != null)
|
||||
{
|
||||
throw new Exception("Action not executed yet");
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasAction()
|
||||
{
|
||||
return m_Action != null;
|
||||
}
|
||||
|
||||
public void Execute(LogScope logScope)
|
||||
{
|
||||
try
|
||||
{
|
||||
SetCurrentTestContext();
|
||||
m_Result = m_Action();
|
||||
logScope.EvaluateLogScope(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_Exception = e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_Action = null;
|
||||
m_Signal.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f939b9e23a0946439b812551e07ac81
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cb14878543cf3d4f8472b15f7ecf0e3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,85 @@
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
/// <summary>
|
||||
/// This attribute is an alternative to the standard `Ignore` attribute in [NUnit](https://nunit.org/). It allows for ignoring tests only under a specified condition. The condition evaluates during `OnLoad`, referenced by ID.
|
||||
/// </summary>
|
||||
public class ConditionalIgnoreAttribute : NUnitAttribute, IApplyToTest
|
||||
{
|
||||
string m_ConditionKey;
|
||||
string m_IgnoreReason;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConditionalIgnoreAttribute"/> class with a condition key.
|
||||
/// </summary>
|
||||
/// <param name="conditionKey">The key to check for enabling the conditional ignore. The condition is set with the static <see cref="AddConditionalIgnoreMapping"/> method.</param>
|
||||
/// <param name="ignoreReason">The reason for the ignore.</param>
|
||||
public ConditionalIgnoreAttribute(string conditionKey, string ignoreReason)
|
||||
{
|
||||
m_ConditionKey = conditionKey;
|
||||
m_IgnoreReason = ignoreReason;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a test as defined for the specific attribute.
|
||||
/// </summary>
|
||||
/// <param name="test">The test to modify</param>
|
||||
public void ApplyToTest(Test test)
|
||||
{
|
||||
var key = m_ConditionKey.ToLowerInvariant();
|
||||
if (m_ConditionMap.ContainsKey(key) && m_ConditionMap[key])
|
||||
{
|
||||
test.RunState = RunState.Ignored;
|
||||
string skipReason = string.Format(m_IgnoreReason);
|
||||
test.Properties.Add(PropertyNames.SkipReason, skipReason);
|
||||
}
|
||||
}
|
||||
|
||||
static Dictionary<string, bool> m_ConditionMap = new Dictionary<string, bool>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a flag indicating whether tests with the same key should be ignored.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to ignore tests for.</param>
|
||||
/// <param name="value">A boolean value indicating whether the tests should be ignored.</param>
|
||||
/// <example>
|
||||
/// An example in which tests are ignored in the Mac editor only.
|
||||
/// <code>
|
||||
/// using UnityEditor;
|
||||
/// using NUnit.Framework;
|
||||
/// using UnityEngine.TestTools;
|
||||
///
|
||||
/// [InitializeOnLoad]
|
||||
/// public class OnLoad
|
||||
/// {
|
||||
/// static OnLoad()
|
||||
/// {
|
||||
/// var editorIsOSX = false;
|
||||
/// #if UNITY_EDITOR_OSX
|
||||
/// editorIsOSX = true;
|
||||
/// #endif
|
||||
///
|
||||
/// ConditionalIgnoreAttribute.AddConditionalIgnoreMapping("IgnoreInMacEditor", editorIsOSX);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// public class MyTestClass
|
||||
/// {
|
||||
/// [Test, ConditionalIgnore("IgnoreInMacEditor", "Ignored on Mac editor.")]
|
||||
/// public void TestNeverRunningInMacEditor()
|
||||
/// {
|
||||
/// Assert.Pass();
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static void AddConditionalIgnoreMapping(string key, bool value)
|
||||
{
|
||||
m_ConditionMap.Add(key.ToLowerInvariant(), value);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c82a8473f4a8f7b42a004c91e06d2f2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
using UnityEngine.TestRunner.NUnitExtensions;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class TestEnumerator
|
||||
{
|
||||
private readonly ITestExecutionContext m_Context;
|
||||
private static IEnumerator m_TestEnumerator;
|
||||
|
||||
public static IEnumerator Enumerator { get { return m_TestEnumerator; } }
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
m_TestEnumerator = null;
|
||||
}
|
||||
|
||||
public TestEnumerator(ITestExecutionContext context, IEnumerator testEnumerator)
|
||||
{
|
||||
m_Context = context;
|
||||
m_TestEnumerator = testEnumerator;
|
||||
}
|
||||
|
||||
public IEnumerator Execute()
|
||||
{
|
||||
m_Context.CurrentResult.SetResult(ResultState.Success);
|
||||
|
||||
return Execute(m_TestEnumerator, new EnumeratorContext(m_Context));
|
||||
}
|
||||
|
||||
private IEnumerator Execute(IEnumerator enumerator, EnumeratorContext context)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (context.ExceptionWasRecorded)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.RecordExceptionWithHint(ex);
|
||||
break;
|
||||
}
|
||||
|
||||
if (enumerator.Current is IEnumerator nestedEnumerator)
|
||||
{
|
||||
yield return Execute(nestedEnumerator, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return enumerator.Current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class EnumeratorContext
|
||||
{
|
||||
private readonly ITestExecutionContext m_Context;
|
||||
|
||||
public EnumeratorContext(ITestExecutionContext context)
|
||||
{
|
||||
m_Context = context;
|
||||
}
|
||||
|
||||
public bool ExceptionWasRecorded
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public void RecordExceptionWithHint(Exception ex)
|
||||
{
|
||||
if (ExceptionWasRecorded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_Context.CurrentResult.RecordException(ex);
|
||||
ExceptionWasRecorded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 750aad009559b814dbc27001341fc1c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
/// <summary>
|
||||
/// The presence of this attribute will cause the test runner to require that every single log is expected. By
|
||||
/// default, the runner will only automatically fail on any error logs, so this adds warnings and infos as well.
|
||||
/// It is the same as calling `LogAssert.NoUnexpectedReceived()` at the bottom of every affected test.
|
||||
///
|
||||
/// This attribute can be applied to test assemblies (will affect every test in the assembly), fixtures (will
|
||||
/// affect every test in the fixture), or on individual test methods. It is also automatically inherited from base
|
||||
/// fixtures.
|
||||
///
|
||||
/// The MustExpect property (on by default) lets you selectively enable or disable the higher level value. For
|
||||
/// example when migrating an assembly to this more strict checking method, you might attach
|
||||
/// `[assembly:TestMustExpectAllLogs]` to the assembly itself, but then whitelist failing fixtures and test methods
|
||||
/// with `[TestMustExpectAllLogs(MustExpect=false)]` until they can be migrated. This also means new tests in that
|
||||
/// assembly would be required to have the more strict checking.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class TestMustExpectAllLogsAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of TestMustExpectAllLogsAttribute.
|
||||
/// </summary>
|
||||
/// <param name="mustExpect">
|
||||
/// A value indicating whether the test must expect all logs.
|
||||
/// </param>
|
||||
public TestMustExpectAllLogsAttribute(bool mustExpect = true)
|
||||
=> MustExpect = mustExpect;
|
||||
/// <summary>
|
||||
/// Returns the flag of whether the test must expect all logs.
|
||||
/// </summary>
|
||||
public bool MustExpect { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3803f736886e77842995ddbc3531afaa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,20 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal.Builders;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class UnityCombinatorialStrategy : CombinatorialStrategy, ICombiningStrategy
|
||||
{
|
||||
public new IEnumerable<ITestCaseData> GetTestCases(IEnumerable[] sources)
|
||||
{
|
||||
var testCases = base.GetTestCases(sources);
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
testCase.GetType().GetProperty("ExpectedResult").SetValue(testCase, new object(), null);
|
||||
}
|
||||
return testCases;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7af6ac3e6b51b8d4aab04adc85b8de2f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this attribute to define a specific set of platforms you want or do not want your test(s) to run on.
|
||||
///
|
||||
/// You can use this attribute on the test method, test class, or test assembly level. Use the supported <see cref="RuntimePlatform"/> enumeration values to specify the platforms. You can also specify which platforms to test by passing one or more `RuntimePlatform` values along with or without the include or exclude properties as parameters to the [Platform](https://github.com/nunit/docs/wiki/Platform-Attribute) attribute constructor.
|
||||
///
|
||||
/// The test(s) skips if the current target platform is:
|
||||
/// - Not explicitly specified in the included platforms list
|
||||
/// - In the excluded platforms list
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
|
||||
public class UnityPlatformAttribute : NUnitAttribute, IApplyToTest
|
||||
{
|
||||
/// <summary>
|
||||
/// A subset of platforms you need to have your tests run on.
|
||||
/// </summary>
|
||||
public RuntimePlatform[] include { get; set; }
|
||||
/// <summary>
|
||||
/// List the platforms you do not want to have your tests run on.
|
||||
/// </summary>
|
||||
public RuntimePlatform[] exclude { get; set; }
|
||||
|
||||
private string m_skippedReason;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance of the <see cref="UnityPlatformAttribute"/> class.
|
||||
/// </summary>
|
||||
public UnityPlatformAttribute()
|
||||
{
|
||||
include = new List<RuntimePlatform>().ToArray();
|
||||
exclude = new List<RuntimePlatform>().ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance of the <see cref="UnityPlatformAttribute"/> class with a list of platforms to include.
|
||||
/// </summary>
|
||||
/// <param name="include">The different <see cref="RuntimePlatform"/> to run the test on.</param>
|
||||
public UnityPlatformAttribute(params RuntimePlatform[] include)
|
||||
: this()
|
||||
{
|
||||
this.include = include;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a test as defined for the specific attribute.
|
||||
/// </summary>
|
||||
/// <param name="test">The test to modify</param>
|
||||
public void ApplyToTest(Test test)
|
||||
{
|
||||
if (test.RunState == RunState.NotRunnable || test.RunState == RunState.Ignored || IsPlatformSupported(Application.platform))
|
||||
{
|
||||
return;
|
||||
}
|
||||
test.RunState = RunState.Skipped;
|
||||
test.Properties.Add(PropertyNames.SkipReason, m_skippedReason);
|
||||
}
|
||||
|
||||
internal bool IsPlatformSupported(RuntimePlatform testTargetPlatform)
|
||||
{
|
||||
if (include.Any() && !include.Any(x => x == testTargetPlatform))
|
||||
{
|
||||
m_skippedReason = string.Format("Only supported on {0}", string.Join(", ", include.Select(x => x.ToString()).ToArray()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exclude.Any(x => x == testTargetPlatform))
|
||||
{
|
||||
m_skippedReason = string.Format("Not supported on {0}", string.Join(", ", exclude.Select(x => x.ToString()).ToArray()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5440c1153b397e14c9c7b1d6eb83b9f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
/// <summary>
|
||||
/// The `UnitySetUp` and <see cref="UnityTearDownAttribute"/> attributes are identical to the standard `SetUp` and `TearDown` attributes, with the exception that they allow for <see cref="IEditModeTestYieldInstruction"/>. The `UnitySetUp` and `UnityTearDown` attributes expect a return type of [IEnumerator](https://docs.microsoft.com/en-us/dotnet/api/system.collections.ienumerator?view=netframework-4.8).
|
||||
/// <example>
|
||||
/// <code>
|
||||
///public class SetUpTearDownExample
|
||||
/// {
|
||||
/// [UnitySetUp]
|
||||
/// public IEnumerator SetUp()
|
||||
/// {
|
||||
/// yield return new EnterPlayMode();
|
||||
/// }
|
||||
///
|
||||
/// [Test]
|
||||
/// public void MyTest()
|
||||
/// {
|
||||
/// Debug.Log("This runs inside playmode");
|
||||
/// }
|
||||
///
|
||||
/// [UnityTearDown]
|
||||
/// public IEnumerator TearDown()
|
||||
/// {
|
||||
/// yield return new ExitPlayMode();
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class UnitySetUpAttribute : NUnitAttribute
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc6401f13df54ba44bfd7cdc93c7d64d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="UnitySetUpAttribute"/> and `UnityTearDown` attributes are identical to the standard `SetUp` and `TearDown` attributes, with the exception that they allow for <see cref="IEditModeTestYieldInstruction"/>. The `UnitySetUp` and `UnityTearDown` attributes expect a return type of [IEnumerator](https://docs.microsoft.com/en-us/dotnet/api/system.collections.ienumerator?view=netframework-4.8).
|
||||
/// <example>
|
||||
/// <code>
|
||||
///public class SetUpTearDownExample
|
||||
/// {
|
||||
/// [UnitySetUp]
|
||||
/// public IEnumerator SetUp()
|
||||
/// {
|
||||
/// yield return new EnterPlayMode();
|
||||
/// }
|
||||
///
|
||||
/// [Test]
|
||||
/// public void MyTest()
|
||||
/// {
|
||||
/// Debug.Log("This runs inside playmode");
|
||||
/// }
|
||||
///
|
||||
/// [UnityTearDown]
|
||||
/// public IEnumerator TearDown()
|
||||
/// {
|
||||
/// yield return new ExitPlayMode();
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class UnityTearDownAttribute : NUnitAttribute
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 600f4b74746dbf944901257f81a8af6d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Builders;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
/// <summary>
|
||||
/// `UnityTest` attribute is the main addition to the standard [NUnit](http://www.nunit.org/) library for the Unity Test Framework. This type of unit test allows you to skip a frame from within a test (so background tasks can finish) or give certain commands to the Unity **Editor**, such as performing a domain reload or entering **Play Mode** from an **Edit Mode** test.
|
||||
/// In Play Mode, the `UnityTest` attribute runs as a [coroutine](https://docs.unity3d.com/Manual/Coroutines.html). Whereas Edit Mode tests run in the [EditorApplication.update](https://docs.unity3d.com/ScriptReference/EditorApplication-update.html) callback loop.
|
||||
/// The `UnityTest` attribute is, in fact, an alternative to the `NUnit` [Test attribute](https://github.com/nunit/docs/wiki/Test-Attribute), which allows yielding instructions back to the framework. Once the instruction is complete, the test run continues. If you `yield return null`, you skip a frame. That might be necessary to ensure that some changes do happen on the next iteration of either the `EditorApplication.update` loop or the [game loop](https://docs.unity3d.com/Manual/ExecutionOrder.html).
|
||||
/// <example>
|
||||
/// ## Edit Mode example
|
||||
/// The most simple example of an Edit Mode test could be the one that yields `null` to skip the current frame and then continues to run:
|
||||
/// <code>
|
||||
/// [UnityTest]
|
||||
/// public IEnumerator EditorUtility_WhenExecuted_ReturnsSuccess()
|
||||
/// {
|
||||
/// var utility = RunEditorUtilityInTheBackground();
|
||||
///
|
||||
/// while (utility.isRunning)
|
||||
/// {
|
||||
/// yield return null;
|
||||
/// }
|
||||
///
|
||||
/// Assert.IsTrue(utility.isSuccess);
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// ## Play Mode example
|
||||
///
|
||||
/// In Play Mode, a test runs as a coroutine attached to a [MonoBehaviour](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html). So all the yield instructions available in coroutines, are also available in your test.
|
||||
///
|
||||
/// From a Play Mode test you can use one of Unity’s [Yield Instructions](https://docs.unity3d.com/ScriptReference/YieldInstruction.html):
|
||||
///
|
||||
/// - [WaitForFixedUpdate](https://docs.unity3d.com/ScriptReference/WaitForFixedUpdate.html): to ensure changes expected within the next cycle of physics calculations.
|
||||
/// - [WaitForSeconds](https://docs.unity3d.com/ScriptReference/WaitForSeconds.html): if you want to pause your test coroutine for a fixed amount of time. Be careful about creating long-running tests.
|
||||
///
|
||||
/// The simplest example is to yield to `WaitForFixedUpdate`:
|
||||
/// <code>
|
||||
/// [UnityTest]
|
||||
/// public IEnumerator GameObject_WithRigidBody_WillBeAffectedByPhysics()
|
||||
/// {
|
||||
/// var go = new GameObject();
|
||||
/// go.AddComponent<Rigidbody>();
|
||||
/// var originalPosition = go.transform.position.y;
|
||||
///
|
||||
/// yield return new WaitForFixedUpdate();
|
||||
///
|
||||
/// Assert.AreNotEqual(originalPosition, go.transform.position.y);
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class UnityTestAttribute : CombiningStrategyAttribute, ISimpleTestBuilder, IImplyFixture, ITestBuilder, IApplyToTest
|
||||
{
|
||||
const string k_MethodMarkedWithUnitytestMustReturnIenumerator = "Method marked with UnityTest must return IEnumerator.";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of UnityTestAttribute.
|
||||
/// </summary>
|
||||
public UnityTestAttribute() : base(new UnityCombinatorialStrategy(), new ParameterDataSourceProvider()) {}
|
||||
|
||||
private readonly NUnitTestCaseBuilder _builder = new NUnitTestCaseBuilder();
|
||||
|
||||
/// <summary>
|
||||
/// This method builds the TestMethod from the Test and the method info. In addition it removes the expected result of the test.
|
||||
/// </summary>
|
||||
/// <param name="method">The method info.</param>
|
||||
/// <param name="suite">The test.</param>
|
||||
/// <returns>A TestMethod object</returns>
|
||||
TestMethod ISimpleTestBuilder.BuildFrom(IMethodInfo method, Test suite)
|
||||
{
|
||||
var t = CreateTestMethod(method, suite);
|
||||
|
||||
AdaptToUnityTestMethod(t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method hides the base method from CombiningStrategyAttribute.
|
||||
/// It builds a TestMethod from a Parameterized Test and the method info.
|
||||
/// In addition it removes the expected result of the test.
|
||||
/// </summary>
|
||||
/// <param name="method">The method info.</param>
|
||||
/// <param name="suite">The test.</param>
|
||||
/// <returns>A TestMethod object</returns>
|
||||
IEnumerable<TestMethod> ITestBuilder.BuildFrom(IMethodInfo method, Test suite)
|
||||
{
|
||||
var testMethods = base.BuildFrom(method, suite);
|
||||
|
||||
foreach (var t in testMethods)
|
||||
{
|
||||
AdaptToUnityTestMethod(t);
|
||||
}
|
||||
|
||||
return testMethods;
|
||||
}
|
||||
|
||||
TestMethod CreateTestMethod(IMethodInfo method, Test suite)
|
||||
{
|
||||
TestCaseParameters parms = new TestCaseParameters
|
||||
{
|
||||
ExpectedResult = new object(),
|
||||
HasExpectedResult = true
|
||||
};
|
||||
|
||||
var t = _builder.BuildTestMethod(method, suite, parms);
|
||||
return t;
|
||||
}
|
||||
|
||||
static void AdaptToUnityTestMethod(TestMethod t)
|
||||
{
|
||||
if (t.parms != null)
|
||||
{
|
||||
t.parms.HasExpectedResult = false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsMethodReturnTypeIEnumerator(IMethodInfo method)
|
||||
{
|
||||
return !method.ReturnType.IsType(typeof(IEnumerator));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method hides the base method ApplyToTest from CombiningStrategyAttribute.
|
||||
/// In addition it ensures that the test with the `UnityTestAttribute` has an IEnumerator as return type.
|
||||
/// </summary>
|
||||
/// <param name="test">The test.</param>
|
||||
public new void ApplyToTest(Test test)
|
||||
{
|
||||
if (IsMethodReturnTypeIEnumerator(test.Method))
|
||||
{
|
||||
test.RunState = RunState.NotRunnable;
|
||||
test.Properties.Set(PropertyNames.SkipReason, k_MethodMarkedWithUnitytestMustReturnIenumerator);
|
||||
}
|
||||
|
||||
base.ApplyToTest(test);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fedb0f9e5006b1943abae52f52f08a1a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
namespace UnityEngine.TestTools.NUnitExtensions
|
||||
{
|
||||
internal abstract class BaseDelegator
|
||||
{
|
||||
protected ManualResetEvent m_Signal = new ManualResetEvent(false);
|
||||
|
||||
protected object m_Result;
|
||||
protected Exception m_Exception;
|
||||
protected ITestExecutionContext m_Context;
|
||||
|
||||
protected bool m_Aborted;
|
||||
|
||||
protected object HandleResult()
|
||||
{
|
||||
SetCurrentTestContext();
|
||||
if (m_Exception != null)
|
||||
{
|
||||
var temp = m_Exception;
|
||||
m_Exception = null;
|
||||
throw temp;
|
||||
}
|
||||
var tempResult = m_Result;
|
||||
m_Result = null;
|
||||
return tempResult;
|
||||
}
|
||||
|
||||
protected void WaitForSignal()
|
||||
{
|
||||
while (!m_Signal.WaitOne(100))
|
||||
{
|
||||
if (m_Aborted)
|
||||
{
|
||||
m_Aborted = false;
|
||||
Reflect.MethodCallWrapper = null;
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Abort()
|
||||
{
|
||||
m_Aborted = true;
|
||||
}
|
||||
|
||||
protected void SetCurrentTestContext()
|
||||
{
|
||||
var prop = typeof(TestExecutionContext).GetProperty("CurrentContext");
|
||||
if (prop != null)
|
||||
{
|
||||
prop.SetValue(null, m_Context, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37cea569bfefafe49a1513c4d7f0e9eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b72875690e0f7343911e06af3145bd5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,296 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using UnityEngine.TestRunner.NUnitExtensions;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
using UnityEngine.TestTools.Logging;
|
||||
using UnityEngine.TestTools.TestRunner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal abstract class BeforeAfterTestCommandBase<T> : DelegatingTestCommand, IEnumerableTestMethodCommand where T : class
|
||||
{
|
||||
private string m_BeforeErrorPrefix;
|
||||
private string m_AfterErrorPrefix;
|
||||
private bool m_SkipYieldAfterActions;
|
||||
protected BeforeAfterTestCommandBase(TestCommand innerCommand, string beforeErrorPrefix, string afterErrorPrefix, bool skipYieldAfterActions = false)
|
||||
: base(innerCommand)
|
||||
{
|
||||
m_BeforeErrorPrefix = beforeErrorPrefix;
|
||||
m_AfterErrorPrefix = afterErrorPrefix;
|
||||
m_SkipYieldAfterActions = skipYieldAfterActions;
|
||||
}
|
||||
|
||||
internal Func<long> GetUtcNow = () => new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
|
||||
|
||||
protected T[] BeforeActions = new T[0];
|
||||
|
||||
protected T[] AfterActions = new T[0];
|
||||
|
||||
protected static MethodInfo[] GetActions(IDictionary<Type, List<MethodInfo>> cacheStorage, Type fixtureType, Type attributeType, Type returnType)
|
||||
{
|
||||
if (cacheStorage.TryGetValue(fixtureType, out var result))
|
||||
{
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
cacheStorage[fixtureType] = GetMethodsWithAttributeFromFixture(fixtureType, attributeType, returnType);
|
||||
|
||||
return cacheStorage[fixtureType].ToArray();
|
||||
}
|
||||
|
||||
protected static T[] GetTestActions(IDictionary<MethodInfo, List<T>> cacheStorage, MethodInfo methodInfo)
|
||||
{
|
||||
if (cacheStorage.TryGetValue(methodInfo, out var result))
|
||||
{
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
var attributesForMethodInfo = new List<T>();
|
||||
var attributes = methodInfo.GetCustomAttributes(false);
|
||||
foreach (var attribute in attributes)
|
||||
{
|
||||
if (attribute is T attribute1)
|
||||
{
|
||||
attributesForMethodInfo.Add(attribute1);
|
||||
}
|
||||
}
|
||||
|
||||
cacheStorage[methodInfo] = attributesForMethodInfo;
|
||||
|
||||
return cacheStorage[methodInfo].ToArray();
|
||||
}
|
||||
|
||||
private static List<MethodInfo> GetMethodsWithAttributeFromFixture(Type fixtureType, Type setUpType, Type returnType)
|
||||
{
|
||||
MethodInfo[] methodsWithAttribute = Reflect.GetMethodsWithAttribute(fixtureType, setUpType, true);
|
||||
return methodsWithAttribute.Where(x => x.ReturnType == returnType).ToList();
|
||||
}
|
||||
|
||||
protected abstract IEnumerator InvokeBefore(T action, Test test, UnityTestExecutionContext context);
|
||||
|
||||
protected abstract IEnumerator InvokeAfter(T action, Test test, UnityTestExecutionContext context);
|
||||
|
||||
protected virtual bool MoveBeforeEnumerator(IEnumerator enumerator, Test test)
|
||||
{
|
||||
return enumerator.MoveNext();
|
||||
}
|
||||
|
||||
protected virtual bool MoveAfterEnumerator(IEnumerator enumerator, Test test)
|
||||
{
|
||||
return enumerator.MoveNext();
|
||||
}
|
||||
|
||||
protected abstract BeforeAfterTestCommandState GetState(UnityTestExecutionContext context);
|
||||
|
||||
public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
|
||||
{
|
||||
var unityContext = (UnityTestExecutionContext)context;
|
||||
var state = GetState(unityContext);
|
||||
|
||||
// When entering PlayMode state will incorrectly be seen as null. Looking at the hashcode to be certain that it is null.
|
||||
if (state?.GetHashCode() == null)
|
||||
{
|
||||
// We do not expect a state to exist in playmode
|
||||
state = ScriptableObject.CreateInstance<BeforeAfterTestCommandState>();
|
||||
}
|
||||
|
||||
state.ApplyTestResult(context.CurrentResult);
|
||||
|
||||
while (state.NextBeforeStepIndex < BeforeActions.Length)
|
||||
{
|
||||
state.Timestamp = GetUtcNow();
|
||||
var action = BeforeActions[state.NextBeforeStepIndex];
|
||||
IEnumerator enumerator;
|
||||
try
|
||||
{
|
||||
enumerator = InvokeBefore(action, Test, unityContext);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state.TestHasRun = true;
|
||||
context.CurrentResult.RecordPrefixedException(m_BeforeErrorPrefix, ex);
|
||||
break;
|
||||
}
|
||||
ActivePcHelper.SetEnumeratorPC(enumerator, state.NextBeforeStepPc);
|
||||
|
||||
using (var logScope = new LogScope())
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
logScope.EvaluateLogScope(true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_SkipYieldAfterActions) // Evaluate the log scope right away for the commands where we do not yield
|
||||
{
|
||||
logScope.EvaluateLogScope(true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state.TestHasRun = true;
|
||||
context.CurrentResult.RecordPrefixedException(m_BeforeErrorPrefix, ex);
|
||||
state.StoreTestResult(context.CurrentResult);
|
||||
break;
|
||||
}
|
||||
|
||||
state.NextBeforeStepPc = ActivePcHelper.GetEnumeratorPC(enumerator);
|
||||
state.StoreTestResult(context.CurrentResult);
|
||||
if (m_SkipYieldAfterActions)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return enumerator.Current;
|
||||
}
|
||||
|
||||
if (GetUtcNow() - state.Timestamp > unityContext.TestCaseTimeout || CoroutineTimedOut(unityContext))
|
||||
{
|
||||
context.CurrentResult.RecordPrefixedError(m_BeforeErrorPrefix, new UnityTestTimeoutException(unityContext.TestCaseTimeout).Message);
|
||||
state.TestHasRun = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.NextBeforeStepIndex++;
|
||||
state.NextBeforeStepPc = 0;
|
||||
}
|
||||
|
||||
if (!state.TestHasRun)
|
||||
{
|
||||
if (innerCommand is IEnumerableTestMethodCommand)
|
||||
{
|
||||
var executeEnumerable = ((IEnumerableTestMethodCommand)innerCommand).ExecuteEnumerable(context);
|
||||
foreach (var iterator in executeEnumerable)
|
||||
{
|
||||
state.StoreTestResult(context.CurrentResult);
|
||||
yield return iterator;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.CurrentResult = innerCommand.Execute(context);
|
||||
state.StoreTestResult(context.CurrentResult);
|
||||
}
|
||||
|
||||
state.TestHasRun = true;
|
||||
}
|
||||
|
||||
while (state.NextAfterStepIndex < AfterActions.Length)
|
||||
{
|
||||
state.Timestamp = GetUtcNow();
|
||||
state.TestAfterStarted = true;
|
||||
var action = AfterActions[state.NextAfterStepIndex];
|
||||
IEnumerator enumerator;
|
||||
try
|
||||
{
|
||||
enumerator = InvokeAfter(action, Test, unityContext);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.CurrentResult.RecordPrefixedException(m_AfterErrorPrefix, ex);
|
||||
state.StoreTestResult(context.CurrentResult);
|
||||
break;
|
||||
}
|
||||
ActivePcHelper.SetEnumeratorPC(enumerator, state.NextAfterStepPc);
|
||||
|
||||
using (var logScope = new LogScope())
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
logScope.EvaluateLogScope(true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_SkipYieldAfterActions) // Evaluate the log scope right away for the commands where we do not yield
|
||||
{
|
||||
logScope.EvaluateLogScope(true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.CurrentResult.RecordPrefixedException(m_AfterErrorPrefix, ex);
|
||||
state.StoreTestResult(context.CurrentResult);
|
||||
break;
|
||||
}
|
||||
|
||||
state.NextAfterStepPc = ActivePcHelper.GetEnumeratorPC(enumerator);
|
||||
state.StoreTestResult(context.CurrentResult);
|
||||
|
||||
|
||||
if (GetUtcNow() - state.Timestamp > unityContext.TestCaseTimeout || CoroutineTimedOut(unityContext))
|
||||
{
|
||||
context.CurrentResult.RecordPrefixedError(m_AfterErrorPrefix, new UnityTestTimeoutException(unityContext.TestCaseTimeout).Message);
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (m_SkipYieldAfterActions)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return enumerator.Current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.NextAfterStepIndex++;
|
||||
state.NextAfterStepPc = 0;
|
||||
}
|
||||
|
||||
state.Reset();
|
||||
}
|
||||
|
||||
public override TestResult Execute(ITestExecutionContext context)
|
||||
{
|
||||
throw new NotImplementedException("Use ExecuteEnumerable");
|
||||
}
|
||||
|
||||
private static TestCommandPcHelper pcHelper;
|
||||
private static bool CoroutineTimedOut(ITestExecutionContext unityContext)
|
||||
{
|
||||
if (string.IsNullOrEmpty(unityContext.CurrentResult.Message))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return unityContext.CurrentResult.ResultState.Equals(ResultState.Failure) &&
|
||||
unityContext.CurrentResult.Message.Contains(new UnityTestTimeoutException(unityContext.TestCaseTimeout).Message);
|
||||
}
|
||||
|
||||
|
||||
internal static TestCommandPcHelper ActivePcHelper
|
||||
{
|
||||
get
|
||||
{
|
||||
if (pcHelper == null)
|
||||
{
|
||||
pcHelper = new TestCommandPcHelper();
|
||||
}
|
||||
|
||||
return pcHelper;
|
||||
}
|
||||
set
|
||||
{
|
||||
pcHelper = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cbbca1d8a0434be4bbc7f165523763ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class BeforeAfterTestCommandState : ScriptableObject
|
||||
{
|
||||
public int NextBeforeStepIndex;
|
||||
public int NextBeforeStepPc;
|
||||
public int NextAfterStepIndex;
|
||||
public int NextAfterStepPc;
|
||||
public bool TestHasRun;
|
||||
public TestStatus CurrentTestResultStatus;
|
||||
public string CurrentTestResultLabel;
|
||||
public FailureSite CurrentTestResultSite;
|
||||
public string CurrentTestMessage;
|
||||
public string CurrentTestStrackTrace;
|
||||
public bool TestAfterStarted;
|
||||
public long Timestamp;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
NextBeforeStepIndex = 0;
|
||||
NextBeforeStepPc = 0;
|
||||
NextAfterStepIndex = 0;
|
||||
NextAfterStepPc = 0;
|
||||
TestHasRun = false;
|
||||
CurrentTestResultStatus = TestStatus.Inconclusive;
|
||||
CurrentTestResultLabel = null;
|
||||
CurrentTestResultSite = default(FailureSite);
|
||||
CurrentTestMessage = null;
|
||||
CurrentTestStrackTrace = null;
|
||||
TestAfterStarted = false;
|
||||
}
|
||||
|
||||
public void StoreTestResult(TestResult result)
|
||||
{
|
||||
CurrentTestResultStatus = result.ResultState.Status;
|
||||
CurrentTestResultLabel = result.ResultState.Label;
|
||||
CurrentTestResultSite = result.ResultState.Site;
|
||||
CurrentTestMessage = result.Message;
|
||||
CurrentTestStrackTrace = result.StackTrace;
|
||||
}
|
||||
|
||||
public void ApplyTestResult(TestResult result)
|
||||
{
|
||||
result.SetResult(new ResultState(CurrentTestResultStatus, CurrentTestResultLabel, CurrentTestResultSite), CurrentTestMessage, CurrentTestStrackTrace);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f65567c9026afb4db5de3355accc636
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,34 @@
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class EnumerableApplyChangesToContextCommand : ApplyChangesToContextCommand, IEnumerableTestMethodCommand
|
||||
{
|
||||
public EnumerableApplyChangesToContextCommand(TestCommand innerCommand, IEnumerable<IApplyToContext> changes)
|
||||
: base(innerCommand, changes) { }
|
||||
|
||||
public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
|
||||
{
|
||||
ApplyChanges(context);
|
||||
|
||||
if (innerCommand is IEnumerableTestMethodCommand)
|
||||
{
|
||||
var executeEnumerable = ((IEnumerableTestMethodCommand)innerCommand).ExecuteEnumerable(context);
|
||||
foreach (var iterator in executeEnumerable)
|
||||
{
|
||||
yield return iterator;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.CurrentResult = innerCommand.Execute(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b4429eff9fcffb48b006e8edcc90338
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class EnumerableRepeatedTestCommand : DelegatingTestCommand, IEnumerableTestMethodCommand
|
||||
{
|
||||
private int repeatCount;
|
||||
|
||||
public EnumerableRepeatedTestCommand(RepeatAttribute.RepeatedTestCommand commandToReplace) : base(commandToReplace.GetInnerCommand())
|
||||
{
|
||||
repeatCount = (int) typeof(RepeatAttribute.RepeatedTestCommand)
|
||||
.GetField("repeatCount", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
.GetValue(commandToReplace);
|
||||
}
|
||||
|
||||
public override TestResult Execute(ITestExecutionContext context)
|
||||
{
|
||||
throw new NotImplementedException("Use ExecuteEnumerable");
|
||||
}
|
||||
|
||||
public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
|
||||
{
|
||||
var unityContext = (UnityTestExecutionContext)context;
|
||||
if (unityContext.EnumerableTestState?.GetHashCode() == null)
|
||||
{
|
||||
unityContext.EnumerableTestState = new EnumerableTestState();
|
||||
}
|
||||
int count = unityContext.EnumerableTestState.Repeat;
|
||||
var firstCycleAfterResume = count > 0;
|
||||
|
||||
while (count < repeatCount || (firstCycleAfterResume && count <= repeatCount))
|
||||
{
|
||||
if (!firstCycleAfterResume)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
firstCycleAfterResume = false;
|
||||
unityContext.EnumerableTestState.Repeat = count;
|
||||
|
||||
if (innerCommand is IEnumerableTestMethodCommand)
|
||||
{
|
||||
var executeEnumerable = ((IEnumerableTestMethodCommand)innerCommand).ExecuteEnumerable(context);
|
||||
foreach (var iterator in executeEnumerable)
|
||||
{
|
||||
yield return iterator;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.CurrentResult = innerCommand.Execute(context);
|
||||
}
|
||||
|
||||
if (context.CurrentResult.ResultState != ResultState.Success)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unityContext.EnumerableTestState.Repeat = 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e273462feb9a65948826739f683cc9a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class EnumerableRetryTestCommand : DelegatingTestCommand, IEnumerableTestMethodCommand
|
||||
{
|
||||
private int retryCount;
|
||||
|
||||
public EnumerableRetryTestCommand(RetryAttribute.RetryCommand commandToReplace) : base(commandToReplace.GetInnerCommand())
|
||||
{
|
||||
retryCount = (int) typeof(RetryAttribute.RetryCommand)
|
||||
.GetField("_retryCount", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
.GetValue(commandToReplace);
|
||||
}
|
||||
|
||||
public override TestResult Execute(ITestExecutionContext context)
|
||||
{
|
||||
throw new NotImplementedException("Use ExecuteEnumerable");
|
||||
}
|
||||
|
||||
public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
|
||||
{
|
||||
var unityContext = (UnityTestExecutionContext)context;
|
||||
if (unityContext.EnumerableTestState?.GetHashCode() == null)
|
||||
{
|
||||
unityContext.EnumerableTestState = new EnumerableTestState();
|
||||
}
|
||||
int count = unityContext.EnumerableTestState.Retry;
|
||||
var firstCycleAfterResume = count > 0;
|
||||
|
||||
while (count < retryCount || (firstCycleAfterResume && count <= retryCount))
|
||||
{
|
||||
if (!firstCycleAfterResume)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
firstCycleAfterResume = false;
|
||||
|
||||
unityContext.EnumerableTestState.Retry = count;
|
||||
|
||||
if (innerCommand is IEnumerableTestMethodCommand)
|
||||
{
|
||||
var executeEnumerable = ((IEnumerableTestMethodCommand)innerCommand).ExecuteEnumerable(context);
|
||||
foreach (var iterator in executeEnumerable)
|
||||
{
|
||||
yield return iterator;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.CurrentResult = innerCommand.Execute(context);
|
||||
}
|
||||
|
||||
if (context.CurrentResult.ResultState != ResultState.Failure)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unityContext.EnumerableTestState.Retry = 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6de2f178a24cd2e48a0816cacd9a0583
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using Unity.Profiling;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class EnumerableSetUpTearDownCommand : BeforeAfterTestCommandBase<MethodInfo>
|
||||
{
|
||||
static readonly Dictionary<Type, List<MethodInfo>> m_BeforeActionsCache = new Dictionary<Type, List<MethodInfo>>();
|
||||
static readonly Dictionary<Type, List<MethodInfo>> m_AfterActionsCache = new Dictionary<Type, List<MethodInfo>>();
|
||||
|
||||
public EnumerableSetUpTearDownCommand(TestCommand innerCommand)
|
||||
: base(innerCommand, "SetUp", "TearDown")
|
||||
{
|
||||
using (new ProfilerMarker(nameof(EnumerableSetUpTearDownCommand)).Auto())
|
||||
{
|
||||
if (Test.TypeInfo.Type != null)
|
||||
{
|
||||
BeforeActions = GetActions(m_BeforeActionsCache, Test.TypeInfo.Type, typeof(UnitySetUpAttribute), typeof(IEnumerator));
|
||||
AfterActions = GetActions(m_AfterActionsCache, Test.TypeInfo.Type, typeof(UnityTearDownAttribute), typeof(IEnumerator)).Reverse().ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool MoveAfterEnumerator(IEnumerator enumerator, Test test)
|
||||
{
|
||||
using (new ProfilerMarker(test.Name + ".TearDown").Auto())
|
||||
return base.MoveAfterEnumerator(enumerator, test);
|
||||
}
|
||||
|
||||
protected override bool MoveBeforeEnumerator(IEnumerator enumerator, Test test)
|
||||
{
|
||||
using (new ProfilerMarker(test.Name + ".Setup").Auto())
|
||||
return base.MoveBeforeEnumerator(enumerator, test);
|
||||
}
|
||||
|
||||
protected override IEnumerator InvokeBefore(MethodInfo action, Test test, UnityTestExecutionContext context)
|
||||
{
|
||||
return (IEnumerator)Reflect.InvokeMethod(action, context.TestObject);
|
||||
}
|
||||
|
||||
protected override IEnumerator InvokeAfter(MethodInfo action, Test test, UnityTestExecutionContext context)
|
||||
{
|
||||
return (IEnumerator)Reflect.InvokeMethod(action, context.TestObject);
|
||||
}
|
||||
|
||||
protected override BeforeAfterTestCommandState GetState(UnityTestExecutionContext context)
|
||||
{
|
||||
return context.SetUpTearDownState;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd85a35169d313840a0874aea1a28629
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using NUnit.Framework.Internal.Execution;
|
||||
using UnityEngine.TestRunner.NUnitExtensions;
|
||||
using Unity.Profiling;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
using UnityEngine.TestTools.TestRunner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class EnumerableTestMethodCommand : TestCommand, IEnumerableTestMethodCommand
|
||||
{
|
||||
private readonly TestMethod testMethod;
|
||||
|
||||
public EnumerableTestMethodCommand(TestMethod testMethod)
|
||||
: base(testMethod)
|
||||
{
|
||||
this.testMethod = testMethod;
|
||||
}
|
||||
|
||||
public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
|
||||
{
|
||||
yield return null;
|
||||
|
||||
IEnumerator currentExecutingTestEnumerator;
|
||||
try
|
||||
{
|
||||
currentExecutingTestEnumerator = new TestEnumeratorWrapper(testMethod).GetEnumerator(context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.CurrentResult.RecordException(ex);
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (currentExecutingTestEnumerator != null)
|
||||
{
|
||||
var testEnumeraterYieldInstruction = new TestEnumerator(context, currentExecutingTestEnumerator);
|
||||
|
||||
yield return testEnumeraterYieldInstruction;
|
||||
|
||||
var enumerator = testEnumeraterYieldInstruction.Execute();
|
||||
|
||||
var executingEnumerator = ExecuteEnumerableAndRecordExceptions(enumerator, new EnumeratorContext(context));
|
||||
while (AdvanceEnumerator(executingEnumerator))
|
||||
{
|
||||
yield return executingEnumerator.Current;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context.CurrentResult.ResultState != ResultState.Ignored)
|
||||
{
|
||||
context.CurrentResult.SetResult(ResultState.Success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool AdvanceEnumerator(IEnumerator enumerator)
|
||||
{
|
||||
using (new ProfilerMarker(testMethod.MethodName).Auto())
|
||||
return enumerator.MoveNext();
|
||||
}
|
||||
|
||||
private IEnumerator ExecuteEnumerableAndRecordExceptions(IEnumerator enumerator, EnumeratorContext context)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (context.ExceptionWasRecorded)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.RecordExceptionWithHint(ex);
|
||||
break;
|
||||
}
|
||||
|
||||
if (enumerator.Current is IEnumerator nestedEnumerator)
|
||||
{
|
||||
yield return ExecuteEnumerableAndRecordExceptions(nestedEnumerator, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return enumerator.Current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class EnumeratorContext
|
||||
{
|
||||
private readonly ITestExecutionContext m_Context;
|
||||
|
||||
public EnumeratorContext(ITestExecutionContext context)
|
||||
{
|
||||
m_Context = context;
|
||||
}
|
||||
|
||||
public bool ExceptionWasRecorded
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public void RecordExceptionWithHint(Exception ex)
|
||||
{
|
||||
if (ExceptionWasRecorded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_Context.CurrentResult.RecordException(ex);
|
||||
ExceptionWasRecorded = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override TestResult Execute(ITestExecutionContext context)
|
||||
{
|
||||
throw new NotImplementedException("Use ExecuteEnumerable");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19a6f000f81e24c4a826c1abd43e77c7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
[Serializable]
|
||||
internal class EnumerableTestState
|
||||
{
|
||||
public int Repeat;
|
||||
public int Retry;
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 356852e4738840b4b1ab533d3a66f0e1
|
||||
timeCreated: 1606321047
|
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class ImmediateEnumerableCommand : DelegatingTestCommand
|
||||
{
|
||||
public ImmediateEnumerableCommand(TestCommand innerCommand)
|
||||
: base(innerCommand) { }
|
||||
|
||||
public override TestResult Execute(ITestExecutionContext context)
|
||||
{
|
||||
if (innerCommand is IEnumerableTestMethodCommand)
|
||||
{
|
||||
var executeEnumerable = ((IEnumerableTestMethodCommand)innerCommand).ExecuteEnumerable(context);
|
||||
foreach (var iterator in executeEnumerable)
|
||||
{
|
||||
if (iterator != null)
|
||||
{
|
||||
throw new Exception("Only null can be yielded at this point.");
|
||||
}
|
||||
}
|
||||
return context.CurrentResult;
|
||||
}
|
||||
|
||||
return innerCommand.Execute(context);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8349e42a2b30c7a4abd8678c203428ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,38 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class OuterUnityTestActionCommand : BeforeAfterTestCommandBase<IOuterUnityTestAction>
|
||||
{
|
||||
static readonly Dictionary<MethodInfo, List<IOuterUnityTestAction>> m_TestActionsCache = new Dictionary<MethodInfo, List<IOuterUnityTestAction>>();
|
||||
public OuterUnityTestActionCommand(TestCommand innerCommand)
|
||||
: base(innerCommand, "BeforeTest", "AfterTest")
|
||||
{
|
||||
if (Test.TypeInfo.Type != null)
|
||||
{
|
||||
BeforeActions = GetTestActions(m_TestActionsCache, Test.Method.MethodInfo);
|
||||
AfterActions = BeforeActions;
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerator InvokeBefore(IOuterUnityTestAction action, Test test, UnityTestExecutionContext context)
|
||||
{
|
||||
return action.BeforeTest(test);
|
||||
}
|
||||
|
||||
protected override IEnumerator InvokeAfter(IOuterUnityTestAction action, Test test, UnityTestExecutionContext context)
|
||||
{
|
||||
return action.AfterTest(test);
|
||||
}
|
||||
|
||||
protected override BeforeAfterTestCommandState GetState(UnityTestExecutionContext context)
|
||||
{
|
||||
return context.OuterUnityTestActionState;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d4fc309a0784294c8ab658b53b12320
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using Unity.Profiling;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class SetUpTearDownCommand : BeforeAfterTestCommandBase<MethodInfo>
|
||||
{
|
||||
static readonly Dictionary<Type, List<MethodInfo>> m_BeforeActionsCache = new Dictionary<Type, List<MethodInfo>>();
|
||||
static readonly Dictionary<Type, List<MethodInfo>> m_AfterActionsCache = new Dictionary<Type, List<MethodInfo>>();
|
||||
|
||||
public SetUpTearDownCommand(TestCommand innerCommand)
|
||||
: base(innerCommand, "SetUp", "TearDown", true)
|
||||
{
|
||||
using (new ProfilerMarker(nameof(SetUpTearDownCommand)).Auto())
|
||||
{
|
||||
if (Test.TypeInfo.Type != null)
|
||||
{
|
||||
BeforeActions = GetActions(m_BeforeActionsCache, Test.TypeInfo.Type, typeof(SetUpAttribute), typeof(void));
|
||||
AfterActions = GetActions(m_AfterActionsCache, Test.TypeInfo.Type, typeof(TearDownAttribute), typeof(void)).Reverse().ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerator InvokeBefore(MethodInfo action, Test test, UnityTestExecutionContext context)
|
||||
{
|
||||
using (new ProfilerMarker(test.Name + ".Setup").Auto())
|
||||
Reflect.InvokeMethod(action, context.TestObject);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
protected override IEnumerator InvokeAfter(MethodInfo action, Test test, UnityTestExecutionContext context)
|
||||
{
|
||||
using (new ProfilerMarker(test.Name + ".TearDown").Auto())
|
||||
Reflect.InvokeMethod(action, context.TestObject);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
protected override BeforeAfterTestCommandState GetState(UnityTestExecutionContext context)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e0db3f3921670cd4ca2e925737c3fba4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,42 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Runner;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class TestActionCommand : BeforeAfterTestCommandBase<ITestAction>
|
||||
{
|
||||
static readonly Dictionary<MethodInfo, List<ITestAction>> m_TestActionsCache = new Dictionary<MethodInfo, List<ITestAction>>();
|
||||
|
||||
public TestActionCommand(TestCommand innerCommand)
|
||||
: base(innerCommand, "BeforeTest", "AfterTest", true)
|
||||
{
|
||||
if (Test.TypeInfo.Type != null)
|
||||
{
|
||||
BeforeActions = GetTestActions(m_TestActionsCache, Test.Method.MethodInfo);
|
||||
AfterActions = BeforeActions;
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerator InvokeBefore(ITestAction action, Test test, UnityTestExecutionContext context)
|
||||
{
|
||||
action.BeforeTest(test);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
protected override IEnumerator InvokeAfter(ITestAction action, Test test, UnityTestExecutionContext context)
|
||||
{
|
||||
action.AfterTest(test);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
protected override BeforeAfterTestCommandState GetState(UnityTestExecutionContext context)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2de8ba3b840049641897e0da7ce1d5cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class TestCommandPcHelper
|
||||
{
|
||||
public virtual void SetEnumeratorPC(IEnumerator enumerator, int pc)
|
||||
{
|
||||
// Noop implementation used in playmode.
|
||||
}
|
||||
|
||||
public virtual int GetEnumeratorPC(IEnumerator enumerator)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33e6b78c96bb0694e96383e3c56b7b54
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using NUnit.Framework.Internal;
|
||||
using NUnit.Framework.Internal.Commands;
|
||||
using Unity.Profiling;
|
||||
|
||||
namespace UnityEngine.TestTools
|
||||
{
|
||||
internal class UnityTestMethodCommand : TestMethodCommand
|
||||
{
|
||||
public UnityTestMethodCommand(TestMethod testMethod)
|
||||
: base(testMethod) { }
|
||||
|
||||
public override TestResult Execute(ITestExecutionContext context)
|
||||
{
|
||||
using (new ProfilerMarker(Test.FullName).Auto())
|
||||
return base.Execute(context);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2ca9278c9dd49df877d622d0f657ecf
|
||||
timeCreated: 1614093428
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user