From f4246d9032dc520070e95c5dbbd36fdfaf9160f0 Mon Sep 17 00:00:00 2001 From: Simon Condon Date: Thu, 20 Oct 2022 15:54:26 +0100 Subject: [PATCH] Minor improvements to test case formatting. When outputting prereqs, items that don't override ToString (i.e. that just print out their type name) are now omitted. If that leaves nothing, fall back on using "test case #X". Also reverted to using v2 of abstractions. --- src/Directory.Build.props | 2 +- src/FlUnit/ActionTest.cs | 244 ++++++++++++++++++++++++++++++------- src/FlUnit/ActionTest.tt | 64 ++++++++-- src/FlUnit/FlUnit.csproj | 2 +- src/FlUnit/FunctionTest.cs | 232 ++++++++++++++++++++++++++++------- src/FlUnit/FunctionTest.tt | 62 ++++++++-- 6 files changed, 494 insertions(+), 112 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 440826c..940558c 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -15,7 +15,7 @@ true - 0.0.0-local.$([System.DateTime]::Now.ToString(yyMMdd.HHmm)) + 0.0.0-local.$([System.DateTime]::Now.ToString(yyMMddTHHmm)) diff --git a/src/FlUnit/ActionTest.cs b/src/FlUnit/ActionTest.cs index b3f169f..86c8d13 100644 --- a/src/FlUnit/ActionTest.cs +++ b/src/FlUnit/ActionTest.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; namespace FlUnit { @@ -73,6 +74,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Action act; internal TestActionOutcome invocationOutcome; @@ -81,14 +83,11 @@ public class Case : ITestCase Action act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -112,6 +111,8 @@ public void Act() } /// + // TODO: Ultimately I'd like to offer some light support for format strings - perhaps something like (empty/"g"/"G" for the current behaviour, ) + // i for "test case #", and (when there are multiple prereqs) an integer for the prequisite of that index. public string ToString(string format, IFormatProvider formatProvider) { return "[implicit test case]"; @@ -143,9 +144,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { @@ -251,6 +249,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Action act; internal readonly T1 prereqs; internal TestActionOutcome invocationOutcome; @@ -261,15 +260,12 @@ public class Case : ITestCase Action act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.prereqs = prereqs; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -293,9 +289,20 @@ public void Act() } /// + // TODO: Ultimately I'd like to offer some light support for format strings - perhaps something like (empty/"g"/"G" for the current behaviour, ) + // i for "test case #", and (when there are multiple prereqs) an integer for the prequisite of that index. public string ToString(string format, IFormatProvider formatProvider) { - return prereqs.ToString(); + string prereqToString = prereqs.ToString(); + + if (prereqToString.Equals(prereqs.GetType().ToString())) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else + { + return prereqToString; + } } /// @@ -324,9 +331,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { @@ -436,6 +440,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Action act; internal readonly (T1, T2) prereqs; internal TestActionOutcome invocationOutcome; @@ -446,15 +451,12 @@ public class Case : ITestCase Action act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.prereqs = prereqs; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -478,9 +480,49 @@ public void Act() } /// + // TODO: Ultimately I'd like to offer some light support for format strings - perhaps something like (empty/"g"/"G" for the current behaviour, ) + // i for "test case #", and (when there are multiple prereqs) an integer for the prequisite of that index. public string ToString(string format, IFormatProvider formatProvider) { - return prereqs.ToString(); + List nonTypeNames = new List(); + +#if NET6_0_OR_GREATER + var tuple = prereqs as ITuple; + for (var i = 0; i < tuple.Length; i++) + { + var item = tuple[i]; + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } +#else + void AddItemIfItOverridesToString(object item) + { + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } + + AddItemIfItOverridesToString(prereqs.Item1); + AddItemIfItOverridesToString(prereqs.Item2); +#endif + + if (nonTypeNames.Count == 0) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else if (nonTypeNames.Count == 1) + { + return nonTypeNames[0]; + } + else + { + return $"({string.Join(", ", nonTypeNames)})"; + } } /// @@ -509,9 +551,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { @@ -623,6 +662,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Action act; internal readonly (T1, T2, T3) prereqs; internal TestActionOutcome invocationOutcome; @@ -633,15 +673,12 @@ public class Case : ITestCase Action act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.prereqs = prereqs; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -665,9 +702,50 @@ public void Act() } /// + // TODO: Ultimately I'd like to offer some light support for format strings - perhaps something like (empty/"g"/"G" for the current behaviour, ) + // i for "test case #", and (when there are multiple prereqs) an integer for the prequisite of that index. public string ToString(string format, IFormatProvider formatProvider) { - return prereqs.ToString(); + List nonTypeNames = new List(); + +#if NET6_0_OR_GREATER + var tuple = prereqs as ITuple; + for (var i = 0; i < tuple.Length; i++) + { + var item = tuple[i]; + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } +#else + void AddItemIfItOverridesToString(object item) + { + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } + + AddItemIfItOverridesToString(prereqs.Item1); + AddItemIfItOverridesToString(prereqs.Item2); + AddItemIfItOverridesToString(prereqs.Item3); +#endif + + if (nonTypeNames.Count == 0) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else if (nonTypeNames.Count == 1) + { + return nonTypeNames[0]; + } + else + { + return $"({string.Join(", ", nonTypeNames)})"; + } } /// @@ -696,9 +774,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { @@ -812,6 +887,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Action act; internal readonly (T1, T2, T3, T4) prereqs; internal TestActionOutcome invocationOutcome; @@ -822,15 +898,12 @@ public class Case : ITestCase Action act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.prereqs = prereqs; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -854,9 +927,51 @@ public void Act() } /// + // TODO: Ultimately I'd like to offer some light support for format strings - perhaps something like (empty/"g"/"G" for the current behaviour, ) + // i for "test case #", and (when there are multiple prereqs) an integer for the prequisite of that index. public string ToString(string format, IFormatProvider formatProvider) { - return prereqs.ToString(); + List nonTypeNames = new List(); + +#if NET6_0_OR_GREATER + var tuple = prereqs as ITuple; + for (var i = 0; i < tuple.Length; i++) + { + var item = tuple[i]; + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } +#else + void AddItemIfItOverridesToString(object item) + { + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } + + AddItemIfItOverridesToString(prereqs.Item1); + AddItemIfItOverridesToString(prereqs.Item2); + AddItemIfItOverridesToString(prereqs.Item3); + AddItemIfItOverridesToString(prereqs.Item4); +#endif + + if (nonTypeNames.Count == 0) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else if (nonTypeNames.Count == 1) + { + return nonTypeNames[0]; + } + else + { + return $"({string.Join(", ", nonTypeNames)})"; + } } /// @@ -885,9 +1000,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { @@ -1003,6 +1115,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Action act; internal readonly (T1, T2, T3, T4, T5) prereqs; internal TestActionOutcome invocationOutcome; @@ -1013,15 +1126,12 @@ public class Case : ITestCase Action act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.prereqs = prereqs; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -1045,9 +1155,52 @@ public void Act() } /// + // TODO: Ultimately I'd like to offer some light support for format strings - perhaps something like (empty/"g"/"G" for the current behaviour, ) + // i for "test case #", and (when there are multiple prereqs) an integer for the prequisite of that index. public string ToString(string format, IFormatProvider formatProvider) { - return prereqs.ToString(); + List nonTypeNames = new List(); + +#if NET6_0_OR_GREATER + var tuple = prereqs as ITuple; + for (var i = 0; i < tuple.Length; i++) + { + var item = tuple[i]; + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } +#else + void AddItemIfItOverridesToString(object item) + { + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } + + AddItemIfItOverridesToString(prereqs.Item1); + AddItemIfItOverridesToString(prereqs.Item2); + AddItemIfItOverridesToString(prereqs.Item3); + AddItemIfItOverridesToString(prereqs.Item4); + AddItemIfItOverridesToString(prereqs.Item5); +#endif + + if (nonTypeNames.Count == 0) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else if (nonTypeNames.Count == 1) + { + return nonTypeNames[0]; + } + else + { + return $"({string.Join(", ", nonTypeNames)})"; + } } /// @@ -1076,9 +1229,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { diff --git a/src/FlUnit/ActionTest.tt b/src/FlUnit/ActionTest.tt index 2f2c068..e252b4c 100644 --- a/src/FlUnit/ActionTest.tt +++ b/src/FlUnit/ActionTest.tt @@ -9,6 +9,7 @@ using FlUnit.Configuration; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; namespace FlUnit { @@ -97,6 +98,7 @@ namespace FlUnit /// public class Case : ITestCase { + private readonly Test test; private readonly Action<#= TList(i, "<", ">") #> act; <# WriteLineIf(i > 0, $"internal readonly {PrereqsFieldType(i)} prereqs;", 3); #> internal TestActionOutcome invocationOutcome; @@ -107,15 +109,12 @@ namespace FlUnit Action<#= TList(i, "<", ">") #> act, Func> makeAssertions) { - this.Test = test; + this.test = test; <# WriteLineIf(i > 0, "this.prereqs = prereqs;", 4); #> this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -139,12 +138,64 @@ namespace FlUnit } /// + // TODO: Ultimately I'd like to offer some light support for format strings - perhaps something like (empty/"g"/"G" for the current behaviour, ) + // i for "test case #", and (when there are multiple prereqs) an integer for the prequisite of that index. public string ToString(string format, IFormatProvider formatProvider) { <# if (i == 0) { #> return "[implicit test case]"; +<# } else if (i == 1) { #> + string prereqToString = prereqs.ToString(); + + if (prereqToString.Equals(prereqs.GetType().ToString())) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else + { + return prereqToString; + } <# } else { #> - return prereqs.ToString(); + List nonTypeNames = new List(); + +#if NET6_0_OR_GREATER + var tuple = prereqs as ITuple; + for (var i = 0; i < tuple.Length; i++) + { + var item = tuple[i]; + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } +#else + void AddItemIfItOverridesToString(object item) + { + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } + +<# for (int j = 1; j <= i; j++) { #> + AddItemIfItOverridesToString(prereqs.Item<#= j #>); +<# } #> +#endif + + if (nonTypeNames.Count == 0) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else if (nonTypeNames.Count == 1) + { + return nonTypeNames[0]; + } + else + { + return $"({string.Join(", ", nonTypeNames)})"; + } <# } #> } @@ -174,9 +225,6 @@ namespace FlUnit this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { diff --git a/src/FlUnit/FlUnit.csproj b/src/FlUnit/FlUnit.csproj index 8221b42..5071580 100644 --- a/src/FlUnit/FlUnit.csproj +++ b/src/FlUnit/FlUnit.csproj @@ -65,7 +65,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/FlUnit/FunctionTest.cs b/src/FlUnit/FunctionTest.cs index 476b210..a2bd757 100644 --- a/src/FlUnit/FunctionTest.cs +++ b/src/FlUnit/FunctionTest.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; namespace FlUnit { @@ -76,6 +77,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Func act; internal TestFunctionOutcome invocationOutcome; @@ -84,14 +86,11 @@ public class Case : ITestCase Func act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -145,9 +144,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { @@ -256,6 +252,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Func act; internal readonly T1 prereqs; internal TestFunctionOutcome invocationOutcome; @@ -266,15 +263,12 @@ public class Case : ITestCase Func act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.prereqs = prereqs; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -299,7 +293,16 @@ public void Act() /// public string ToString(string format, IFormatProvider formatProvider) { - return prereqs.ToString(); + string prereqToString = prereqs.ToString(); + + if (prereqToString.Equals(prereqs.GetType().ToString())) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else + { + return prereqToString; + } } /// @@ -328,9 +331,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { @@ -443,6 +443,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Func act; internal readonly (T1, T2) prereqs; internal TestFunctionOutcome invocationOutcome; @@ -453,15 +454,12 @@ public class Case : ITestCase Func act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.prereqs = prereqs; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -486,7 +484,45 @@ public void Act() /// public string ToString(string format, IFormatProvider formatProvider) { - return prereqs.ToString(); + List nonTypeNames = new List(); + +#if NET6_0_OR_GREATER + var tuple = prereqs as ITuple; + for (var i = 0; i < tuple.Length; i++) + { + var item = tuple[i]; + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } +#else + void AddItemIfItOverridesToString(object item) + { + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } + + AddItemIfItOverridesToString(prereqs.Item1); + AddItemIfItOverridesToString(prereqs.Item2); +#endif + + if (nonTypeNames.Count == 0) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else if (nonTypeNames.Count == 1) + { + return nonTypeNames[0]; + } + else + { + return $"({string.Join(", ", nonTypeNames)})"; + } } /// @@ -515,9 +551,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { @@ -632,6 +665,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Func act; internal readonly (T1, T2, T3) prereqs; internal TestFunctionOutcome invocationOutcome; @@ -642,15 +676,12 @@ public class Case : ITestCase Func act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.prereqs = prereqs; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -675,7 +706,46 @@ public void Act() /// public string ToString(string format, IFormatProvider formatProvider) { - return prereqs.ToString(); + List nonTypeNames = new List(); + +#if NET6_0_OR_GREATER + var tuple = prereqs as ITuple; + for (var i = 0; i < tuple.Length; i++) + { + var item = tuple[i]; + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } +#else + void AddItemIfItOverridesToString(object item) + { + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } + + AddItemIfItOverridesToString(prereqs.Item1); + AddItemIfItOverridesToString(prereqs.Item2); + AddItemIfItOverridesToString(prereqs.Item3); +#endif + + if (nonTypeNames.Count == 0) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else if (nonTypeNames.Count == 1) + { + return nonTypeNames[0]; + } + else + { + return $"({string.Join(", ", nonTypeNames)})"; + } } /// @@ -704,9 +774,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { @@ -823,6 +890,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Func act; internal readonly (T1, T2, T3, T4) prereqs; internal TestFunctionOutcome invocationOutcome; @@ -833,15 +901,12 @@ public class Case : ITestCase Func act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.prereqs = prereqs; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -866,7 +931,47 @@ public void Act() /// public string ToString(string format, IFormatProvider formatProvider) { - return prereqs.ToString(); + List nonTypeNames = new List(); + +#if NET6_0_OR_GREATER + var tuple = prereqs as ITuple; + for (var i = 0; i < tuple.Length; i++) + { + var item = tuple[i]; + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } +#else + void AddItemIfItOverridesToString(object item) + { + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } + + AddItemIfItOverridesToString(prereqs.Item1); + AddItemIfItOverridesToString(prereqs.Item2); + AddItemIfItOverridesToString(prereqs.Item3); + AddItemIfItOverridesToString(prereqs.Item4); +#endif + + if (nonTypeNames.Count == 0) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else if (nonTypeNames.Count == 1) + { + return nonTypeNames[0]; + } + else + { + return $"({string.Join(", ", nonTypeNames)})"; + } } /// @@ -895,9 +1000,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { @@ -1016,6 +1118,7 @@ public override void Dispose() /// public class Case : ITestCase { + private readonly Test test; private readonly Func act; internal readonly (T1, T2, T3, T4, T5) prereqs; internal TestFunctionOutcome invocationOutcome; @@ -1026,15 +1129,12 @@ public class Case : ITestCase Func act, Func> makeAssertions) { - this.Test = test; + this.test = test; this.prereqs = prereqs; this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -1059,7 +1159,48 @@ public void Act() /// public string ToString(string format, IFormatProvider formatProvider) { - return prereqs.ToString(); + List nonTypeNames = new List(); + +#if NET6_0_OR_GREATER + var tuple = prereqs as ITuple; + for (var i = 0; i < tuple.Length; i++) + { + var item = tuple[i]; + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } +#else + void AddItemIfItOverridesToString(object item) + { + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } + + AddItemIfItOverridesToString(prereqs.Item1); + AddItemIfItOverridesToString(prereqs.Item2); + AddItemIfItOverridesToString(prereqs.Item3); + AddItemIfItOverridesToString(prereqs.Item4); + AddItemIfItOverridesToString(prereqs.Item5); +#endif + + if (nonTypeNames.Count == 0) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else if (nonTypeNames.Count == 1) + { + return nonTypeNames[0]; + } + else + { + return $"({string.Join(", ", nonTypeNames)})"; + } } /// @@ -1088,9 +1229,6 @@ public class Assertion : ITestAssertion this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() { diff --git a/src/FlUnit/FunctionTest.tt b/src/FlUnit/FunctionTest.tt index ede17a1..f0de633 100644 --- a/src/FlUnit/FunctionTest.tt +++ b/src/FlUnit/FunctionTest.tt @@ -9,6 +9,7 @@ using FlUnit.Configuration; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; namespace FlUnit { @@ -100,6 +101,7 @@ namespace FlUnit /// public class Case : ITestCase { + private readonly Test test; private readonly Func<<#= TList(i, "", ", ") #>TResult> act; <# WriteLineIf(i > 0, $"internal readonly {PrereqsFieldType(i)} prereqs;", 3); #> internal TestFunctionOutcome invocationOutcome; @@ -110,15 +112,12 @@ namespace FlUnit Func<<#= TList(i, "", ", ") #>TResult> act, Func> makeAssertions) { - this.Test = test; + this.test = test; <# WriteLineIf(i > 0, "this.prereqs = prereqs;", 4); #> this.act = act; this.Assertions = makeAssertions(this).ToArray(); } - /// - public Test Test { get; } - /// public IReadOnlyCollection Assertions { get; } @@ -145,8 +144,58 @@ namespace FlUnit { <# if (i == 0) { #> return "[implicit test case]"; +<# } else if (i == 1) { #> + string prereqToString = prereqs.ToString(); + + if (prereqToString.Equals(prereqs.GetType().ToString())) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else + { + return prereqToString; + } <# } else { #> - return prereqs.ToString(); + List nonTypeNames = new List(); + +#if NET6_0_OR_GREATER + var tuple = prereqs as ITuple; + for (var i = 0; i < tuple.Length; i++) + { + var item = tuple[i]; + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } +#else + void AddItemIfItOverridesToString(object item) + { + var itemToString = item.ToString(); + if (!itemToString.Equals(item.GetType().ToString())) + { + nonTypeNames.Add(itemToString); + } + } + +<# for (int j = 1; j <= i; j++) { #> + AddItemIfItOverridesToString(prereqs.Item<#= j #>); +<# } #> +#endif + + if (nonTypeNames.Count == 0) + { + return $"test case #{Array.IndexOf(test.Cases.ToArray(), this) + 1}"; + } + else if (nonTypeNames.Count == 1) + { + return nonTypeNames[0]; + } + else + { + return $"({string.Join(", ", nonTypeNames)})"; + } <# } #> } @@ -176,9 +225,6 @@ namespace FlUnit this.description = description; } - /// - public ITestCase TestCase => testCase; - /// public void Assert() {