From 377bdef1282c01ef6c9374ae6f3f55fd1e3170d3 Mon Sep 17 00:00:00 2001 From: Matt Whitfield Date: Wed, 13 Dec 2023 00:11:46 +0000 Subject: [PATCH] Fixture life cycle and ability to omit test class attributes (#240) --- .../Resources/OmitTestClassAttribute.txt | 11 +++++ .../Resources/UseConstructorForClassSetup.txt | 11 +++++ .../TestClasses.Designer.cs | 41 ++++++++++++++++++- src/Unitverse.Core.Tests/TestClasses.resx | 6 +++ .../Frameworks/Test/MsTestTestFramework.cs | 5 +++ .../Frameworks/Test/NUnitTestFramework.cs | 5 +++ .../Helpers/DetectedGenerationOptions.cs | 4 ++ .../Helpers/FrameworkSetHelper.cs | 12 ++++++ .../Options/IGenerationOptions.cs | 4 ++ .../Options/MutableGenerationOptions.cs | 4 ++ .../AbstractClassGenerationStrategy.cs | 6 +-- .../StandardClassGenerationStrategy.cs | 6 +-- .../StaticClassGenerationStrategy.cs | 6 +-- .../DefaultGenerationOptions.cs | 4 ++ src/Unitverse/Options/GenerationOptions.cs | 10 +++++ 15 files changed, 119 insertions(+), 16 deletions(-) create mode 100644 src/Unitverse.Core.Tests/Resources/OmitTestClassAttribute.txt create mode 100644 src/Unitverse.Core.Tests/Resources/UseConstructorForClassSetup.txt diff --git a/src/Unitverse.Core.Tests/Resources/OmitTestClassAttribute.txt b/src/Unitverse.Core.Tests/Resources/OmitTestClassAttribute.txt new file mode 100644 index 00000000..5a004daa --- /dev/null +++ b/src/Unitverse.Core.Tests/Resources/OmitTestClassAttribute.txt @@ -0,0 +1,11 @@ +// # OmitTestClassAttribute=true +namespace TestNamespace +{ + public class TestClass + { + public static string ParseTheThing(string input) + { + return string.Empty; + } + } +} \ No newline at end of file diff --git a/src/Unitverse.Core.Tests/Resources/UseConstructorForClassSetup.txt b/src/Unitverse.Core.Tests/Resources/UseConstructorForClassSetup.txt new file mode 100644 index 00000000..0a7b66c0 --- /dev/null +++ b/src/Unitverse.Core.Tests/Resources/UseConstructorForClassSetup.txt @@ -0,0 +1,11 @@ +// # UseConstructorForTestClassSetUp=true +namespace TestNamespace +{ + public class TestClass + { + public static string ParseTheThing(string input) + { + return string.Empty; + } + } +} \ No newline at end of file diff --git a/src/Unitverse.Core.Tests/TestClasses.Designer.cs b/src/Unitverse.Core.Tests/TestClasses.Designer.cs index b8c483e3..3e0ebbc3 100644 --- a/src/Unitverse.Core.Tests/TestClasses.Designer.cs +++ b/src/Unitverse.Core.Tests/TestClasses.Designer.cs @@ -1534,7 +1534,8 @@ public static string NullableReferenceTypes { } /// - /// Looks up a localized string similar to namespace TestNamespace.SubNameSpace + /// Looks up a localized string similar to // # UseFieldsForConstructorParameterTests=false + ///namespace TestNamespace.SubNameSpace ///{ /// using System; /// @@ -1562,6 +1563,25 @@ public static string OldStyleConstructorFieldTesting { } } + /// + /// Looks up a localized string similar to // # OmitTestClassAttribute=true + ///namespace TestNamespace + ///{ + /// public class TestClass + /// { + /// public static string ParseTheThing(string input) + /// { + /// return string.Empty; + /// } + /// } + ///}. + /// + public static string OmitTestClassAttribute { + get { + return ResourceManager.GetString("OmitTestClassAttribute", resourceCulture); + } + } + /// /// Looks up a localized string similar to namespace TestNamespace.SubNameSpace ///{ @@ -2161,6 +2181,25 @@ public static string TypeGenericDisambiguation { } } + /// + /// Looks up a localized string similar to // # UseConstructorForTestClassSetUp=true + ///namespace TestNamespace + ///{ + /// public class TestClass + /// { + /// public static string ParseTheThing(string input) + /// { + /// return string.Empty; + /// } + /// } + ///}. + /// + public static string UseConstructorForClassSetup { + get { + return ResourceManager.GetString("UseConstructorForClassSetup", resourceCulture); + } + } + /// /// Looks up a localized string similar to namespace SomeOtherNamespace ///{ diff --git a/src/Unitverse.Core.Tests/TestClasses.resx b/src/Unitverse.Core.Tests/TestClasses.resx index d7d34e58..e0f867ca 100644 --- a/src/Unitverse.Core.Tests/TestClasses.resx +++ b/src/Unitverse.Core.Tests/TestClasses.resx @@ -274,6 +274,9 @@ Resources\OldStyleConstructorFieldTesting.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + Resources\OmitTestClassAttribute.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + Resources\OperatorOverloading.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 @@ -343,6 +346,9 @@ Resources\TypeGenericDisambiguation.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + Resources\UseConstructorForClassSetup.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + Resources\UsingSort-Natural.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 diff --git a/src/Unitverse.Core/Frameworks/Test/MsTestTestFramework.cs b/src/Unitverse.Core/Frameworks/Test/MsTestTestFramework.cs index e288dde1..2260263f 100644 --- a/src/Unitverse.Core/Frameworks/Test/MsTestTestFramework.cs +++ b/src/Unitverse.Core/Frameworks/Test/MsTestTestFramework.cs @@ -159,6 +159,11 @@ public StatementSyntax AssertThrowsAsync(TypeSyntax exceptionType, ExpressionSyn protected override BaseMethodDeclarationSyntax CreateSetupMethodSyntax(string targetTypeName) { + if (Options.GenerationOptions.UseConstructorForTestClassSetUp) + { + return SyntaxFactory.ConstructorDeclaration(SyntaxFactory.Identifier(targetTypeName)).AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); + } + return Generate.Method("SetUp", false, false).AddAttributeLists(Generate.Attribute("TestInitialize").AsList()); } diff --git a/src/Unitverse.Core/Frameworks/Test/NUnitTestFramework.cs b/src/Unitverse.Core/Frameworks/Test/NUnitTestFramework.cs index be90a7fa..4372feec 100644 --- a/src/Unitverse.Core/Frameworks/Test/NUnitTestFramework.cs +++ b/src/Unitverse.Core/Frameworks/Test/NUnitTestFramework.cs @@ -164,6 +164,11 @@ public StatementSyntax AssertThrowsAsync(TypeSyntax exceptionType, ExpressionSyn protected override BaseMethodDeclarationSyntax CreateSetupMethodSyntax(string targetTypeName) { + if (Options.GenerationOptions.UseConstructorForTestClassSetUp) + { + return SyntaxFactory.ConstructorDeclaration(SyntaxFactory.Identifier(targetTypeName)).AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); + } + return Generate.Method("SetUp", false, false).AddAttributeLists(Generate.Attribute("SetUp").AsList()); } diff --git a/src/Unitverse.Core/Helpers/DetectedGenerationOptions.cs b/src/Unitverse.Core/Helpers/DetectedGenerationOptions.cs index 01d61c82..d6cd5317 100644 --- a/src/Unitverse.Core/Helpers/DetectedGenerationOptions.cs +++ b/src/Unitverse.Core/Helpers/DetectedGenerationOptions.cs @@ -92,5 +92,9 @@ public DetectedGenerationOptions(IGenerationOptions baseOptions, bool? usefluent public bool EmitMultilinePocoInitializers => _baseOptions.EmitMultilinePocoInitializers; public bool UseFieldsForConstructorParameterTests => _baseOptions.UseFieldsForConstructorParameterTests; + + public bool UseConstructorForTestClassSetUp => _baseOptions.UseConstructorForTestClassSetUp; + + public bool OmitTestClassAttribute => _baseOptions.OmitTestClassAttribute; } } diff --git a/src/Unitverse.Core/Helpers/FrameworkSetHelper.cs b/src/Unitverse.Core/Helpers/FrameworkSetHelper.cs index efcae1f0..b21fa090 100644 --- a/src/Unitverse.Core/Helpers/FrameworkSetHelper.cs +++ b/src/Unitverse.Core/Helpers/FrameworkSetHelper.cs @@ -28,5 +28,17 @@ public static ExpressionSyntax QualifyFieldReference(this IFrameworkSet framewor return nameSyntax; } + + public static ClassDeclarationSyntax ApplyTestClassAttribute(this IFrameworkSet frameworkSet, ClassDeclarationSyntax classDeclarationSyntax) + { + if (!frameworkSet.Options.GenerationOptions.OmitTestClassAttribute && + !string.IsNullOrWhiteSpace(frameworkSet.TestFramework.TestClassAttribute)) + { + var testFixtureAtt = Generate.Attribute(frameworkSet.TestFramework.TestClassAttribute); + return classDeclarationSyntax.AddAttributeLists(testFixtureAtt.AsList()); + } + + return classDeclarationSyntax; + } } } diff --git a/src/Unitverse.Core/Options/IGenerationOptions.cs b/src/Unitverse.Core/Options/IGenerationOptions.cs index 874bc98c..d8fb3523 100644 --- a/src/Unitverse.Core/Options/IGenerationOptions.cs +++ b/src/Unitverse.Core/Options/IGenerationOptions.cs @@ -71,5 +71,9 @@ public interface IGenerationOptions bool EmitMultilinePocoInitializers { get; } bool UseFieldsForConstructorParameterTests { get; } + + bool UseConstructorForTestClassSetUp { get; } + + bool OmitTestClassAttribute { get; } } } \ No newline at end of file diff --git a/src/Unitverse.Core/Options/MutableGenerationOptions.cs b/src/Unitverse.Core/Options/MutableGenerationOptions.cs index bdc2c0ee..923dca83 100644 --- a/src/Unitverse.Core/Options/MutableGenerationOptions.cs +++ b/src/Unitverse.Core/Options/MutableGenerationOptions.cs @@ -118,5 +118,9 @@ public MutableGenerationOptions(IGenerationOptions options) public bool EmitMultilinePocoInitializers { get; set; } public bool UseFieldsForConstructorParameterTests { get; set; } + + public bool UseConstructorForTestClassSetUp { get; set; } + + public bool OmitTestClassAttribute { get; set; } } } \ No newline at end of file diff --git a/src/Unitverse.Core/Strategies/ClassGeneration/AbstractClassGenerationStrategy.cs b/src/Unitverse.Core/Strategies/ClassGeneration/AbstractClassGenerationStrategy.cs index 5ec0ccfa..83b5665a 100644 --- a/src/Unitverse.Core/Strategies/ClassGeneration/AbstractClassGenerationStrategy.cs +++ b/src/Unitverse.Core/Strategies/ClassGeneration/AbstractClassGenerationStrategy.cs @@ -54,11 +54,7 @@ public ClassDeclarationSyntax Create(ClassModel model) var classDeclaration = SyntaxFactory.ClassDeclaration(targetTypeName); classDeclaration = classDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); - if (!string.IsNullOrWhiteSpace(_frameworkSet.TestFramework.TestClassAttribute)) - { - var testFixtureAtt = Generate.Attribute(_frameworkSet.TestFramework.TestClassAttribute); - classDeclaration = classDeclaration.AddAttributeLists(testFixtureAtt.AsList()); - } + classDeclaration = _frameworkSet.ApplyTestClassAttribute(classDeclaration); classDeclaration = classDeclaration.AddMembers(GenerateConcreteInheritor(model)); diff --git a/src/Unitverse.Core/Strategies/ClassGeneration/StandardClassGenerationStrategy.cs b/src/Unitverse.Core/Strategies/ClassGeneration/StandardClassGenerationStrategy.cs index 5b3a0591..5a34facf 100644 --- a/src/Unitverse.Core/Strategies/ClassGeneration/StandardClassGenerationStrategy.cs +++ b/src/Unitverse.Core/Strategies/ClassGeneration/StandardClassGenerationStrategy.cs @@ -53,11 +53,7 @@ public ClassDeclarationSyntax Create(ClassModel model) var classDeclaration = SyntaxFactory.ClassDeclaration(targetTypeName); classDeclaration = classDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); - if (!string.IsNullOrWhiteSpace(_frameworkSet.TestFramework.TestClassAttribute)) - { - var testFixtureAtt = Generate.Attribute(_frameworkSet.TestFramework.TestClassAttribute); - classDeclaration = classDeclaration.AddAttributeLists(testFixtureAtt.AsList()); - } + classDeclaration = _frameworkSet.ApplyTestClassAttribute(classDeclaration); var variableDeclaration = SyntaxFactory.VariableDeclaration(model.TypeSyntax) .AddVariables(SyntaxFactory.VariableDeclarator(model.TargetFieldName)); diff --git a/src/Unitverse.Core/Strategies/ClassGeneration/StaticClassGenerationStrategy.cs b/src/Unitverse.Core/Strategies/ClassGeneration/StaticClassGenerationStrategy.cs index 1a23bc5a..e9a1d431 100644 --- a/src/Unitverse.Core/Strategies/ClassGeneration/StaticClassGenerationStrategy.cs +++ b/src/Unitverse.Core/Strategies/ClassGeneration/StaticClassGenerationStrategy.cs @@ -69,11 +69,7 @@ public ClassDeclarationSyntax Create(ClassModel model) classDeclaration = classDeclaration.AddMembers(field); } - if (!string.IsNullOrWhiteSpace(_frameworkSet.TestFramework.TestClassAttribute)) - { - var testFixtureAtt = Generate.Attribute(_frameworkSet.TestFramework.TestClassAttribute); - classDeclaration = classDeclaration.AddAttributeLists(testFixtureAtt.AsList()); - } + classDeclaration = _frameworkSet.ApplyTestClassAttribute(classDeclaration); return classDeclaration; } diff --git a/src/Unitverse.Tests.Common/DefaultGenerationOptions.cs b/src/Unitverse.Tests.Common/DefaultGenerationOptions.cs index c33e02ad..6b5385e5 100644 --- a/src/Unitverse.Tests.Common/DefaultGenerationOptions.cs +++ b/src/Unitverse.Tests.Common/DefaultGenerationOptions.cs @@ -74,5 +74,9 @@ public class DefaultGenerationOptions : IGenerationOptions public bool EmitMultilinePocoInitializers { get; set; } = true; public bool UseFieldsForConstructorParameterTests { get; set; } = true; + + public bool UseConstructorForTestClassSetUp { get; set; } = false; + + public bool OmitTestClassAttribute { get; set; } = false; } } \ No newline at end of file diff --git a/src/Unitverse/Options/GenerationOptions.cs b/src/Unitverse/Options/GenerationOptions.cs index d985c705..c6ed2ac7 100644 --- a/src/Unitverse/Options/GenerationOptions.cs +++ b/src/Unitverse/Options/GenerationOptions.cs @@ -183,5 +183,15 @@ public class GenerationOptions : DialogPage, IGenerationOptions [DisplayName("Use fields for constructor parameter tests")] [Description("Whether to use fields for constructor parameter tests, or to create a new value for every test")] public bool UseFieldsForConstructorParameterTests { get; set; } = true; + + [Category("Generation")] + [DisplayName("Use constructor for test class set up")] + [Description("Whether to use constructor for test class set up instead of the framework set up method")] + public bool UseConstructorForTestClassSetUp { get; set; } = false; + + [Category("Generation")] + [DisplayName("Omit test class attribute")] + [Description("Whether to omit the attribute used to decorate test classes")] + public bool OmitTestClassAttribute { get; set; } = false; } } \ No newline at end of file