diff --git a/Directory.Build.props b/Directory.Build.props index 940dda1..3943ac4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -18,8 +18,8 @@ - - + + diff --git a/src/Heleonix.Testing.NUnit/Internal/TestHost.cs b/src/Heleonix.Testing.NUnit/Internal/TestHost.cs index 8050084..0aeb5a4 100644 --- a/src/Heleonix.Testing.NUnit/Internal/TestHost.cs +++ b/src/Heleonix.Testing.NUnit/Internal/TestHost.cs @@ -8,7 +8,11 @@ namespace Heleonix.Testing.NUnit.Internal; using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; +using System.Reflection; using System.Text.RegularExpressions; +using global::NUnit.Framework; +using global::NUnit.Framework.Interfaces; using global::NUnit.Framework.Internal; /// @@ -89,8 +93,17 @@ public void Execute(SpecNode node) TestExecutionContext.CurrentContext.OutWriter.WriteLine($"{new string(' ', node.NestingLevel * 4)}\u2713 {node.Description}"); } } - catch (Exception) + catch (Exception ex) { + if (ex is not AssertionException) + { + var result = TestExecutionContext.CurrentContext.CurrentResult; + + result.RecordAssertion(AssertionStatus.Failed, ex.Message, ex.StackTrace); + + result.RecordTestCompletion(); + } + if (node.IsAssertable) { TestExecutionContext.CurrentContext.OutWriter.WriteLine($"{new string(' ', node.NestingLevel * 4)}\u2717 {node.Description}"); @@ -110,7 +123,7 @@ private void ValidateAdding(SpecNode child) { if (!this.SpecStructureRules.ContainsKey(child.Type)) { - throw new InvalidOperationException($"The spec '{child.Type}' is not valid for the current test pattern"); + throw new InvalidOperationException($"The spec '{child.Type}' is not valid for the current test pattern."); } var rule = this.SpecStructureRules[child.Type]; @@ -119,7 +132,7 @@ private void ValidateAdding(SpecNode child) && !Regex.IsMatch(string.Join(",", this.specExecutionStack), rule.SpecExecutionStackRule)) { throw new InvalidOperationException($"Invalid test structure: cannot place the '{child.Type}' " + - $"into the '{string.Join("->", this.specExecutionStack.Reverse())}'"); + $"into the '{string.Join("->", this.specExecutionStack.Reverse())}'."); } if (rule.PredecessorsRule != null) @@ -129,7 +142,7 @@ private void ValidateAdding(SpecNode child) if (!Regex.IsMatch(string.Join(",", parent.Children.Reverse()), rule.PredecessorsRule)) { throw new InvalidOperationException($"Invalid test structure: cannot place the '{child.Type}' " + - $"after the '{string.Join("->", parent.Children)}'"); + $"after the '{string.Join("->", parent.Children)}'."); } } } diff --git a/test/Heleonix.Testing.NUnit.Tests/Internal/TestHostTests.cs b/test/Heleonix.Testing.NUnit.Tests/Internal/TestHostTests.cs index ef89216..596e4e3 100644 --- a/test/Heleonix.Testing.NUnit.Tests/Internal/TestHostTests.cs +++ b/test/Heleonix.Testing.NUnit.Tests/Internal/TestHostTests.cs @@ -9,7 +9,9 @@ namespace Heleonix.Testing.NUnit.Tests.Internal; using System.Collections.Generic; using System.Reflection; using global::NUnit.Framework; +using global::NUnit.Framework.Interfaces; using global::NUnit.Framework.Internal; +using global::NUnit.Framework.Internal.Builders; using Heleonix.Testing.NUnit.Internal; using Moq; using Moq.Protected; @@ -268,7 +270,7 @@ public static void ValidateAdding6() /// /// Tests writing of a failed test with marking into the Output. /// - [Test(Description = "When an assertable node is throwing an exception Should write the test description as failed into the output")] + [Test(Description = "When an assertable node is throwing an exception Should write the test description as failed into the output and write failure result")] public static void Execute1() { // Arrange @@ -285,16 +287,33 @@ public static void Execute1() var rootNode = new SpecNode(SpecNodeType.Root, null, () => { }); - var node = new SpecNode(SpecNodeType.Should, "description", () => { throw new InvalidOperationException(); }, true); + var node = new SpecNode( + SpecNodeType.Should, + "description", + () => { throw new InvalidOperationException("Custom exception message."); }, + true); rootNode.Add(node); + var prevResult = TestExecutionContext.CurrentContext.CurrentResult; + + // Substitute the current test result to catch SpecNode execution. + TestExecutionContext.CurrentContext.CurrentResult = + TestExecutionContext.CurrentContext.CurrentTest.MakeTestResult(); + // Act methodInfo.Invoke(testHostMock.Object, new[] { node }); + var failCount = TestExecutionContext.CurrentContext.CurrentResult.FailCount; + var message = TestExecutionContext.CurrentContext.CurrentResult.Message; + var stackTrace = TestExecutionContext.CurrentContext.CurrentResult.StackTrace; + + TestExecutionContext.CurrentContext.CurrentResult = prevResult; + // Assert - // Cannot read the NUnit Output, so rely on the 100% test coverage. - Assert.True(true); + Assert.That(failCount, Is.EqualTo(1)); + Assert.That(message, Contains.Substring("Custom exception message.")); + Assert.That(stackTrace, Is.Not.Empty); } ///