Initial commit
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "BracerLib.Tests",
|
||||
"rootNamespace": "BracerLib.Tests",
|
||||
"references": [
|
||||
"UnityEngine.TestRunner",
|
||||
"BracerLib"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll",
|
||||
"Moq.dll"
|
||||
],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f994df8a4a2196f499e769b079127c12
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace BracerLib.Tests
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
[ExcludeFromCoverage]
|
||||
public class MonoBehaviourTester : MonoBehaviour, IMonoBehaviourTest
|
||||
{
|
||||
public virtual bool IsTestFinished { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e2baafc97e51834e89c53aaa65ddd67
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ca20ad462434c06ad77f83ad433b8e3
|
||||
timeCreated: 1778953578
|
||||
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
|
||||
namespace BracerLib.Tests.Objects
|
||||
{
|
||||
public class ObjectLifetimeTests : TestBase
|
||||
{
|
||||
private class SomeDisposable : IDisposable
|
||||
{
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed)
|
||||
return;
|
||||
|
||||
IsDisposed = true;
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
private SomeDisposable disposableObject;
|
||||
private SomeDisposable disposableFuncObject;
|
||||
private GameObject singleTestLifetimeObject;
|
||||
private GameObject singleTestLifetimeFuncObject;
|
||||
private GameObject completeTestLifetimeObject;
|
||||
private GameObject completeTestLifetimeFuncObject;
|
||||
private bool singleTestWasCreated;
|
||||
|
||||
[UnityTest, Order(1)]
|
||||
public IEnumerator SetUpOneTimeObjects()
|
||||
{
|
||||
completeTestLifetimeObject = new GameObject("full lifetime");
|
||||
RegisterOneTimeTestObject(completeTestLifetimeObject);
|
||||
|
||||
yield return null;
|
||||
Assert.IsTrue(completeTestLifetimeObject != null);
|
||||
|
||||
completeTestLifetimeFuncObject = RegisterOneTimeTestObject(GetNewObject);
|
||||
|
||||
yield return null;
|
||||
Assert.IsTrue(completeTestLifetimeFuncObject != null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not here to test Unity code, but want to run through a basic shift of the object position.
|
||||
/// </summary>
|
||||
[UnityTest, Order(2)]
|
||||
public IEnumerator TempUnityObjectMovesCorrectly()
|
||||
{
|
||||
Assert.IsFalse(singleTestWasCreated);
|
||||
|
||||
singleTestLifetimeObject = new GameObject("singleTestLifetime");
|
||||
RegisterTempTestObject(singleTestLifetimeObject);
|
||||
singleTestLifetimeFuncObject = RegisterTempTestObject(GetNewObject);
|
||||
singleTestWasCreated = true;
|
||||
|
||||
Assert.IsTrue(singleTestWasCreated);
|
||||
|
||||
yield return null;
|
||||
|
||||
var testTransform = singleTestLifetimeObject.transform;
|
||||
var tPos = testTransform.position;
|
||||
var lastPos = tPos;
|
||||
tPos = Vector3.one;
|
||||
testTransform.position = tPos;
|
||||
|
||||
Assert.IsTrue(tPos != lastPos);
|
||||
|
||||
testTransform.Translate(Vector3.up);
|
||||
|
||||
yield return null;
|
||||
|
||||
tPos = testTransform.position;
|
||||
|
||||
Assert.IsTrue(tPos != lastPos);
|
||||
}
|
||||
|
||||
[UnityTest, Order(3)]
|
||||
public IEnumerator TempUnityObjectNoLongerExistsAfterPreviousTest()
|
||||
{
|
||||
Assert.IsTrue(singleTestWasCreated);
|
||||
Assert.IsNull(singleTestLifetimeObject);
|
||||
Assert.IsNull(singleTestLifetimeFuncObject);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
[UnityTest, Order(4)]
|
||||
public IEnumerator OneTimeObjectStillExists()
|
||||
{
|
||||
Assert.IsTrue(completeTestLifetimeObject != null);
|
||||
Assert.IsTrue(completeTestLifetimeFuncObject != null);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
[Test, Order(5)]
|
||||
public void RegisterDisposableObject()
|
||||
{
|
||||
disposableObject = new SomeDisposable();
|
||||
RegisterDisposableTempTestObject(disposableObject);
|
||||
Assert.IsNotNull(disposableObject);
|
||||
Assert.IsFalse(disposableObject.IsDisposed);
|
||||
|
||||
disposableFuncObject = RegisterDisposableTempTestObject(() => new SomeDisposable());
|
||||
Assert.IsNotNull(disposableFuncObject);
|
||||
Assert.IsFalse(disposableFuncObject.IsDisposed);
|
||||
}
|
||||
|
||||
[Test, Order(6)]
|
||||
public void CheckIfDisposableObjectHasDisposed()
|
||||
{
|
||||
Assert.IsNotNull(disposableObject);
|
||||
Assert.IsTrue(disposableObject.IsDisposed);
|
||||
|
||||
disposableObject = null;
|
||||
|
||||
Assert.IsNotNull(disposableFuncObject);
|
||||
Assert.IsTrue(disposableFuncObject.IsDisposed);
|
||||
|
||||
disposableObject = null;
|
||||
}
|
||||
|
||||
private GameObject GetNewObject() => new GameObject();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78520c491186453a91097eac4579ed75
|
||||
timeCreated: 1778931474
|
||||
@@ -0,0 +1,55 @@
|
||||
using System.Collections;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BracerLib.Tests.Objects
|
||||
{
|
||||
public interface ITester
|
||||
{
|
||||
void Test();
|
||||
}
|
||||
|
||||
public class Tester : ITester
|
||||
{
|
||||
public void Test() {}
|
||||
}
|
||||
|
||||
public class MockComponent : MonoBehaviour
|
||||
{
|
||||
private ITester tester;
|
||||
|
||||
public void DoTest()
|
||||
{
|
||||
tester.Test();
|
||||
}
|
||||
}
|
||||
|
||||
public class ObjectMockTests : TestBase
|
||||
{
|
||||
private MockComponent mockComponent;
|
||||
private Mock<ITester> testerMock;
|
||||
|
||||
protected override IEnumerator UnityOneTimeSetUp()
|
||||
{
|
||||
testerMock = new Mock<ITester>();
|
||||
|
||||
var go = new GameObject("mock test obj");
|
||||
mockComponent = go.AddComponent<MockComponent>();
|
||||
RegisterOneTimeTestObject(go);
|
||||
SetReflectedValue(mockComponent, "tester", testerMock.Object);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMock()
|
||||
{
|
||||
testerMock.Setup(x => x.Test());
|
||||
|
||||
mockComponent.DoTest();
|
||||
|
||||
testerMock.Verify(x => x.Test(), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45e688432fb9423e8efb7c88cdbd9785
|
||||
timeCreated: 1779762115
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82e81a731adf4d6fbab5315db59006d2
|
||||
timeCreated: 1778983978
|
||||
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace BracerLib.Tests.Properties
|
||||
{
|
||||
public class PropertyTests : TestBase
|
||||
{
|
||||
public class SomeObject : MonoBehaviour
|
||||
{
|
||||
public DependencyA dependencyA;
|
||||
|
||||
[SerializeField]
|
||||
private DependencyB dependencyB1;
|
||||
[SerializeField]
|
||||
private DependencyB dependencyB2;
|
||||
[SerializeField]
|
||||
private DependencyB dependencyB3;
|
||||
|
||||
private DependencyC dependencyC;
|
||||
private DependencyD dependencyD;
|
||||
private ValueDependency valueDependency;
|
||||
private int someValue;
|
||||
|
||||
public DependencyB DependencyB1 => dependencyB1;
|
||||
public DependencyB DependencyB2 => dependencyB2;
|
||||
public DependencyB DependencyB3 => dependencyB3;
|
||||
public DependencyC DependencyC => dependencyC;
|
||||
public DependencyD DependencyD => dependencyD;
|
||||
public ValueDependency ValueDependency => valueDependency;
|
||||
public int SomeValue => someValue;
|
||||
}
|
||||
|
||||
public class DependencyA : MonoBehaviour
|
||||
{
|
||||
public int Value => 1;
|
||||
}
|
||||
|
||||
public class DependencyB : MonoBehaviour
|
||||
{
|
||||
public int Value => 2;
|
||||
}
|
||||
|
||||
public class DependencyC : MonoBehaviour
|
||||
{
|
||||
public int Value => 3;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class DependencyD { }
|
||||
|
||||
public struct ValueDependency
|
||||
{
|
||||
public int Value;
|
||||
}
|
||||
|
||||
private GameObject setupGameObject;
|
||||
private SomeObject setupSomeObject;
|
||||
private DependencyA setupDependencyA;
|
||||
|
||||
protected override IEnumerator UnityOneTimeSetUp()
|
||||
{
|
||||
setupGameObject = new GameObject("setup");
|
||||
setupSomeObject = setupGameObject.AddComponent<SomeObject>();
|
||||
setupDependencyA = setupGameObject.AddComponent<DependencyA>();
|
||||
|
||||
setupSomeObject.dependencyA = setupDependencyA;
|
||||
RegisterOneTimeTestObject(setupSomeObject);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestProperties()
|
||||
{
|
||||
Assert.IsNotNull(setupSomeObject);
|
||||
Assert.IsNotNull(setupDependencyA);
|
||||
|
||||
// Set Serialized private Mono
|
||||
var depB = new[] { setupGameObject.AddComponent<DependencyB>(), setupGameObject.AddComponent<DependencyB>(), setupGameObject.AddComponent<DependencyB>() };
|
||||
SetObjectReference(setupSomeObject, "dependencyB1", depB[0]);
|
||||
SetObjectReferences(setupSomeObject, ("dependencyB2", depB[1]), ("dependencyB3", depB[2]));
|
||||
|
||||
// Set Reflected private Mono
|
||||
var depC = setupGameObject.AddComponent<DependencyC>();
|
||||
SetReflectedValue(setupSomeObject, "dependencyC", depC);
|
||||
|
||||
// Set Reflected private POCO
|
||||
// Set Reflected private value
|
||||
var depD = new DependencyD();
|
||||
var valueDependency = new ValueDependency { Value = 255 };
|
||||
SetReflectedValues(setupSomeObject, ("dependencyD", depD), ("valueDependency", valueDependency));
|
||||
|
||||
yield return null;
|
||||
|
||||
Assert.IsNotNull(depB[0]);
|
||||
Assert.IsNotNull(setupSomeObject.DependencyB1);
|
||||
Assert.AreEqual(depB[0], setupSomeObject.DependencyB1);
|
||||
|
||||
Assert.IsNotNull(depB[1]);
|
||||
Assert.IsNotNull(setupSomeObject.DependencyB2);
|
||||
Assert.AreEqual(depB[1], setupSomeObject.DependencyB2);
|
||||
|
||||
Assert.IsNotNull(depB[2]);
|
||||
Assert.IsNotNull(setupSomeObject.DependencyB3);
|
||||
Assert.AreEqual(depB[2], setupSomeObject.DependencyB3);
|
||||
|
||||
Assert.IsNotNull(depC);
|
||||
Assert.IsNotNull(setupSomeObject.DependencyC);
|
||||
Assert.AreEqual(depC, setupSomeObject.DependencyC);
|
||||
|
||||
Assert.IsNotNull(depD);
|
||||
Assert.IsNotNull(setupSomeObject.DependencyD);
|
||||
Assert.AreEqual(depD, setupSomeObject.DependencyD);
|
||||
|
||||
Assert.AreEqual(setupSomeObject.ValueDependency.Value, valueDependency.Value);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestPropertyErrors()
|
||||
{
|
||||
yield return null;
|
||||
|
||||
SetReflectedValue(setupSomeObject, "someFakeValue", 1);
|
||||
LogAssert.Expect(LogType.Warning, "There is no property someFakeValue to the target object.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce9835c5996a47e6a286fabb5d421d3e
|
||||
timeCreated: 1778983994
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f662576f6c6c422d810fcd5290ec107c
|
||||
timeCreated: 1778977478
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Collections;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace BracerLib.Tests.Scenes
|
||||
{
|
||||
public class SceneTests : TestBase
|
||||
{
|
||||
private Scene oneTimeScene;
|
||||
private Scene testScene;
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator CloseSceneWithZeroScenesRegistered()
|
||||
{
|
||||
var sceneCount = SceneManager.loadedSceneCount;
|
||||
Assert.IsTrue(sceneCount > 0);
|
||||
|
||||
yield return CloseLatestScene();
|
||||
|
||||
Assert.IsTrue(SceneManager.loadedSceneCount == sceneCount);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator CreateScenesWithSpecificLifetimes()
|
||||
{
|
||||
yield return OpenScene("Scenes/Tests/Test_Empty", true);
|
||||
oneTimeScene = SceneManager.GetSceneAt(SceneManager.loadedSceneCount - 1);
|
||||
Assert.IsTrue(oneTimeScene.isLoaded);
|
||||
|
||||
yield return OpenScene("Scenes/Tests/Test_Empty");
|
||||
testScene = SceneManager.GetSceneAt(SceneManager.loadedSceneCount - 1);
|
||||
Assert.IsTrue(testScene.isLoaded);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TestSceneLifetimes()
|
||||
{
|
||||
yield return null;
|
||||
|
||||
Assert.IsTrue(oneTimeScene.isLoaded);
|
||||
Assert.IsFalse(testScene.isLoaded);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c5d9b3d87fe4f1dab685f84ed847fdf
|
||||
timeCreated: 1778977483
|
||||
@@ -0,0 +1,413 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.TestTools;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace BracerLib.Tests
|
||||
{
|
||||
[ExcludeFromCodeCoverage, ExcludeFromCoverage]
|
||||
public class TestBase
|
||||
{
|
||||
// private readonly IDictionary<Object, SerializedObject> globalPropertyCache;
|
||||
private readonly IDictionary<Object, SerializedObject> objectPropertyCache;
|
||||
private readonly Queue<Object> destroyOnTestEnd;
|
||||
private readonly Stack<Scene> closeOnTestEnd;
|
||||
private readonly Queue<IDisposable> disposeOnTestEnd;
|
||||
private readonly Queue<Object> destroyOnOneTimeEnd;
|
||||
private readonly Stack<Scene> closeOnOneTimeEnd;
|
||||
private readonly Queue<IDisposable> disposeOnOneTimeEnd;
|
||||
|
||||
[ExcludeFromCoverage]
|
||||
protected TestBase()
|
||||
{
|
||||
// globalPropertyCache = new Dictionary<Object, SerializedObject>();
|
||||
objectPropertyCache = new Dictionary<Object, SerializedObject>();
|
||||
destroyOnTestEnd = new Queue<Object>();
|
||||
closeOnTestEnd = new Stack<Scene>();
|
||||
disposeOnTestEnd = new Queue<IDisposable>();
|
||||
destroyOnOneTimeEnd = new Queue<Object>();
|
||||
closeOnOneTimeEnd = new Stack<Scene>();
|
||||
disposeOnOneTimeEnd = new Queue<IDisposable>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called as part of NUnit framework. Override <see cref="OneTimeSetUp"/> instead.
|
||||
/// </summary>
|
||||
[OneTimeSetUp, ExcludeFromCoverage]
|
||||
public void DoOneTimeSetUp()
|
||||
{
|
||||
OneTimeSetUp();
|
||||
}
|
||||
|
||||
[UnityOneTimeSetUp, ExcludeFromCoverage]
|
||||
public IEnumerator DoUnityOneTimeSetUp()
|
||||
{
|
||||
yield return UnityOneTimeSetUp();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called as part of NUnit framework. Override <see cref="SetUp"/> instead.
|
||||
/// </summary>
|
||||
[SetUp, ExcludeFromCoverage]
|
||||
public void DoSetUp()
|
||||
{
|
||||
SetUp();
|
||||
}
|
||||
|
||||
[UnitySetUp, ExcludeFromCoverage]
|
||||
public IEnumerator DoUnitySetUp()
|
||||
{
|
||||
yield return UnitySetUp();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called as part of NUnit framework. Override <see cref="TearDown"/> instead.
|
||||
/// </summary>
|
||||
[TearDown, ExcludeFromCoverage]
|
||||
public void DoTearDown()
|
||||
{
|
||||
TearDown();
|
||||
|
||||
objectPropertyCache.Clear();
|
||||
}
|
||||
|
||||
[UnityTearDown, ExcludeFromCoverage]
|
||||
public IEnumerator DoUnityTearDown()
|
||||
{
|
||||
yield return UnityTearDown();
|
||||
|
||||
Reset();
|
||||
|
||||
while (closeOnTestEnd.Count > 0)
|
||||
yield return CloseLatestScene();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called as part of NUnit framework. Override <see cref="OneTimeTearDown"/> instead.
|
||||
/// </summary>
|
||||
[OneTimeTearDown, ExcludeFromCoverage]
|
||||
public void DoOneTimeTearDown()
|
||||
{
|
||||
OneTimeTearDown();
|
||||
}
|
||||
|
||||
[UnityOneTimeTearDown, ExcludeFromCoverage]
|
||||
public IEnumerator DoUnityOneTimeTearDown()
|
||||
{
|
||||
yield return UnityOneTimeTearDown();
|
||||
|
||||
CleanupUnityObjects(destroyOnOneTimeEnd);
|
||||
CleanupDisposableObjects(disposeOnOneTimeEnd);
|
||||
|
||||
while (closeOnOneTimeEnd.Count > 0)
|
||||
yield return CloseLatestScene(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pass a Unity object that will be destroyed at the end of the test.
|
||||
/// </summary>
|
||||
protected T RegisterTempTestObject<T>(T obj) where T : Object
|
||||
{
|
||||
destroyOnTestEnd.Enqueue(obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pass a function that generates or returns a Unity object that will be destroyed at the end of the test.
|
||||
/// </summary>
|
||||
protected T RegisterTempTestObject<T>(Func<T> generator) where T : Object
|
||||
{
|
||||
var obj = generator();
|
||||
|
||||
return RegisterTempTestObject(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pass a Unity object that will be destroyed at the end of all the tests in a given suite.
|
||||
/// </summary>
|
||||
protected T RegisterOneTimeTestObject<T>(T obj) where T : Object
|
||||
{
|
||||
destroyOnOneTimeEnd.Enqueue(obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pass a function that generates or returns a Unity object that will be destroyed at the end of all the tests in a given suite.
|
||||
/// </summary>
|
||||
protected T RegisterOneTimeTestObject<T>(Func<T> generator) where T : Object
|
||||
{
|
||||
var obj = generator();
|
||||
|
||||
return RegisterOneTimeTestObject(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pass a disposable object that will be cleaned up at the end of the test.
|
||||
/// </summary>
|
||||
protected T RegisterDisposableTempTestObject<T>(T obj) where T : IDisposable
|
||||
{
|
||||
disposeOnTestEnd.Enqueue(obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pass a function that generates or returns a disposable object that will be cleaned up at the end of the test.
|
||||
/// </summary>
|
||||
/// <param name="generator"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
protected T RegisterDisposableTempTestObject<T>(Func<T> generator) where T : IDisposable
|
||||
{
|
||||
var obj = generator();
|
||||
|
||||
return RegisterDisposableTempTestObject(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pass a disposable object that will be cleaned up at the end of the test.
|
||||
/// </summary>
|
||||
protected T RegisterDisposableOneTimeTestObject<T>(T obj) where T : IDisposable
|
||||
{
|
||||
disposeOnOneTimeEnd.Enqueue(obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pass a function that generates or returns a disposable object that will be cleaned up at the end of the test.
|
||||
/// </summary>
|
||||
/// <param name="generator"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
protected T RegisterDisposableOneTimeTestObject<T>(Func<T> generator) where T : IDisposable
|
||||
{
|
||||
var obj = generator();
|
||||
|
||||
return RegisterDisposableOneTimeTestObject(obj);
|
||||
}
|
||||
|
||||
protected IEnumerator OpenScene(string scenePath, bool isOneTime = false)
|
||||
{
|
||||
var asyncOp = SceneManager.LoadSceneAsync(scenePath, LoadSceneMode.Additive);
|
||||
asyncOp!.completed += SetLoadedSceneActive;
|
||||
|
||||
yield return asyncOp;
|
||||
|
||||
var loadedScene = SceneManager.GetSceneAt(SceneManager.loadedSceneCount - 1);
|
||||
if (!isOneTime)
|
||||
closeOnTestEnd.Push(loadedScene);
|
||||
else
|
||||
closeOnOneTimeEnd.Push(loadedScene);
|
||||
}
|
||||
|
||||
protected IEnumerator CloseLatestScene(bool isOneTime = false)
|
||||
{
|
||||
var targetStack = !isOneTime ? closeOnTestEnd : closeOnOneTimeEnd;
|
||||
|
||||
if (!targetStack.TryPop(out var targetScene))
|
||||
yield break;
|
||||
|
||||
var asyncOp = SceneManager.UnloadSceneAsync(targetScene);
|
||||
asyncOp!.completed += SetLoadedSceneActive;
|
||||
|
||||
yield return asyncOp;
|
||||
}
|
||||
|
||||
protected void SetLoadedSceneActive(AsyncOperation asyncOperation)
|
||||
{
|
||||
SceneManager.SetActiveScene(SceneManager.GetSceneAt(SceneManager.loadedSceneCount - 1));
|
||||
}
|
||||
|
||||
[ExcludeFromCoverage]
|
||||
protected virtual void OneTimeSetUp() { }
|
||||
|
||||
[ExcludeFromCoverage]
|
||||
protected virtual IEnumerator UnityOneTimeSetUp()
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
protected virtual void SetUp() { }
|
||||
|
||||
protected virtual IEnumerator UnitySetUp()
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
protected virtual void TearDown() { }
|
||||
|
||||
protected virtual IEnumerator UnityTearDown()
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
[ExcludeFromCoverage]
|
||||
protected virtual void OneTimeTearDown() { }
|
||||
|
||||
[ExcludeFromCoverage]
|
||||
protected virtual IEnumerator UnityOneTimeTearDown()
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a private value member of an object via C# reflection.
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// public class SomeObject {
|
||||
/// private int item;
|
||||
/// }
|
||||
///
|
||||
/// var obj = new SomeObject();
|
||||
/// SetReflectedValue(obj, "item", 25);
|
||||
/// </code></example>
|
||||
private protected void SetReflectedValue(object targetObject, string targetProperty, object targetValue)
|
||||
{
|
||||
SetReflectedValue(targetObject, targetObject.GetType(), targetProperty, targetValue);
|
||||
}
|
||||
|
||||
private protected void SetReflectedValues(object targetObject, params ValueTuple<string, object>[] properties)
|
||||
{
|
||||
var type = targetObject.GetType();
|
||||
|
||||
for (var i = 0; i < properties.Length; i++)
|
||||
SetReflectedValue(targetObject, type, properties[i].Item1, properties[i].Item2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a non-interface reference member of a MonoBehaviour via Unity reflection.
|
||||
/// Will be applied depending on context of Test setup being used.
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// public class SomeOtherObject { }
|
||||
///
|
||||
/// public class SomeObject : MonoBehaviour {
|
||||
/// private SomeOtherObject item;
|
||||
/// }
|
||||
///
|
||||
/// var gameObj = new GameObject("SomeObj");
|
||||
/// var c = gameObj.AddComponent(typeof(SomeObject));
|
||||
/// var someOtherObj = new SomeOtherObj();
|
||||
///
|
||||
/// SetObjectReference(c, "item", someOtherObj);
|
||||
/// </code></example>
|
||||
private protected void SetObjectReference(Object targetObj, string targetValue, Object value)
|
||||
{
|
||||
if (!objectPropertyCache.TryGetValue(targetObj, out var serializedObject))
|
||||
{
|
||||
serializedObject = new SerializedObject(targetObj);
|
||||
objectPropertyCache.Add(targetObj, serializedObject);
|
||||
}
|
||||
|
||||
var property = serializedObject.FindProperty(targetValue);
|
||||
property.objectReferenceValue = value;
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a non-interface reference member of a MonoBehaviour via Unity reflection.
|
||||
/// Will be applied depending on context of Test setup being used.
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// public class SomeObject : MonoBehaviour {
|
||||
/// private SomeOtherObject item1;
|
||||
/// private SomeAdditionalObject item2;
|
||||
/// }
|
||||
///
|
||||
/// var gameObj = new GameObject("SomeObj");
|
||||
/// var c = gameObj.AddComponent(typeof(SomeObject));
|
||||
///
|
||||
/// SetObjectReference(c, a);
|
||||
/// </code></example>
|
||||
private protected void SetObjectReferences(Object targetObj, params ValueTuple<string, Object>[] properties)
|
||||
{
|
||||
for (var i = 0; i < properties.Length; i++)
|
||||
SetObjectReference(targetObj, properties[i].Item1, properties[i].Item2);
|
||||
}
|
||||
|
||||
private void SetReflectedValue(object targetObject, Type type, string targetProperty, object targetValue)
|
||||
{
|
||||
var fieldProperty = type.GetField(targetProperty, BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
if (fieldProperty == null)
|
||||
{
|
||||
Debug.LogWarning($"There is no property {targetProperty} to the target object.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fieldProperty.SetValue(targetObject, targetValue);
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
ResetAllMocks();
|
||||
CleanupDisposableObjects(disposeOnTestEnd);
|
||||
CleanupUnityObjects(destroyOnTestEnd);
|
||||
}
|
||||
|
||||
private void CleanupUnityObjects(Queue<Object> unityObjects)
|
||||
{
|
||||
if (unityObjects.Count == 0)
|
||||
return;
|
||||
|
||||
while (unityObjects.Count != 0)
|
||||
{
|
||||
var temp = unityObjects.Dequeue();
|
||||
if (temp != null)
|
||||
Object.DestroyImmediate(temp);
|
||||
}
|
||||
}
|
||||
|
||||
private void CleanupDisposableObjects(Queue<IDisposable> disposableObjects)
|
||||
{
|
||||
if (disposableObjects.Count == 0)
|
||||
return;
|
||||
|
||||
while (disposableObjects.Count != 0)
|
||||
{
|
||||
var temp = disposableObjects.Dequeue();
|
||||
temp?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
[ExcludeFromCoverage]
|
||||
private void ResetAllMocks()
|
||||
{
|
||||
var mocks = GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.Where(f => f.FieldType == typeof(Mock)).Select(f => (Mock)f.GetValue(this));
|
||||
|
||||
foreach (var m in mocks)
|
||||
m.Reset();
|
||||
}
|
||||
|
||||
// [ExcludeFromCoverage]
|
||||
// private void Apply(bool isGlobal = false)
|
||||
// {
|
||||
// ApplyPropertyCache(objectPropertyCache);
|
||||
// }
|
||||
//
|
||||
// [ExcludeFromCoverage]
|
||||
// private void ApplyPropertyCache(IDictionary<Object, SerializedObject> cache)
|
||||
// {
|
||||
// if (cache.Count == 0)
|
||||
// return;
|
||||
//
|
||||
// foreach (var pair in cache)
|
||||
// pair.Value.ApplyModifiedProperties();
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1863291fabd7fb43837115239feede3
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3b38a9a1e7f41b8849eb925b8dda6ef
|
||||
timeCreated: 1686834699
|
||||
@@ -0,0 +1,63 @@
|
||||
using System.Collections;
|
||||
using BracerLib.Utility;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BracerLib.Tests.Utility
|
||||
{
|
||||
public class MathUtilityTests : TestBase
|
||||
{
|
||||
private static IEnumerable BoundValues()
|
||||
{
|
||||
yield return new TestCaseData(2, 1, 3, 2).SetName("Value is between bounds");
|
||||
yield return new TestCaseData(0, 1, 3, 3).SetName("Value is below bounds");
|
||||
yield return new TestCaseData(4, 1, 3, 1).SetName("Value is above bounds");
|
||||
}
|
||||
|
||||
private static IEnumerable BetweenValuesInt()
|
||||
{
|
||||
yield return new TestCaseData(0, -1, 1, BoundsInclusivity.None, true).SetName("Value is between bounds");
|
||||
yield return new TestCaseData(-2, -1, 1, BoundsInclusivity.None, false).SetName("Value is below bounds");
|
||||
yield return new TestCaseData(2, -1, 1, BoundsInclusivity.None, false).SetName("Value is above bounds");
|
||||
yield return new TestCaseData(-1, -1, 1, BoundsInclusivity.Both, true).SetName("Value is at bound, inclusive both");
|
||||
yield return new TestCaseData(-1, -1, 1, BoundsInclusivity.Left, true).SetName("Value is at bound, inclusive left");
|
||||
yield return new TestCaseData(1, -1, 1, BoundsInclusivity.Right, true).SetName("Value is at bound, inclusive right");
|
||||
yield return new TestCaseData(1, -1, 1, BoundsInclusivity.Both, true).SetName("Value is at bound, exclusive");
|
||||
}
|
||||
|
||||
private static IEnumerable BetweenValuesFloat()
|
||||
{
|
||||
yield return new TestCaseData(0f, -1f, 1f, BoundsInclusivity.None, true).SetName("Value is between bounds");
|
||||
yield return new TestCaseData(-2f, -1f, 1f, BoundsInclusivity.None, false).SetName("Value is below bounds");
|
||||
yield return new TestCaseData(2f, -1f, 1f, BoundsInclusivity.None, false).SetName("Value is above bounds");
|
||||
yield return new TestCaseData(-1f, -1f, 1f, BoundsInclusivity.Both, true).SetName("Value is at bound, inclusive both");
|
||||
yield return new TestCaseData(-1f, -1f, 1f, BoundsInclusivity.Left, true).SetName("Value is at bound, inclusive left");
|
||||
yield return new TestCaseData(1f, -1f, 1f, BoundsInclusivity.Right, true).SetName("Value is at bound, inclusive right");
|
||||
yield return new TestCaseData(1f, -1f, 1f, BoundsInclusivity.Both, true).SetName("Value is at bound, exclusive");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(nameof(BoundValues))]
|
||||
public void ValuesAreWithinBounds(int value, int min, int max, int expected)
|
||||
{
|
||||
var result = MathUtility.KeepWithinBounds(value, min, max);
|
||||
Assert.That(result, Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(nameof(BetweenValuesInt))]
|
||||
public void ValuesBetweenBounds(int value, int min, int max, BoundsInclusivity inclusivity, bool expected)
|
||||
{
|
||||
var result = MathUtility.IsBetween(value, min, max, inclusivity);
|
||||
Assert.That(result, Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(nameof(BetweenValuesFloat))]
|
||||
public void ValuesBetweenBoundsFloat(float value, float min, float max, BoundsInclusivity inclusivity, bool expected)
|
||||
{
|
||||
var result = MathUtility.IsBetween(value, min, max, inclusivity);
|
||||
Assert.That(result, Is.EqualTo(expected));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fcf35728772424c9c2c84e29290ac5e
|
||||
timeCreated: 1780244918
|
||||
@@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using BracerLib.Utility;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BracerLib.Tests.Utility
|
||||
{
|
||||
public class TriangulatorTest : TestBase
|
||||
{
|
||||
private static IEnumerable AreaValueTests()
|
||||
{
|
||||
var points = new List<Vector2>();
|
||||
|
||||
yield return new TestCaseData(points.ToArray(), 0f).SetName("No points to calculate");
|
||||
|
||||
points.AddRange(new[]
|
||||
{
|
||||
Vector2.one,
|
||||
new Vector2(5f, 7f),
|
||||
new Vector2(-2f, 8f)
|
||||
});
|
||||
|
||||
yield return new TestCaseData(points.ToArray(), 23f).SetName("Area of a triangle");
|
||||
|
||||
points.Add(new Vector2(3f, 5f));
|
||||
|
||||
yield return new TestCaseData(points.ToArray(), 10f).SetName("Area of a quad");
|
||||
}
|
||||
|
||||
private static IEnumerable InsideTrianglePointsTest()
|
||||
{
|
||||
yield return new TestCaseData(
|
||||
Vector2.zero,
|
||||
new Vector2(3f, 3f),
|
||||
new Vector2(3f, 0f),
|
||||
new Vector2(2f, 1f),
|
||||
true
|
||||
).SetName("Point inside triangle");
|
||||
|
||||
yield return new TestCaseData(
|
||||
Vector2.zero,
|
||||
new Vector2(3f, 3f),
|
||||
new Vector2(3f, 0f),
|
||||
new Vector2(1f, 0f),
|
||||
true
|
||||
).SetName("Point on the line");
|
||||
|
||||
yield return new TestCaseData(
|
||||
Vector2.zero,
|
||||
new Vector2(3f, 3f),
|
||||
new Vector2(3f, 0f),
|
||||
new Vector2(3f, 0f),
|
||||
false
|
||||
).SetName("Point is one of triangle points");
|
||||
|
||||
yield return new TestCaseData(
|
||||
Vector2.zero,
|
||||
new Vector2(3f, 3f),
|
||||
new Vector2(3f, 0f),
|
||||
new Vector2(-2f, 1f),
|
||||
false
|
||||
).SetName("Point outside triangle");
|
||||
}
|
||||
|
||||
private static IEnumerable TriangulatePointsTest()
|
||||
{
|
||||
yield return new TestCaseData(
|
||||
new[]
|
||||
{
|
||||
Vector2.zero,
|
||||
Vector2.right,
|
||||
Vector2.right + Vector2.up,
|
||||
Vector2.up,
|
||||
Vector2.left + Vector2.up,
|
||||
Vector2.left
|
||||
},
|
||||
new[] { 5,3,2,2,0,5,5,4,3,2,1,0 }
|
||||
).SetName("Positive triangulation");
|
||||
|
||||
yield return new TestCaseData(
|
||||
new[]
|
||||
{
|
||||
Vector2.zero,
|
||||
Vector2.right,
|
||||
Vector2.right + Vector2.down,
|
||||
Vector2.down,
|
||||
Vector2.left + Vector2.down,
|
||||
Vector2.left
|
||||
},
|
||||
new[] { 1,3,4,4,0,1,1,2,3,4,5,0 }
|
||||
).SetName("Negative triangulation");
|
||||
|
||||
yield return new TestCaseData(
|
||||
new[] { Vector2.zero, Vector2.right },
|
||||
Array.Empty<int>()
|
||||
).SetName("Empty triangulation");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(nameof(AreaValueTests))]
|
||||
public void AreaCalculatesCorrectly(Vector2[] points, float expected)
|
||||
{
|
||||
var result = Triangulator.Area(points);
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(nameof(InsideTrianglePointsTest))]
|
||||
public void PointsInsideTriangleCorrectly(Vector2 a, Vector2 b, Vector2 c, Vector2 p, bool expected)
|
||||
{
|
||||
var result = Triangulator.InsideTriangle(a, b, c, p);
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(nameof(TriangulatePointsTest))]
|
||||
public void TriangulatePoints(Vector2[] points, int[] expected)
|
||||
{
|
||||
var result = Triangulator.Triangulate(points);
|
||||
Assert.AreEqual(expected.Length, result.Length);
|
||||
for (var i = 0; i < result.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected[i], result[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a7aaa2ed31747e5ae172f296a2808e3
|
||||
timeCreated: 1686834708
|
||||
Reference in New Issue
Block a user