diff --git a/Frank.Testing.TestOutputExtensions/Frank.Testing.TestOutputExtensions.csproj b/Frank.Testing.TestOutputExtensions/Frank.Testing.TestOutputExtensions.csproj index 75d72d5..8a14d3c 100644 --- a/Frank.Testing.TestOutputExtensions/Frank.Testing.TestOutputExtensions.csproj +++ b/Frank.Testing.TestOutputExtensions/Frank.Testing.TestOutputExtensions.csproj @@ -1,13 +1,14 @@  - Xunit + Xunit.Abstractions Extends ITestOutputHelper to allow output of a generic type using a serializer. - test, xunit, output, helper, serializer, json, console + test, testing, extensions, xunit, output, helper, serializer, json, xml, csharp, dump, var, dumpvar, vardump, xmlserializer, jsonserializer, testoutputhelper, testoutput, outputhelper, ITestOutputHelper, abstractions, xunit.abstractions, xunit.abstractions.extensions, xunit.extensions.ordering + diff --git a/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs b/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs new file mode 100644 index 0000000..fd2449b --- /dev/null +++ b/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs @@ -0,0 +1,53 @@ +using System.ComponentModel; + +using FluentAssertions; + +using VarDump; +using VarDump.Visitor; + +namespace Xunit.Abstractions; + +public static class TestOutputCSharpExtensions +{ + /// + /// Writes the provided source object as C# code to the test output. + /// + /// + /// The C# code is written using the + /// + /// + /// + /// var testPerson = new Frank.Testing.Tests.TestPerson + /// { + /// Name = "John Doe", + /// Age = 30, + /// Address = new Frank.Testing.Tests.TestAddress + /// { + /// City = "Main City", + /// ZipCode = 18846 + /// } + /// }; + /// + /// + /// The type of the source object. + /// The test output helper. + /// The source object to be written as C# code. + /// The optional dump options to control the formatting of the C# code. + public static void WriteCSharp(this ITestOutputHelper outputHelper, T source, DumpOptions? dumpOptions = null) + { + var options = dumpOptions ?? DumpOptions; + var dumper = new CSharpDumper(options); + outputHelper.WriteLine(dumper.Dump(source)); + } + + private static DumpOptions DumpOptions => new DumpOptions() + { + IgnoreNullValues = true, + DateKind = DateKind.ConvertToUtc, + DateTimeInstantiation = DateTimeInstantiation.Parse, + UseTypeFullName = true, + GenerateVariableInitializer = true, + SortDirection = ListSortDirection.Ascending, + MaxDepth = 64, + }; +} \ No newline at end of file diff --git a/Frank.Testing.TestOutputExtensions/TestOutputExtensions.cs b/Frank.Testing.TestOutputExtensions/TestOutputJsonExtensions.cs similarity index 95% rename from Frank.Testing.TestOutputExtensions/TestOutputExtensions.cs rename to Frank.Testing.TestOutputExtensions/TestOutputJsonExtensions.cs index c845af1..0f331cc 100644 --- a/Frank.Testing.TestOutputExtensions/TestOutputExtensions.cs +++ b/Frank.Testing.TestOutputExtensions/TestOutputJsonExtensions.cs @@ -1,11 +1,9 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Xunit.Abstractions; +namespace Xunit.Abstractions; -namespace Xunit; - -public static class TestOutputExtensions +public static class TestOutputJsonExtensions { /// /// Writes the specified object's string representation followed by the current line terminator to the output. diff --git a/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs b/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs new file mode 100644 index 0000000..19c05b5 --- /dev/null +++ b/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs @@ -0,0 +1,29 @@ +using System.Text; +using System.Xml; +using System.Xml.Serialization; + +namespace Xunit.Abstractions; + +public static class TestOutputXmlExtensions +{ + public static void WriteXml(this ITestOutputHelper outputHelper, T source, XmlWriterSettings? xmlWriterSettings = null) + { + var settings = xmlWriterSettings ?? XmlWriterSettings; + + using var textWriter = new StringWriter(); + using var xmlWriter = XmlWriter.Create(textWriter, settings); + var xmlSerializer = new XmlSerializerFactory().CreateSerializer(typeof(T)); + xmlSerializer.Serialize(xmlWriter, source); + outputHelper.WriteLine(textWriter.ToString()); + } + + private static XmlWriterSettings XmlWriterSettings => new() + { + Indent = true, + IndentChars = new string(' ', 4), + NewLineChars = "\n", + NewLineHandling = NewLineHandling.Replace, + OmitXmlDeclaration = false, + Encoding = new UTF8Encoding(false), + }; +} \ No newline at end of file diff --git a/Frank.Testing.Tests/Frank.Testing.Tests.csproj b/Frank.Testing.Tests/Frank.Testing.Tests.csproj index ebb790f..136322f 100644 --- a/Frank.Testing.Tests/Frank.Testing.Tests.csproj +++ b/Frank.Testing.Tests/Frank.Testing.Tests.csproj @@ -10,6 +10,7 @@ + @@ -25,6 +26,7 @@ + diff --git a/Frank.Testing.Tests/UnitTest1.cs b/Frank.Testing.Tests/TestLoggingTests.cs similarity index 94% rename from Frank.Testing.Tests/UnitTest1.cs rename to Frank.Testing.Tests/TestLoggingTests.cs index 8bd8a2e..57a0df4 100644 --- a/Frank.Testing.Tests/UnitTest1.cs +++ b/Frank.Testing.Tests/TestLoggingTests.cs @@ -10,11 +10,11 @@ namespace Frank.Testing.Tests; -public class UnitTest1 +public class TestLoggingTests { private readonly ITestOutputHelper _outputHelper; - public UnitTest1(ITestOutputHelper outputHelper) + public TestLoggingTests(ITestOutputHelper outputHelper) { _outputHelper = outputHelper; } diff --git a/Frank.Testing.Tests/TestOutputCSharpExtensionsTests.cs b/Frank.Testing.Tests/TestOutputCSharpExtensionsTests.cs new file mode 100644 index 0000000..938dc82 --- /dev/null +++ b/Frank.Testing.Tests/TestOutputCSharpExtensionsTests.cs @@ -0,0 +1,17 @@ +using JetBrains.Annotations; + +using Xunit.Abstractions; + +namespace Frank.Testing.Tests; + +[TestSubject(typeof(TestOutputCSharpExtensions))] +public class TestOutputCSharpExtensionsTests(ITestOutputHelper outputHelper) +{ + [Fact] + public void WriteCSharp_ShouldWriteCSharpOutput_WhenSourceIsSimpleObject() + { + var source = new TestPerson { Name = "John Doe", Age = 30 }; + + outputHelper.WriteCSharp(source); + } +} \ No newline at end of file diff --git a/Frank.Testing.Tests/TestOutputExtensionsTests.cs b/Frank.Testing.Tests/TestOutputExtensionsTests.cs index 8a2d241..a861aa8 100644 --- a/Frank.Testing.Tests/TestOutputExtensionsTests.cs +++ b/Frank.Testing.Tests/TestOutputExtensionsTests.cs @@ -4,7 +4,7 @@ namespace Frank.Testing.Tests; -[TestSubject(typeof(TestOutputExtensions))] +[TestSubject(typeof(TestOutputJsonExtensions))] public class TestOutputExtensionsTests { private readonly ITestOutputHelper _outputHelper; diff --git a/Frank.Testing.Tests/TestOutputXmlExtensionsTests.cs b/Frank.Testing.Tests/TestOutputXmlExtensionsTests.cs new file mode 100644 index 0000000..8e3d3df --- /dev/null +++ b/Frank.Testing.Tests/TestOutputXmlExtensionsTests.cs @@ -0,0 +1,40 @@ +using JetBrains.Annotations; + +using Xunit.Abstractions; + +namespace Frank.Testing.Tests; + +[TestSubject(typeof(TestOutputXmlExtensions))] +public class TestOutputXmlExtensionsTests(ITestOutputHelper outputHelper) +{ + [Fact] + public void WriteXml_ShouldWriteXmlOutput_WhenSourceIsSimpleObject() + { + var source = new TestPerson { Name = "John Doe", Age = 30 }; + + outputHelper.WriteXml(source); + } + + [Fact] + public void WriteXml_ShouldWriteXmlOutput_WhenSourceIsNestedObject() + { + var source = new TestPerson() { Name = "John Doe", Age = 30, Address = new TestAddress() { City = "Main City", ZipCode = 18846 } }; + outputHelper.WriteXml(source); + } + + [Fact] + public void WriteXml_ShouldHandleEmptyObjects() + { + var source = new TestPerson(); + + outputHelper.WriteXml(source); + } + + [Fact] + public void WriteXml_ShouldHandleNullObjects() + { + object? source = null; + + outputHelper.WriteXml(source); + } +} \ No newline at end of file diff --git a/Frank.Testing.Tests/TestingInfrastructure/TestAddress.cs b/Frank.Testing.Tests/TestingInfrastructure/TestAddress.cs new file mode 100644 index 0000000..3208c74 --- /dev/null +++ b/Frank.Testing.Tests/TestingInfrastructure/TestAddress.cs @@ -0,0 +1,8 @@ +namespace Frank.Testing.Tests; + +public class TestAddress +{ + public string City { get; set; } + + public int ZipCode { get; set; } +} \ No newline at end of file diff --git a/Frank.Testing.Tests/TestingInfrastructure/TestPerson.cs b/Frank.Testing.Tests/TestingInfrastructure/TestPerson.cs new file mode 100644 index 0000000..b0ad391 --- /dev/null +++ b/Frank.Testing.Tests/TestingInfrastructure/TestPerson.cs @@ -0,0 +1,9 @@ +namespace Frank.Testing.Tests; + +public class TestPerson +{ + public string Name { get; set; } + public int Age { get; set; } + + public TestAddress? Address { get; set; } +} \ No newline at end of file diff --git a/README.md b/README.md index f3f108b..d7eeef0 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,20 @@ public class MyTestClass [Fact] public void MyTestMethod() { - _outputHelper.WriteLine(new { MyProperty = "MyValue" }); + _outputHelper.WriteLine(new { MyProperty = "MyValue" }); // Writes to test output as JSON: {"MyProperty":"MyValue"} + _outputHelper.WriteJson(new { MyProperty = "MyValue" }); // Writes to test output as JSON: {"MyProperty":"MyValue"} + } + + [Fact] + public void MyTestMethod2() + { + _outputHelper.WriteCSharp(new { MyProperty = "MyValue" }); // Writes to test output as C#: var anonymousType = new { MyProperty = "MyValue" }; + } + + [Fact] + public void MyTestMethod3() + { + _outputHelper.WriteXml(new MyClass() { Name = "MyName" }); // Writes to test output as XML: MyName } } ```