diff --git a/Content/GameSettings.json b/Content/GameSettings.json
new file mode 100644
index 0000000..f4ab815
--- /dev/null
+++ b/Content/GameSettings.json
@@ -0,0 +1,9 @@
+{
+ "ID": "6888874e4229953ae4692194ef19ddf2",
+ "TypeName": "FlaxEditor.Content.Settings.GameSettings",
+ "EngineBuild": 6187,
+ "Data": {
+ "ProductName": "Simple Unit Testing",
+ "FirstScene": "00000000000000000000000000000000"
+}
+}
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..43bfce9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# Unit Testing Plugin for the FlaxEngine
+
diff --git a/Source/Assert.cs b/Source/Editor/Assert.cs
similarity index 54%
rename from Source/Assert.cs
rename to Source/Editor/Assert.cs
index 0427ce8..605982f 100644
--- a/Source/Assert.cs
+++ b/Source/Editor/Assert.cs
@@ -1,21 +1,33 @@
using System;
-namespace FlaxEngine.UnitTesting
+namespace FlaxCommunity.UnitTesting.Editor
{
///
/// Special type of exception that is used to terminate the test case early
///
///
- public class SuccessException : Exception { }
+ public class SuccessException : Exception
+ {
+ public SuccessException()
+ {
+ }
+
+ public SuccessException(string message) : base(message)
+ {
+ }
+
+ public SuccessException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+ }
public static class Assert
{
public static void Pass() => throw new SuccessException();
public static void Fail() => throw new Exception();
- // TODO: use Equals instead of ==
- public static void AreEqual(object a, object b) { if (a != b) throw new Exception(); }
- public static void AreNotEqual(object a, object b) { if (a == b) throw new Exception(); }
+ public static void AreEqual(object a, object b) { if (!Equals(a, b)) throw new Exception(); }
+ public static void AreNotEqual(object a, object b) { if (Equals(a, b)) throw new Exception(); }
public static void True(bool a) { if (!a) throw new Exception(); }
public static void False(bool a) { if (a) throw new Exception(); }
diff --git a/Source/ExampleClass.cs b/Source/Editor/ExampleClass.cs
similarity index 76%
rename from Source/ExampleClass.cs
rename to Source/Editor/ExampleClass.cs
index eeb37fb..a944eda 100644
--- a/Source/ExampleClass.cs
+++ b/Source/Editor/ExampleClass.cs
@@ -1,7 +1,7 @@
#if !FLAX_PLUGIN
-using FlaxEngine.UnitTesting;
+using FlaxCommunity.UnitTesting.Editor;
-namespace UnitTests
+namespace UnitTests.Editor
{
[TestFixture]
internal class SimpleTests
@@ -15,7 +15,7 @@ public void SuccessTest()
[Test]
public void ErrorTest()
{
- Assert.True(null != null);
+ Assert.True(1 != 1);
}
}
@@ -23,9 +23,16 @@ public void ErrorTest()
internal class SetupTests
{
private object Tested = null;
+ private object Database = null;
+
+ [OneTimeSetUp]
+ public void Init()
+ {
+ Database = new object { };
+ }
[SetUp]
- public void Setup()
+ public void BeforeEach()
{
Tested = "Test";
}
@@ -37,8 +44,13 @@ public void SetupTest()
}
[TearDown]
+ public void AfterEach()
+ {
+ }
+
public void Dispose()
{
+ Database = null;
}
}
diff --git a/Source/TestAttributes.cs b/Source/Editor/TestAttributes.cs
similarity index 59%
rename from Source/TestAttributes.cs
rename to Source/Editor/TestAttributes.cs
index 44612bf..3f1e0a7 100644
--- a/Source/TestAttributes.cs
+++ b/Source/Editor/TestAttributes.cs
@@ -1,9 +1,12 @@
using System;
-namespace FlaxEngine.UnitTesting
+namespace FlaxCommunity.UnitTesting.Editor
{
+ ///
+ /// A test case
+ ///
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
- public class TestCase : Attribute
+ public sealed class TestCase : Attribute
{
public readonly object[] Attributes;
public object ExpectedResult { get; set; }
@@ -43,24 +46,52 @@ public TestCase(object T1, object T2, object T3, object T4, object T5, object T6
}
}
+ ///
+ /// A single test
+ ///
[AttributeUsage(AttributeTargets.Method)]
- public class Test : Attribute
+ public sealed class Test : Attribute
{
}
+ ///
+ /// Executed before every single test
+ ///
[AttributeUsage(AttributeTargets.Method)]
- public class SetUp : Attribute
+ public sealed class SetUp : Attribute
{
}
+ ///
+ /// Executed after every single test
+ ///
[AttributeUsage(AttributeTargets.Method)]
- public class TearDown : Attribute
+ public sealed class TearDown : Attribute
{
}
+ ///
+ /// Executed before all tests
+ ///
+ [AttributeUsage(AttributeTargets.Method)]
+ public sealed class OneTimeSetUp : Attribute
+ {
+ }
+
+ ///
+ /// Executed after all tests
+ ///
+ [AttributeUsage(AttributeTargets.Method)]
+ public sealed class OneTimeTearDown : Attribute
+ {
+ }
+
+ ///
+ /// Specifies a class as a unit test class
+ ///
[AttributeUsage(AttributeTargets.Class)]
- public class TestFixture : Attribute
+ public sealed class TestFixture : Attribute
{
}
}
\ No newline at end of file
diff --git a/Source/Editor/TestRunner.cs b/Source/Editor/TestRunner.cs
index e920ada..85d2c83 100644
--- a/Source/Editor/TestRunner.cs
+++ b/Source/Editor/TestRunner.cs
@@ -1,69 +1,81 @@
using FlaxEditor;
using FlaxEditor.GUI;
+using FlaxEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using FlaxCommunity.UnitTesting;
-namespace FlaxEngine.UnitTesting.Editor
+namespace FlaxCommunity.UnitTesting.Editor
{
public class TestRunner : EditorPlugin
{
- private static List suites = new List();
- private MainMenuButton mmBtn;
+ private static readonly List _suites = new List();
+ private MainMenuButton _mmBtn;
public override PluginDescription Description => new PluginDescription
{
Author = "Lukáš Jech",
- AuthorUrl ="https://lukas.jech.me",
+ AuthorUrl = "https://lukas.jech.me",
Category = "Unit Testing",
Description = "Simple unit testing framework",
IsAlpha = false,
IsBeta = false,
Name = "Simple Unit Testing",
- SupportedPlatforms = new PlatformType[] {PlatformType.Windows},
- Version = new Version(1,0),
- RepositoryUrl = "https://github.com/klukule/flax-ut"
+ SupportedPlatforms = new PlatformType[] { PlatformType.Windows },
+ Version = new Version(1, 1),
+ RepositoryUrl = "https://github.com/FlaxCommunityProjects/FlaxUnitTesting"
};
-
+
public override void InitializeEditor()
{
base.InitializeEditor();
- mmBtn = Editor.UI.MainMenu.AddButton("Unit Tests");
- mmBtn.ContextMenu.AddButton("Run unit tests").Clicked += RunTests;
+ _mmBtn = Editor.UI.MainMenu.AddButton("Unit Tests");
+ _mmBtn.ContextMenu.AddButton("Run unit tests").Clicked += RunTests;
+ FlaxEditor.Scripting.ScriptsBuilder.ScriptsReloadBegin += ScriptsBuilder_ScriptsReloadBegin;
+ }
+ private void ScriptsBuilder_ScriptsReloadBegin()
+ {
+ // Clear type information as per warning https://docs.flaxengine.com/manual/scripting/plugins/index.html
+ _suites.Clear();
}
public override void Deinitialize()
{
base.Deinitialize();
- if (mmBtn != null)
+ if (_mmBtn != null)
{
- mmBtn.Dispose();
- mmBtn = null;
+ _mmBtn.Dispose();
+ _mmBtn = null;
}
}
private static void GatherTests()
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
- suites.Clear();
+ _suites.Clear();
foreach (var assembly in assemblies)
foreach (var type in assembly.GetTypes())
if (type.GetCustomAttributes().Count() > 0)
- suites.Add(type);
+ _suites.Add(type);
}
public static void RunTests()
{
GatherTests();
- foreach (var suite in suites)
+ foreach (var suite in _suites)
{
- var tests = suite.GetMethods().Where(m => m.GetCustomAttributes().Count() > 0 || m.GetCustomAttributes().Count() > 0).ToArray();
- var setup = suite.GetMethods().Where(m => m.GetCustomAttributes().Count() > 0).FirstOrDefault();
- var disposer = suite.GetMethods().Where(m => m.GetCustomAttributes().Count() > 0).FirstOrDefault();
+ var suiteMethods = suite.GetMethods();
+
+ var tests = suiteMethods.Where(m => m.GetCustomAttributes().Count() > 0 || m.GetCustomAttributes().Count() > 0).ToArray();
+ var setup = suiteMethods.Where(m => m.GetCustomAttributes().Count() > 0).FirstOrDefault();
+ var disposer = suiteMethods.Where(m => m.GetCustomAttributes().Count() > 0).FirstOrDefault();
+ var beforeEach = suiteMethods.Where(m => m.GetCustomAttributes().Count() > 0).FirstOrDefault();
+ var afterEach = suiteMethods.Where(m => m.GetCustomAttributes().Count() > 0).FirstOrDefault();
var instance = Activator.CreateInstance(suite);
@@ -71,50 +83,63 @@ public static void RunTests()
foreach (var testMethod in tests)
{
- // Mitigates the AttributeNullException
- foreach (var test in testMethod.GetCustomAttributes())
+ if (testMethod.GetCustomAttributes().Count() > 0)
{
bool failed = false;
+ beforeEach?.Invoke(instance, null);
try
{
testMethod?.Invoke(instance, null);
}
- catch (Exception e)
+ catch (TargetInvocationException e)
{
- if(e.GetType() != typeof(SuccessException))
+ if (!(e.InnerException is SuccessException))
failed = true;
}
+ catch (Exception e)
+ {
+ failed = true;
+ }
finally
{
+ afterEach?.Invoke(instance, null);
Debug.Log($"Test '{suite.Name} {testMethod.Name}' finished with " + (failed ? "Error" : "Success"));
}
}
-
- var testCases = testMethod.GetCustomAttributes();
- int successCount = 0;
- foreach (var testCase in testCases)
+ else
{
- bool failed = false;
- try
+ var testCases = testMethod.GetCustomAttributes();
+ int successCount = 0;
+ foreach (var testCase in testCases)
{
- var result = testMethod?.Invoke(instance, testCase.Attributes);
- if (testCase.ExpectedResult != null)
- failed = !testCase.ExpectedResult.Equals(result);
- }
- catch (Exception e)
- {
- if(e.GetType() != typeof(SuccessException))
+ bool failed = false;
+ beforeEach?.Invoke(instance, null);
+ try
+ {
+ var result = testMethod?.Invoke(instance, testCase.Attributes);
+ if (testCase.ExpectedResult != null)
+ failed = !testCase.ExpectedResult.Equals(result);
+ }
+ catch (TargetInvocationException e)
+ {
+ if (!(e.InnerException is SuccessException))
+ failed = true;
+ }
+ catch (Exception e)
+ {
failed = true;
+ }
+ finally
+ {
+ afterEach?.Invoke(instance, null);
+
+ if (!failed)
+ successCount++;
+ }
}
- finally
- {
- if (!failed)
- successCount++;
- }
- }
- if(testCases.Count() > 0)
Debug.Log($"Test '{suite.Name} {testMethod.Name}' finished with {successCount}/{testCases.Count()} successfull test cases.");
+ }
}
disposer?.Invoke(instance, null);
diff --git a/UnitTests.Editor.csproj b/UnitTests.Editor.csproj
index 3ca6c26..3b46309 100644
--- a/UnitTests.Editor.csproj
+++ b/UnitTests.Editor.csproj
@@ -22,7 +22,7 @@
prompt
4
true
- DEBUG;FLAX_ASSERTIONS;TRACE;FLAX_0;FLAX_0_3;FLAX_0_3_6173;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN
+ DEBUG;FLAX_ASSERTIONS;TRACE;FLAX_0;FLAX_0_5;FLAX_0_5_6187;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN
false
@@ -33,7 +33,7 @@
prompt
4
true
- TRACE;FLAX_0;FLAX_0_3;FLAX_0_3_6173;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN
+ TRACE;FLAX_0;FLAX_0_5;FLAX_0_5_6187;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN
false
@@ -42,13 +42,13 @@
- Cache\Assemblies\Release\FlaxEngine.dll
+ Cache\Assemblies\FlaxEngine.dll
- Cache\Assemblies\Release\Newtonsoft.Json.dll
+ Cache\Assemblies\Newtonsoft.Json.dll
- Cache\Assemblies\Release\FlaxEditor.dll
+ Cache\Assemblies\FlaxEditor.dll
@@ -59,6 +59,9 @@
+
+
+
diff --git a/UnitTests.csproj b/UnitTests.csproj
index af430b2..94b8756 100644
--- a/UnitTests.csproj
+++ b/UnitTests.csproj
@@ -22,7 +22,7 @@
prompt
4
true
- DEBUG;FLAX_ASSERTIONS;TRACE;FLAX_0;FLAX_0_3;FLAX_0_3_6173;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN
+ DEBUG;FLAX_ASSERTIONS;TRACE;FLAX_0;FLAX_0_5;FLAX_0_5_6187;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN
false
@@ -33,7 +33,7 @@
prompt
4
true
- TRACE;FLAX_0;FLAX_0_3;FLAX_0_3_6173;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN
+ TRACE;FLAX_0;FLAX_0_5;FLAX_0_5_6187;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN
false
@@ -42,19 +42,16 @@
- Cache\Assemblies\Release\FlaxEngine.dll
+ Cache\Assemblies\FlaxEngine.dll
- Cache\Assemblies\Release\Newtonsoft.Json.dll
+ Cache\Assemblies\Newtonsoft.Json.dll
- Cache\Assemblies\Release\FlaxEditor.dll
+ Cache\Assemblies\FlaxEditor.dll
-
-
-