Skip to content

Commit f9ac6c4

Browse files
committed
Implement OneTimeSetUp and OneTimeTearDown
See NUnit 5
1 parent 85d7e18 commit f9ac6c4

File tree

5 files changed

+110
-58
lines changed

5 files changed

+110
-58
lines changed

Source/Editor/TestRunner.cs

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,112 +9,121 @@ namespace FlaxEngine.UnitTesting.Editor
99
{
1010
public class TestRunner : EditorPlugin
1111
{
12-
private static List<Type> suites = new List<Type>();
13-
private MainMenuButton mmBtn;
12+
private static readonly List<Type> _suites = new List<Type>();
13+
private MainMenuButton _mmBtn;
1414

1515
public override PluginDescription Description => new PluginDescription
1616
{
1717
Author = "Lukáš Jech",
18-
AuthorUrl ="https://lukas.jech.me",
18+
AuthorUrl = "https://lukas.jech.me",
1919
Category = "Unit Testing",
2020
Description = "Simple unit testing framework",
2121
IsAlpha = false,
2222
IsBeta = false,
2323
Name = "Simple Unit Testing",
24-
SupportedPlatforms = new PlatformType[] {PlatformType.Windows},
25-
Version = new Version(1,0),
26-
RepositoryUrl = "https://github.com/klukule/flax-ut"
24+
SupportedPlatforms = new PlatformType[] { PlatformType.Windows },
25+
Version = new Version(1, 1),
26+
RepositoryUrl = "https://github.com/FlaxCommunityProjects/FlaxUnitTesting"
2727
};
2828

2929
public override void InitializeEditor()
3030
{
3131
base.InitializeEditor();
3232

33-
mmBtn = Editor.UI.MainMenu.AddButton("Unit Tests");
34-
mmBtn.ContextMenu.AddButton("Run unit tests").Clicked += RunTests;
33+
_mmBtn = Editor.UI.MainMenu.AddButton("Unit Tests");
34+
_mmBtn.ContextMenu.AddButton("Run unit tests").Clicked += RunTests;
3535

3636
}
3737

3838
public override void Deinitialize()
3939
{
4040
base.Deinitialize();
41-
if (mmBtn != null)
41+
if (_mmBtn != null)
4242
{
43-
mmBtn.Dispose();
44-
mmBtn = null;
43+
_mmBtn.Dispose();
44+
_mmBtn = null;
4545
}
4646
}
4747

4848
private static void GatherTests()
4949
{
5050
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
51-
suites.Clear();
51+
_suites.Clear();
5252
foreach (var assembly in assemblies)
5353
foreach (var type in assembly.GetTypes())
5454
if (type.GetCustomAttributes<TestFixture>().Count() > 0)
55-
suites.Add(type);
55+
_suites.Add(type);
5656
}
5757

5858
public static void RunTests()
5959
{
6060
GatherTests();
6161

62-
foreach (var suite in suites)
62+
foreach (var suite in _suites)
6363
{
64-
var tests = suite.GetMethods().Where(m => m.GetCustomAttributes<TestCase>().Count() > 0 || m.GetCustomAttributes<Test>().Count() > 0).ToArray();
65-
var setup = suite.GetMethods().Where(m => m.GetCustomAttributes<SetUp>().Count() > 0).FirstOrDefault();
66-
var disposer = suite.GetMethods().Where(m => m.GetCustomAttributes<TearDown>().Count() > 0).FirstOrDefault();
64+
var suiteMethods = suite.GetMethods();
65+
66+
var tests = suiteMethods.Where(m => m.GetCustomAttributes<Test>().Count() > 0 || m.GetCustomAttributes<TestCase>().Count() > 0).ToArray();
67+
var setup = suiteMethods.Where(m => m.GetCustomAttributes<OneTimeSetUp>().Count() > 0).FirstOrDefault();
68+
var disposer = suiteMethods.Where(m => m.GetCustomAttributes<OneTimeTearDown>().Count() > 0).FirstOrDefault();
69+
var beforeEach = suiteMethods.Where(m => m.GetCustomAttributes<SetUp>().Count() > 0).FirstOrDefault();
70+
var afterEach = suiteMethods.Where(m => m.GetCustomAttributes<TearDown>().Count() > 0).FirstOrDefault();
6771

6872
var instance = Activator.CreateInstance(suite);
6973

7074
setup?.Invoke(instance, null);
7175

7276
foreach (var testMethod in tests)
7377
{
74-
// Mitigates the AttributeNullException
75-
foreach (var test in testMethod.GetCustomAttributes<Test>())
78+
if (testMethod.GetCustomAttributes<Test>().Count() > 0)
7679
{
7780
bool failed = false;
81+
beforeEach?.Invoke(instance, null);
7882
try
7983
{
8084
testMethod?.Invoke(instance, null);
8185
}
8286
catch (Exception e)
8387
{
84-
if(e.GetType() != typeof(SuccessException))
88+
if (e.GetType() != typeof(SuccessException))
8589
failed = true;
8690
}
8791
finally
8892
{
93+
afterEach?.Invoke(instance, null);
8994
Debug.Log($"Test '{suite.Name} {testMethod.Name}' finished with " + (failed ? "Error" : "Success"));
9095
}
9196
}
92-
93-
var testCases = testMethod.GetCustomAttributes<TestCase>();
94-
int successCount = 0;
95-
foreach (var testCase in testCases)
97+
else
9698
{
97-
bool failed = false;
98-
try
99-
{
100-
var result = testMethod?.Invoke(instance, testCase.Attributes);
101-
if (testCase.ExpectedResult != null)
102-
failed = !testCase.ExpectedResult.Equals(result);
103-
}
104-
catch (Exception e)
99+
var testCases = testMethod.GetCustomAttributes<TestCase>();
100+
int successCount = 0;
101+
foreach (var testCase in testCases)
105102
{
106-
if(e.GetType() != typeof(SuccessException))
107-
failed = true;
108-
}
109-
finally
110-
{
111-
if (!failed)
112-
successCount++;
103+
bool failed = false;
104+
beforeEach?.Invoke(instance, null);
105+
try
106+
{
107+
var result = testMethod?.Invoke(instance, testCase.Attributes);
108+
if (testCase.ExpectedResult != null)
109+
failed = !testCase.ExpectedResult.Equals(result);
110+
}
111+
catch (Exception e)
112+
{
113+
if (e.GetType() != typeof(SuccessException))
114+
failed = true;
115+
}
116+
finally
117+
{
118+
afterEach?.Invoke(instance, null);
119+
120+
if (!failed)
121+
successCount++;
122+
}
113123
}
114-
}
115124

116-
if(testCases.Count() > 0)
117125
Debug.Log($"Test '{suite.Name} {testMethod.Name}' finished with {successCount}/{testCases.Count()} successfull test cases.");
126+
}
118127
}
119128

120129
disposer?.Invoke(instance, null);

Source/ExampleClass.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,24 @@ public void SuccessTest()
1515
[Test]
1616
public void ErrorTest()
1717
{
18-
Assert.True(null != null);
18+
Assert.True(1 != 1);
1919
}
2020
}
2121

2222
[TestFixture]
2323
internal class SetupTests
2424
{
2525
private object Tested = null;
26+
private object Database = null;
27+
28+
[OneTimeSetUp]
29+
public void Init()
30+
{
31+
Database = new object { };
32+
}
2633

2734
[SetUp]
28-
public void Setup()
35+
public void BeforeEach()
2936
{
3037
Tested = "Test";
3138
}
@@ -37,8 +44,13 @@ public void SetupTest()
3744
}
3845

3946
[TearDown]
47+
public void AfterEach()
48+
{
49+
}
50+
4051
public void Dispose()
4152
{
53+
Database = null;
4254
}
4355
}
4456

Source/TestAttributes.cs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
namespace FlaxEngine.UnitTesting
44
{
5+
/// <summary>
6+
/// A test case
7+
/// </summary>
58
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
6-
public class TestCase : Attribute
9+
public sealed class TestCase : Attribute
710
{
811
public readonly object[] Attributes;
912
public object ExpectedResult { get; set; }
@@ -43,24 +46,52 @@ public TestCase(object T1, object T2, object T3, object T4, object T5, object T6
4346
}
4447
}
4548

49+
/// <summary>
50+
/// A single test
51+
/// </summary>
4652
[AttributeUsage(AttributeTargets.Method)]
47-
public class Test : Attribute
53+
public sealed class Test : Attribute
4854
{
4955

5056
}
5157

58+
/// <summary>
59+
/// Executed before every single test
60+
/// </summary>
5261
[AttributeUsage(AttributeTargets.Method)]
53-
public class SetUp : Attribute
62+
public sealed class SetUp : Attribute
5463
{
5564
}
5665

66+
/// <summary>
67+
/// Executed after every single test
68+
/// </summary>
5769
[AttributeUsage(AttributeTargets.Method)]
58-
public class TearDown : Attribute
70+
public sealed class TearDown : Attribute
5971
{
6072
}
6173

74+
/// <summary>
75+
/// Executed before all tests
76+
/// </summary>
77+
[AttributeUsage(AttributeTargets.Method)]
78+
public sealed class OneTimeSetUp : Attribute
79+
{
80+
}
81+
82+
/// <summary>
83+
/// Executed after all tests
84+
/// </summary>
85+
[AttributeUsage(AttributeTargets.Method)]
86+
public sealed class OneTimeTearDown : Attribute
87+
{
88+
}
89+
90+
/// <summary>
91+
/// Specifies a class as a unit test class
92+
/// </summary>
6293
[AttributeUsage(AttributeTargets.Class)]
63-
public class TestFixture : Attribute
94+
public sealed class TestFixture : Attribute
6495
{
6596
}
6697
}

UnitTests.Editor.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<ErrorReport>prompt</ErrorReport>
2323
<WarningLevel>4</WarningLevel>
2424
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
25-
<DefineConstants>DEBUG;FLAX_ASSERTIONS;TRACE;FLAX_0;FLAX_0_3;FLAX_0_3_6173;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN</DefineConstants>
25+
<DefineConstants>DEBUG;FLAX_ASSERTIONS;TRACE;FLAX_0;FLAX_0_5;FLAX_0_5_6187;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN</DefineConstants>
2626
<UseVSHostingProcess>false</UseVSHostingProcess>
2727
</PropertyGroup>
2828
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -33,7 +33,7 @@
3333
<ErrorReport>prompt</ErrorReport>
3434
<WarningLevel>4</WarningLevel>
3535
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
36-
<DefineConstants>TRACE;FLAX_0;FLAX_0_3;FLAX_0_3_6173;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN</DefineConstants>
36+
<DefineConstants>TRACE;FLAX_0;FLAX_0_5;FLAX_0_5_6187;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN</DefineConstants>
3737
<UseVSHostingProcess>false</UseVSHostingProcess>
3838
</PropertyGroup>
3939
<ItemGroup>
@@ -42,13 +42,13 @@
4242
<Reference Include="System.Xml" />
4343
<Reference Include="System.Core" />
4444
<Reference Include="FlaxEngine">
45-
<HintPath>Cache\Assemblies\Release\FlaxEngine.dll</HintPath>
45+
<HintPath>Cache\Assemblies\FlaxEngine.dll</HintPath>
4646
</Reference>
4747
<Reference Include="Newtonsoft.Json">
48-
<HintPath>Cache\Assemblies\Release\Newtonsoft.Json.dll</HintPath>
48+
<HintPath>Cache\Assemblies\Newtonsoft.Json.dll</HintPath>
4949
</Reference>
5050
<Reference Include="FlaxEditor">
51-
<HintPath>Cache\Assemblies\Release\FlaxEditor.dll</HintPath>
51+
<HintPath>Cache\Assemblies\FlaxEditor.dll</HintPath>
5252
</Reference>
5353
</ItemGroup>
5454
<ItemGroup>

UnitTests.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<ErrorReport>prompt</ErrorReport>
2323
<WarningLevel>4</WarningLevel>
2424
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
25-
<DefineConstants>DEBUG;FLAX_ASSERTIONS;TRACE;FLAX_0;FLAX_0_3;FLAX_0_3_6173;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN</DefineConstants>
25+
<DefineConstants>DEBUG;FLAX_ASSERTIONS;TRACE;FLAX_0;FLAX_0_5;FLAX_0_5_6187;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN</DefineConstants>
2626
<UseVSHostingProcess>false</UseVSHostingProcess>
2727
</PropertyGroup>
2828
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -33,7 +33,7 @@
3333
<ErrorReport>prompt</ErrorReport>
3434
<WarningLevel>4</WarningLevel>
3535
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
36-
<DefineConstants>TRACE;FLAX_0;FLAX_0_3;FLAX_0_3_6173;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN</DefineConstants>
36+
<DefineConstants>TRACE;FLAX_0;FLAX_0_5;FLAX_0_5_6187;FLAX_EDITOR;FLAX_WINDOWS;FLAX_EDITOR_WIN</DefineConstants>
3737
<UseVSHostingProcess>false</UseVSHostingProcess>
3838
</PropertyGroup>
3939
<ItemGroup>
@@ -42,13 +42,13 @@
4242
<Reference Include="System.Xml" />
4343
<Reference Include="System.Core" />
4444
<Reference Include="FlaxEngine">
45-
<HintPath>Cache\Assemblies\Release\FlaxEngine.dll</HintPath>
45+
<HintPath>Cache\Assemblies\FlaxEngine.dll</HintPath>
4646
</Reference>
4747
<Reference Include="Newtonsoft.Json">
48-
<HintPath>Cache\Assemblies\Release\Newtonsoft.Json.dll</HintPath>
48+
<HintPath>Cache\Assemblies\Newtonsoft.Json.dll</HintPath>
4949
</Reference>
5050
<Reference Include="FlaxEditor">
51-
<HintPath>Cache\Assemblies\Release\FlaxEditor.dll</HintPath>
51+
<HintPath>Cache\Assemblies\FlaxEditor.dll</HintPath>
5252
</Reference>
5353
</ItemGroup>
5454
<ItemGroup>

0 commit comments

Comments
 (0)