From 567633c31f17efbb7be1f415c36fb02d5ba3f731 Mon Sep 17 00:00:00 2001 From: Andre Niggemann Date: Thu, 11 Jul 2024 11:14:56 +0200 Subject: [PATCH] InitialDesign for MAssert and modified Transition Test as an example for the usage. Feel free to break the tests and switch between Assert.That and MAssert.That to see the effects. Fix wrongly translated example --- MORYX-Framework.sln | 7 ++ src/Moryx.TestTools.NUnit/MAssert.cs | 54 +++++++++++++++ .../Moryx.TestTools.NUnit.csproj | 13 ++++ src/Tests/Moryx.Tests/Moryx.Tests.csproj | 1 + .../Moryx.Tests/Workplans/TransitionTests.cs | 65 +++++++++++-------- 5 files changed, 114 insertions(+), 26 deletions(-) create mode 100644 src/Moryx.TestTools.NUnit/MAssert.cs create mode 100644 src/Moryx.TestTools.NUnit/Moryx.TestTools.NUnit.csproj diff --git a/MORYX-Framework.sln b/MORYX-Framework.sln index 4b91aaf84..a62cf04a1 100644 --- a/MORYX-Framework.sln +++ b/MORYX-Framework.sln @@ -118,6 +118,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moryx.Runtime.Endpoints.Tes EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moryx.Runtime.Endpoints.IntegrationTests", "src\Tests\Moryx.Runtime.Endpoints.IntegrationTests\Moryx.Runtime.Endpoints.IntegrationTests.csproj", "{4FFB98A7-9A4C-476F-8BCC-C19B7F757BF8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moryx.TestTools.NUnit", "src\Moryx.TestTools.NUnit\Moryx.TestTools.NUnit.csproj", "{6FF878E0-AF61-4C3A-9B9C-71C35A949E51}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moryx.TestTools.IntegrationTest", "src\Moryx.TestTools.IntegrationTest\Moryx.TestTools.IntegrationTest.csproj", "{C949164C-0345-4893-9E4C-A79BC1F93F85}" EndProject Global @@ -298,6 +300,10 @@ Global {4FFB98A7-9A4C-476F-8BCC-C19B7F757BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU {4FFB98A7-9A4C-476F-8BCC-C19B7F757BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU {4FFB98A7-9A4C-476F-8BCC-C19B7F757BF8}.Release|Any CPU.Build.0 = Release|Any CPU + {6FF878E0-AF61-4C3A-9B9C-71C35A949E51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FF878E0-AF61-4C3A-9B9C-71C35A949E51}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FF878E0-AF61-4C3A-9B9C-71C35A949E51}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FF878E0-AF61-4C3A-9B9C-71C35A949E51}.Release|Any CPU.Build.0 = Release|Any CPU {C949164C-0345-4893-9E4C-A79BC1F93F85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C949164C-0345-4893-9E4C-A79BC1F93F85}.Debug|Any CPU.Build.0 = Debug|Any CPU {C949164C-0345-4893-9E4C-A79BC1F93F85}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -346,6 +352,7 @@ Global {FEB3BA44-2CD9-445A-ABF2-C92378C443F7} = {0A466330-6ED6-4861-9C94-31B1949CDDB9} {7792C4E0-6D07-42C9-AC29-BAB76836FC11} = {0A466330-6ED6-4861-9C94-31B1949CDDB9} {4FFB98A7-9A4C-476F-8BCC-C19B7F757BF8} = {8517D209-5BC1-47BD-A7C7-9CF9ADD9F5B6} + {6FF878E0-AF61-4C3A-9B9C-71C35A949E51} = {953AAE25-26C8-4A28-AB08-61BAFE41B22F} {C949164C-0345-4893-9E4C-A79BC1F93F85} = {953AAE25-26C8-4A28-AB08-61BAFE41B22F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/Moryx.TestTools.NUnit/MAssert.cs b/src/Moryx.TestTools.NUnit/MAssert.cs new file mode 100644 index 000000000..8c75378d0 --- /dev/null +++ b/src/Moryx.TestTools.NUnit/MAssert.cs @@ -0,0 +1,54 @@ +using NUnit.Framework; +using NUnit.Framework.Constraints; +using NUnit.Framework.Internal; +using System; +using System.Linq.Expressions; +using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; +using System.Xml.Linq; + +namespace Moryx.TestTools.NUnit +{ + public abstract class MAssert + { + public static void That(bool condition, string? message = null, [CallerArgumentExpression(nameof(condition))] string? predicateExpression = null) + { + That(condition, Is.True, message, predicateExpression); + } + public static void That(Func predicate, string? message = null, [CallerArgumentExpression(nameof(predicate))]string? predicateExpression = null) + { + That(predicate, Is.True, message, predicateExpression); + } + + public static void That(T actual, IResolveConstraint constraint, string? message = null, [CallerArgumentExpression(nameof(actual))] string? predicateExpression = null) + { + if (message != null) + { + message = $"{message}\nExpression: {predicateExpression}"; + } + else + { + message = predicateExpression; + } + Assert.That(actual, constraint, message); + } + + public static void That(Func actualExpression, Constraint constraint, string? message = null, [CallerArgumentExpression(nameof(actualExpression))] string? predicateExpression = null) + { + if (message != null) + { + message = $"{message}\nExpression: {predicateExpression}"; + } + else + { + message = predicateExpression; + } + int fails = TestExecutionContext.CurrentContext.CurrentResult.PendingFailures; + T value = default(T)!; + Assert.That(() => value = actualExpression(), new ThrowsNothingConstraint(), $"{message}\nExpected {constraint.Description} and"); + if (TestExecutionContext.CurrentContext.CurrentResult.PendingFailures > fails) return; // TODO: Check if we there could be multithreading issues and whether or not we care + Assert.That(value, constraint, message); + } + } + +} diff --git a/src/Moryx.TestTools.NUnit/Moryx.TestTools.NUnit.csproj b/src/Moryx.TestTools.NUnit/Moryx.TestTools.NUnit.csproj new file mode 100644 index 000000000..7fea020cc --- /dev/null +++ b/src/Moryx.TestTools.NUnit/Moryx.TestTools.NUnit.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/src/Tests/Moryx.Tests/Moryx.Tests.csproj b/src/Tests/Moryx.Tests/Moryx.Tests.csproj index 1ff29d6a4..ce8ad8b6e 100644 --- a/src/Tests/Moryx.Tests/Moryx.Tests.csproj +++ b/src/Tests/Moryx.Tests/Moryx.Tests.csproj @@ -14,6 +14,7 @@ + diff --git a/src/Tests/Moryx.Tests/Workplans/TransitionTests.cs b/src/Tests/Moryx.Tests/Workplans/TransitionTests.cs index a001cf612..c5852a3ac 100644 --- a/src/Tests/Moryx.Tests/Workplans/TransitionTests.cs +++ b/src/Tests/Moryx.Tests/Workplans/TransitionTests.cs @@ -1,8 +1,10 @@ // Copyright (c) 2023, Phoenix Contact GmbH & Co. KG // Licensed under the Apache License, Version 2.0 +using System; using System.Collections.Generic; using System.Linq; +using Moryx.TestTools.NUnit; using Moryx.Workplans; using Moryx.Workplans.Transitions; using NUnit.Framework; @@ -56,14 +58,15 @@ public void SplitTransition() // Act trans.Initialize(); _inputs[0].Add(_token); - + // Assert - Assert.AreEqual(0, _inputs[0].Tokens.Count()); - Assert.IsTrue(_outputs.All(o => o.Tokens.Count() == 1)); - Assert.IsInstanceOf(_outputs[0].Tokens.First()); - Assert.IsInstanceOf(_outputs[1].Tokens.First()); - Assert.AreEqual(_token, ((SplitToken)_outputs[0].Tokens.First()).Original); - Assert.AreEqual(_token, ((SplitToken)_outputs[1].Tokens.First()).Original); + Assert.Multiple(() => + { + MAssert.That(_inputs[0].Tokens, Is.Empty); + MAssert.That(_outputs.Select(o => o.Tokens), Has.All.Count.EqualTo(1)); + MAssert.That(() => ((SplitToken)_outputs[0].Tokens.First()).Original, Is.EqualTo(_token)); + MAssert.That(() => ((SplitToken)_outputs[1].Tokens.First()).Original, Is.EqualTo(_token)); + }); } [Test] @@ -83,11 +86,13 @@ public void JoinTransition() trans.Initialize(); _inputs[0].Add(split1); _inputs[1].Add(split2); - // Assert - Assert.IsTrue(_inputs.All(i => !i.Tokens.Any())); - Assert.AreEqual(1, _outputs[0].Tokens.Count()); - Assert.AreEqual(_token, _outputs[0].Tokens.First()); + Assert.Multiple(() => + { + MAssert.That(_inputs.All(i => !i.Tokens.Any())); + MAssert.That(_outputs[0].Tokens.Count(), Is.EqualTo(1), "The split token should be joined into one"); + MAssert.That(_outputs[0].Tokens.First(), Is.EqualTo(_token)); + }); } [TestCase(0, Description = "Place only one split token on the first input")] @@ -108,9 +113,12 @@ public void IncompleteJoinTransition(int index) _inputs[index].Add(split); // Assert - Assert.AreEqual(1, _inputs[index].Tokens.Count()); - Assert.AreEqual(0, _inputs[(index + 1) % 2].Tokens.Count()); - Assert.AreEqual(0, _outputs[0].Tokens.Count()); + Assert.Multiple(() => + { + MAssert.That(_inputs[index].Tokens, Has.Count.EqualTo(1)); + MAssert.That(_inputs[(index + 1) % 2].Tokens, Is.Empty); + MAssert.That(_outputs[0].Tokens, Is.Empty); + }); } [Test] @@ -138,10 +146,12 @@ public void SubWorkplanTransition() _inputs[0].Add(_token); // Assert - Assert.AreEqual(0, _inputs[0].Tokens.Count()); - Assert.AreEqual(_token, _outputs[0].Tokens.First()); - Assert.AreEqual(2, triggered.Count); - Assert.IsTrue(triggered.All(t => t is DummyTransition)); + Assert.Multiple(() => { + MAssert.That(_inputs[0].Tokens, Is.Empty); + MAssert.That(() => _outputs[0].Tokens.First(), Is.EqualTo(_token)); + MAssert.That(triggered.Count, Is.EqualTo(2)); + MAssert.That(triggered, Has.All.InstanceOf()); + }); } [Test] @@ -171,14 +181,17 @@ public void SubworkplanPause() trans.Resume(); // Assert - Assert.AreEqual(0, _inputs[0].Tokens.Count()); - Assert.AreEqual(_token, _outputs[0].Tokens.First()); - Assert.AreEqual(1, triggered.Count); - Assert.IsInstanceOf(state); - var snapshot = (WorkplanSnapshot)state; - Assert.AreEqual(1, snapshot.Holders.Length); - var stepId = workplan.Steps.First(s => s is PausableStep).Id; - Assert.AreEqual(stepId, snapshot.Holders[0].HolderId); + Assert.Multiple(() => + { + MAssert.That(_inputs[0].Tokens, Is.Empty); + MAssert.That(_outputs[0].Tokens.First(), Is.EqualTo(_token)); + MAssert.That(triggered, Has.Count.EqualTo(1)); + MAssert.That(state, Is.InstanceOf()); + var snapshot = (WorkplanSnapshot)state; + MAssert.That(snapshot.Holders, Has.Length.EqualTo(1)); + var stepId = workplan.Steps.First(s => s is PausableStep).Id; + MAssert.That(snapshot.Holders[0].HolderId, Is.EqualTo(stepId)); + }); } } }