├── assets ├── SourceClass.png ├── SolutionContextMenu.png ├── CodeEditorContextMenu.png └── SourceClassTestsAnnotated.png ├── src ├── SentryOne.UnitTestGenerator.Core │ ├── AssemblyInfo.cs │ ├── Key.snk │ ├── Assets │ │ ├── TargetAsset.cs │ │ ├── IAsset.cs │ │ ├── AssetFactory.cs │ │ └── PropertyTesterAsset.cs │ ├── Helpers │ │ ├── IMessageLogger.cs │ │ ├── Ignore.cs │ │ ├── IGenerationContext.cs │ │ ├── StandardReferenceHelper.cs │ │ ├── NamespaceTransform.cs │ │ ├── SymbolExtensions.cs │ │ ├── GenerationContext.cs │ │ ├── StringExtensions.cs │ │ └── NameExtractor.cs │ ├── Models │ │ ├── INugetPackageReference.cs │ │ ├── ITestableModel.cs │ │ ├── IConstructorModel.cs │ │ ├── IInterfaceModel.cs │ │ ├── IPropertyModel.cs │ │ ├── IIndexerModel.cs │ │ ├── IReferencedAssembly.cs │ │ ├── GenerationResult.cs │ │ ├── IOperatorModel.cs │ │ ├── IMethodModel.cs │ │ ├── NugetPackageReference.cs │ │ ├── ParameterModel.cs │ │ ├── ConstructorModel.cs │ │ ├── InterfaceModel.cs │ │ ├── IndexerModel.cs │ │ ├── PropertyModel.cs │ │ ├── TestableModel.cs │ │ ├── ReferencedAssembly.cs │ │ └── SemanticVersion.cs │ ├── Options │ │ ├── MockingFrameworkType.cs │ │ ├── IUnitTestGeneratorOptions.cs │ │ ├── TestFrameworkTypes.cs │ │ ├── IGenerationOptions.cs │ │ ├── IVersioningOptions.cs │ │ ├── UnitTestGeneratorOptions.cs │ │ ├── EditorConfigFieldMapper.cs │ │ ├── MutableGenerationOptions.cs │ │ ├── MutableVersioningOptions.cs │ │ └── UnitTestGeneratorOptionsFactory.cs │ ├── Frameworks │ │ ├── IFrameworkSet.cs │ │ ├── IMockingFramework.cs │ │ ├── FrameworkSet.cs │ │ ├── Test │ │ │ ├── NUnit2TestFramework.cs │ │ │ └── NUnit3TestFramework.cs │ │ └── ITestFramework.cs │ └── Strategies │ │ ├── ClassGeneration │ │ ├── IClassGenerationStrategy.cs │ │ └── ClassGenerationStrategyFactory.cs │ │ ├── IGenerationStrategy.cs │ │ ├── ClassDecoration │ │ ├── IClassDecorationStrategy.cs │ │ └── ClassDecorationStrategyFactory.cs │ │ ├── ValueGeneration │ │ ├── IValueGenerationStrategy.cs │ │ ├── BrushFactory.cs │ │ ├── EnumFactory.cs │ │ ├── SimpleValueGenerationStrategy.cs │ │ └── TypedValueGenerationStrategy.cs │ │ ├── OperatorGeneration │ │ └── OperatorGenerationStrategyFactory.cs │ │ ├── ItemGenerationStrategyFactory.cs │ │ ├── IndexerGeneration │ │ └── IndexerGenerationStrategyFactory.cs │ │ ├── MethodGeneration │ │ └── MethodGenerationStrategyFactory.cs │ │ ├── ClassLevelGeneration │ │ └── ClassLevelGenerationStrategyFactory.cs │ │ ├── PropertyGeneration │ │ └── PropertyGenerationStrategyFactory.cs │ │ └── InterfaceGeneration │ │ └── InterfaceGenerationStrategyFactory.cs ├── SentryOne.UnitTestGenerator.Core.Tests │ ├── AssemblyInfo.cs │ ├── Resources │ │ ├── ArrowPropertyGetter.txt │ │ ├── DefaultParameterRequiresUsing.txt │ │ ├── AbstractImplicitConstructor.txt │ │ ├── DependencyObjectTestFile.txt │ │ ├── ByteArray.txt │ │ ├── WinformTestFile.txt │ │ ├── GenericMethodTestFile.txt │ │ ├── RepeatedValueTypeParameters.txt │ │ ├── TypeGenericDisambiguation.txt │ │ ├── ConstructorGenericTestFile.txt │ │ ├── StaticTestFile.txt │ │ ├── ExtensionMethod.txt │ │ ├── AsyncMethod.txt │ │ ├── ChainedClassesTestFile.txt │ │ ├── AbstractSelfReferencingClass.txt │ │ ├── MappingMethod.txt │ │ ├── RefAndOutParameters.txt │ │ ├── Singleton.txt │ │ ├── IEnumerableClass.txt │ │ ├── PocoInitialization.txt │ │ ├── AsyncMappingMethod.txt │ │ ├── IndexerTestFile.txt │ │ ├── InterfaceImplementationTestFile.txt │ │ ├── AbstractChainTextFile.txt │ │ ├── IComparableTestFile.txt │ │ ├── AbstractProperty.txt │ │ ├── OverloadGenericDisambiguation.txt │ │ ├── SampleClassTestFile.txt │ │ ├── Generate.txt │ │ ├── InterfaceSampleTestFile.txt │ │ ├── TestTextFile.txt │ │ ├── AbstractClassTestFile.txt │ │ ├── OperatorOverloading.txt │ │ ├── NestedClassTestFile.txt │ │ ├── PropertyChangeTestFile.txt │ │ ├── GenericCollection.txt │ │ ├── ConstructorSamplesTestFile.txt │ │ └── SemanticVersion.txt │ ├── Helpers │ │ ├── IgnoreTests.cs │ │ ├── SymbolExtensionsTests.cs │ │ ├── NameExtractorTests.cs │ │ ├── NamespaceTransformTests.cs │ │ ├── StringExtensionsTests.cs │ │ ├── GenerationContextTests.cs │ │ └── StandardReferenceHelperTests.cs │ ├── Assets │ │ ├── AssetFactoryTests.cs │ │ └── PropertyTesterAssetTests.cs │ ├── GlobalSuppressions.cs │ ├── Frameworks │ │ └── Test │ │ │ ├── XUnitTestFrameworkTests.cs │ │ │ ├── MsTestTestFrameworkTests.cs │ │ │ ├── NUnit2TestFrameworkTests.cs │ │ │ ├── NUnit3TestFrameworkTests.cs │ │ │ └── NUnitTestFrameworkTests.cs │ ├── Models │ │ ├── OperatorModelTests.cs │ │ ├── SemanticVersionTests.cs │ │ ├── GenerationResultTests.cs │ │ ├── NugetPackageReferenceTests.cs │ │ └── PropertyModelTests.cs │ ├── Strategies │ │ ├── ValueGeneration │ │ │ └── EnumFactoryTests.cs │ │ ├── MethodGeneration │ │ │ └── MethodGenerationStrategyFactoryTests.cs │ │ ├── IndexerGeneration │ │ │ └── IndexerGenerationStrategyFactoryTests.cs │ │ ├── OperatorGeneration │ │ │ └── OperatorGenerationStrategyFactoryTests.cs │ │ ├── PropertyGeneration │ │ │ └── PropertyGenerationStrategyFactoryTests.cs │ │ ├── InterfaceGeneration │ │ │ ├── InterfaceGenerationStrategyFactoryTests.cs │ │ │ └── EnumerableGenerationStrategyTests.cs │ │ ├── ClassLevelGeneration │ │ │ └── ClassLevelGenerationStrategyFactoryTests.cs │ │ └── ClassGeneration │ │ │ ├── ClassGenerationStrategyFactoryTests.cs │ │ │ ├── StaticClassGenerationStrategyTests.cs │ │ │ ├── AbstractClassGenerationStrategyTests.cs │ │ │ └── StandardClassGenerationStrategyTests.cs │ ├── Options │ │ ├── EditorConfigFieldMapperTests.cs │ │ └── UnitTestGeneratorOptionsTests.cs │ └── Properties │ │ └── AssemblyInfo.cs ├── SentryOne.UnitTestGenerator │ ├── Key.snk │ ├── Resources │ │ ├── CommandImages.png │ │ ├── UnitTestGeneratorPackage.ico │ │ ├── UnitTestGeneratorPackage.png │ │ └── DisconnectedFileHeader.txt │ ├── Helper │ │ ├── FindTargetStatus.cs │ │ ├── EnvDteConstants.cs │ │ ├── AggregateLogger.cs │ │ ├── StatusBarMessageLogger.cs │ │ └── OutputWindowMessageLogger.cs │ ├── Constants.cs │ ├── IUnitTestGeneratorPackage.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── source.extension.vsixmanifest ├── SentryOne.UnitTestGenerator.Tests │ └── SentryOne.UnitTestGenerator.Tests.csproj ├── SentryOne.UnitTestGenerator.ruleset └── SentryOne.UnitTestGenerator.Specs │ ├── VersionOptions.cs │ ├── BaseContext.cs │ ├── notes.md │ ├── Strategies │ ├── PropertyGenerator │ │ ├── SingleConstructorInitializedPropertyGeneration.feature │ │ └── ReadOnlyPropertyGeneration.feature │ ├── Regeneration │ │ ├── GenericRegeneration.feature │ │ └── Regeneration.feature │ ├── ClassLevelGeneration │ │ ├── CanConstructSingleConstructorGeneration.feature │ │ ├── CanConstructNoConstructorGeneration.feature │ │ ├── NullParameterCheckConstructorGeneration.feature │ │ ├── CanConstructMultiConstructorGeneration.feature │ │ └── StringParameterCheckConstructorGeneration.feature │ ├── InterfaceGeneration │ │ ├── EnumerableGeneration.feature │ │ └── ComparableGeneration.feature │ ├── MethodGeneration │ │ └── MappingMethodGeneration.feature │ ├── ClassGeneration │ │ ├── StaticClassGeneration.feature │ │ └── StandardClassGeneration.feature │ └── IndexerGeneration │ │ ├── WriteOnlyIndexerGeneration.feature │ │ ├── ReadOnlyIndexerGeneration.feature │ │ └── ReadWriteIndexGeneration.feature │ ├── GenerationOptions.cs │ ├── MethodBasedStrategyContext.cs │ ├── ClassBasedStrategyContext.cs │ ├── BaseSteps.cs │ └── MockGeneration │ └── MockGeneration.feature ├── nuget.config ├── publishManifest.json └── contributing.md /assets/SourceClass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sentryone/unittestgenerator/HEAD/assets/SourceClass.png -------------------------------------------------------------------------------- /assets/SolutionContextMenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sentryone/unittestgenerator/HEAD/assets/SolutionContextMenu.png -------------------------------------------------------------------------------- /assets/CodeEditorContextMenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sentryone/unittestgenerator/HEAD/assets/CodeEditorContextMenu.png -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Resources; 2 | 3 | [assembly: NeutralResourcesLanguage("en")] -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Resources; 2 | 3 | [assembly: NeutralResourcesLanguage("en")] -------------------------------------------------------------------------------- /assets/SourceClassTestsAnnotated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sentryone/unittestgenerator/HEAD/assets/SourceClassTestsAnnotated.png -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sentryone/unittestgenerator/HEAD/src/SentryOne.UnitTestGenerator/Key.snk -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sentryone/unittestgenerator/HEAD/src/SentryOne.UnitTestGenerator.Core/Key.snk -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Resources/CommandImages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sentryone/unittestgenerator/HEAD/src/SentryOne.UnitTestGenerator/Resources/CommandImages.png -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Assets/TargetAsset.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Assets 2 | { 3 | public enum TargetAsset 4 | { 5 | PropertyTester, 6 | } 7 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Resources/UnitTestGeneratorPackage.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sentryone/unittestgenerator/HEAD/src/SentryOne.UnitTestGenerator/Resources/UnitTestGeneratorPackage.ico -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Resources/UnitTestGeneratorPackage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sentryone/unittestgenerator/HEAD/src/SentryOne.UnitTestGenerator/Resources/UnitTestGeneratorPackage.png -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Helpers/IMessageLogger.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Helpers 2 | { 3 | public interface IMessageLogger 4 | { 5 | void Initialize(); 6 | 7 | void LogMessage(string message); 8 | } 9 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/INugetPackageReference.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | public interface INugetPackageReference 4 | { 5 | string Name { get; } 6 | 7 | string Version { get; } 8 | } 9 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Helper/FindTargetStatus.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Helper 2 | { 3 | internal enum FindTargetStatus 4 | { 5 | Found, 6 | FileNotFound, 7 | FolderNotFound, 8 | ProjectNotFound, 9 | } 10 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/ArrowPropertyGetter.txt: -------------------------------------------------------------------------------- 1 | public class TestClass 2 | { 3 | string _str1; 4 | 5 | public TestClass(string str1) 6 | { 7 | _str1 = str1; 8 | } 9 | 10 | public string Str1 => _str1; 11 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Options/MockingFrameworkType.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Options 2 | { 3 | public enum MockingFrameworkType 4 | { 5 | NSubstitute, 6 | Moq, 7 | RhinoMocks, 8 | FakeItEasy, 9 | } 10 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Options/IUnitTestGeneratorOptions.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Options 2 | { 3 | public interface IUnitTestGeneratorOptions 4 | { 5 | IGenerationOptions GenerationOptions { get; } 6 | 7 | IVersioningOptions VersioningOptions { get; } 8 | } 9 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/DefaultParameterRequiresUsing.txt: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Collections.Generic; 3 | 4 | namespace WindowsFormsApp1 5 | { 6 | public partial class Form1 7 | { 8 | public Form1(IEnumerable brushes) 9 | { 10 | 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/ITestableModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | public interface ITestableModel 4 | { 5 | string Name { get; } 6 | 7 | string OriginalName { get; } 8 | 9 | T Node { get; } 10 | 11 | void MutateName(string newName); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Assets/IAsset.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Assets 2 | { 3 | using SentryOne.UnitTestGenerator.Core.Options; 4 | 5 | public interface IAsset 6 | { 7 | string AssetFileName { get; } 8 | 9 | string Content(string targetNamespace, TestFrameworkTypes testFrameworkTypes); 10 | } 11 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator 2 | { 3 | internal static class Constants 4 | { 5 | #pragma warning disable SA1401 // Fields should be private 6 | public static string ExtensionName = "SentryOne Unit Test Generator"; 7 | #pragma warning restore SA1401 // Fields should be private 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Assets/AssetFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Assets 2 | { 3 | public static class AssetFactory 4 | { 5 | public static IAsset Create(TargetAsset assetType) 6 | { 7 | return assetType == TargetAsset.PropertyTester ? new PropertyTesterAsset() : null; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/AbstractImplicitConstructor.txt: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows; 3 | 4 | namespace TestNamespace { 5 | public abstract class TestClass 6 | { 7 | public abstract int SomeMethod(); 8 | 9 | public int IntProperty { get; set; } 10 | 11 | public abstract string SomePublicAbstractMethod(int p, int r); 12 | } 13 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/IConstructorModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.CodeAnalysis.CSharp.Syntax; 5 | 6 | public interface IConstructorModel : ITestableModel 7 | { 8 | IList Parameters { get; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/DependencyObjectTestFile.txt: -------------------------------------------------------------------------------- 1 | 2 | using System.Drawing; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | 8 | namespace WindowsFormsApp1 9 | { 10 | public class Form1 : Window 11 | { 12 | public Form1() 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Resources/DisconnectedFileHeader.txt: -------------------------------------------------------------------------------- 1 | // This file was generated with SentryOne Unit Test Generator 2 | 3 | // It has not been added to a test project because an existing test project was not found 4 | // and the 'Automatically create Tests project' setting is turned off. 5 | 6 | // To change this, please go to Tools -> Options -> SentryOne Unit Test Generator 7 | 8 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/ByteArray.txt: -------------------------------------------------------------------------------- 1 | namespace TestNamespace 2 | { 3 | public class TestClass 4 | { 5 | public TestClass(byte[] array, ulong unsignedLong, uint unsignedInt, decimal dec, short sh, ushort ush, byte b, sbyte s, double d, float f, bool boo) 6 | { 7 | Array = array; 8 | } 9 | 10 | public byte[] Array { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/WinformTestFile.txt: -------------------------------------------------------------------------------- 1 | 2 | using System.Drawing; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Forms; 7 | 8 | namespace WindowsFormsApp1 9 | { 10 | public partial class Form1 : Form 11 | { 12 | public Form1(Color c, Brush b) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Frameworks/IFrameworkSet.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Frameworks 2 | { 3 | using SentryOne.UnitTestGenerator.Core.Helpers; 4 | 5 | public interface IFrameworkSet 6 | { 7 | ITestFramework TestFramework { get; } 8 | 9 | IMockingFramework MockingFramework { get; } 10 | 11 | IGenerationContext Context { get; } 12 | 13 | string TestTypeNaming { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/GenericMethodTestFile.txt: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Forms; 8 | 9 | namespace WindowsFormsApp1 10 | { 11 | public class GTest 12 | { 13 | public void DoStuff(Guid g, DateTime dtParam, T theThing, int? thing2) 14 | { 15 | 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/IInterfaceModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.CodeAnalysis; 5 | 6 | public interface IInterfaceModel 7 | { 8 | string InterfaceName { get; } 9 | 10 | bool IsGeneric { get; } 11 | 12 | IList GenericTypes { get; } 13 | 14 | INamedTypeSymbol InterfaceType { get; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Helper/EnvDteConstants.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Helper 2 | { 3 | internal static class EnvDteConstants 4 | { 5 | public const string VsViewKindTextView = "{7651A703-06E5-11D1-8EBD-00A0C90F26EA}"; 6 | public const string VsProjectItemKindPhysicalFolder = "{6BB5F8EF-4483-11D3-8BCF-00C04F8EC28C}"; 7 | public const string VsProjectItemKindPhysicalFile = "{6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}"; 8 | } 9 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/IPropertyModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using Microsoft.CodeAnalysis; 4 | using Microsoft.CodeAnalysis.CSharp.Syntax; 5 | 6 | public interface IPropertyModel : ITestableModel 7 | { 8 | bool HasGet { get; } 9 | 10 | bool HasSet { get; } 11 | 12 | TypeInfo TypeInfo { get; } 13 | 14 | bool IsStatic { get; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/RepeatedValueTypeParameters.txt: -------------------------------------------------------------------------------- 1 | namespace TestNamespace.SubNameSpace 2 | { 3 | public class InnerClass 4 | { 5 | public InnerClass(int intParam1, int intParam2, int intParam3, string stringParam1, string stringParam2, string stringParam3) 6 | { 7 | 8 | } 9 | } 10 | 11 | public class OuterClass 12 | { 13 | public OuterClass(InnerClass innerClass) 14 | { 15 | 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ClassGeneration/IClassGenerationStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.ClassGeneration 2 | { 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using SentryOne.UnitTestGenerator.Core.Models; 5 | 6 | public interface IClassGenerationStrategy 7 | { 8 | int Priority { get; } 9 | 10 | bool CanHandle(ClassModel model); 11 | 12 | ClassDeclarationSyntax Create(ClassModel model); 13 | } 14 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Helpers/IgnoreTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Helpers 2 | { 3 | using NUnit.Framework; 4 | using SentryOne.UnitTestGenerator.Core.Helpers; 5 | 6 | [TestFixture] 7 | public static class IgnoreTests 8 | { 9 | [Test] 10 | public static void CanCallHResult() 11 | { 12 | var result = 1512227133; 13 | Assert.DoesNotThrow(() => Ignore.HResult(result)); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/TypeGenericDisambiguation.txt: -------------------------------------------------------------------------------- 1 | namespace TestNamespace.SubNameSpace 2 | { 3 | public class TestClass 4 | { 5 | public void ThisIsAMethod(string methodName) 6 | { 7 | System.Console.WriteLine("Testing this"); 8 | } 9 | } 10 | 11 | public class TestClass 12 | { 13 | public void ThisIsAMethod(string methodName) 14 | { 15 | System.Console.WriteLine("Testing this"); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Options/TestFrameworkTypes.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Options 2 | { 3 | using System; 4 | using System.ComponentModel; 5 | 6 | [Flags] 7 | public enum TestFrameworkTypes 8 | { 9 | [Description("NUnit v2")] 10 | NUnit2 = 1, 11 | [Description("NUnit v3")] 12 | NUnit3 = 2, 13 | [Description("MSTest v2")] 14 | MsTest = 4, 15 | [Description("xUnit")] 16 | XUnit = 8, 17 | } 18 | } -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/ConstructorGenericTestFile.txt: -------------------------------------------------------------------------------- 1 | namespace AssemblyCore 2 | { 3 | public class ConstructorGereric 4 | { 5 | public T T1 { get; } 6 | public U U1 { get; } 7 | public T T2 { get; } 8 | 9 | 10 | public ConstructorGereric(T t1) 11 | { 12 | T1 = t1; 13 | } 14 | 15 | public ConstructorGereric(T t1, U u1) 16 | { 17 | T1 = t1; 18 | U1 = u1; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/IIndexerModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | 7 | public interface IIndexerModel : ITestableModel 8 | { 9 | IList Parameters { get; } 10 | 11 | TypeInfo TypeInfo { get; } 12 | 13 | bool HasGet { get; } 14 | 15 | bool HasSet { get; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/IReferencedAssembly.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System; 4 | 5 | public interface IReferencedAssembly 6 | { 7 | string Name { get; } 8 | 9 | // this is because nunit.framework is the same for v2 and v3 - so we need to have a locatable name that contains a version reference 10 | string LocatableName { get; } 11 | 12 | Version Version { get; } 13 | 14 | string Location { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Helpers/Ignore.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Helpers 2 | { 3 | public static class Ignore 4 | { 5 | [System.Diagnostics.CodeAnalysis.SuppressMessage( 6 | "Microsoft.Usage", 7 | "CA1801:ReviewUnusedParameters", 8 | MessageId = "result", 9 | Justification = "Helper method to notify in code that we don't care about the result.")] 10 | public static void HResult(int? result) 11 | { 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Helpers/IGenerationContext.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Helpers 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.CodeAnalysis; 5 | 6 | public interface IGenerationContext 7 | { 8 | IEnumerable EmittedTypes { get; } 9 | 10 | IEnumerable GenericTypes { get; } 11 | 12 | bool MocksUsed { get; set; } 13 | 14 | void AddEmittedType(ITypeSymbol typeInfo); 15 | 16 | void AddGenericType(string identifier); 17 | } 18 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/IGenerationStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.CodeAnalysis.CSharp.Syntax; 5 | using SentryOne.UnitTestGenerator.Core.Models; 6 | 7 | public interface IGenerationStrategy 8 | { 9 | bool IsExclusive { get; } 10 | 11 | int Priority { get; } 12 | 13 | bool CanHandle(T member, ClassModel model); 14 | 15 | IEnumerable Create(T method, ClassModel model); 16 | } 17 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Assets/AssetFactoryTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Assets 2 | { 3 | using NUnit.Framework; 4 | using SentryOne.UnitTestGenerator.Core.Assets; 5 | 6 | [TestFixture] 7 | public static class AssetFactoryTests 8 | { 9 | [Test] 10 | public static void CanCallCreate() 11 | { 12 | var assetType = TargetAsset.PropertyTester; 13 | var result = AssetFactory.Create(assetType); 14 | Assert.That(result, Is.InstanceOf()); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // This file is used by Code Analysis to maintain SuppressMessage 2 | // attributes that are applied to this project. 3 | // Project-level suppressions either have no target or are given 4 | // a specific target and scoped to a namespace, type, member, etc. 5 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "Test Project")] 6 | ////, Target = "~M:SentryOne.UnitTestGenerator.Core.Tests.Frameworks.Mocking.FakeItEasyMockingFrameworkTests.CanCallMockInterface" 7 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/StaticTestFile.txt: -------------------------------------------------------------------------------- 1 | namespace TestNamespace.SubNameSpace 2 | { 3 | using System.Globalization; 4 | 5 | public static class TestClass 6 | { 7 | public static void ThisIsAMethod(string methodName, CultureInfo methodValue) 8 | { 9 | System.Console.WriteLine("Testing this"); 10 | } 11 | 12 | public static string WillReturnAString() 13 | { 14 | return "Hello"; 15 | } 16 | 17 | public static int ThisIsAProperty { get; set; } 18 | 19 | public static string GetITest { get; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ClassDecoration/IClassDecorationStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.ClassDecoration 2 | { 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using SentryOne.UnitTestGenerator.Core.Models; 5 | 6 | internal interface IClassDecorationStrategy 7 | { 8 | bool IsExclusive { get; } 9 | 10 | int Priority { get; } 11 | 12 | TypeDeclarationSyntax Apply(TypeDeclarationSyntax declaration, ClassModel model); 13 | 14 | bool CanHandle(TypeDeclarationSyntax existingSyntax, ClassModel model); 15 | } 16 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Frameworks/IMockingFramework.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Frameworks 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.CodeAnalysis.CSharp.Syntax; 5 | using SentryOne.UnitTestGenerator.Core.Models; 6 | using SentryOne.UnitTestGenerator.Core.Options; 7 | 8 | public interface IMockingFramework 9 | { 10 | IEnumerable GetUsings(); 11 | 12 | ExpressionSyntax MockInterface(TypeSyntax interfaceName); 13 | 14 | IEnumerable ReferencedNugetPackages(IVersioningOptions options); 15 | } 16 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/ExtensionMethod.txt: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Collections; 9 | using System.Collections.Generic; 10 | 11 | namespace WindowsFormsApp1 12 | { 13 | public static class Form1 14 | { 15 | public static string ToOther(this string source) 16 | { 17 | return source; 18 | } 19 | 20 | public static T ToOther(this List source) 21 | { 22 | return source.FirstOrDefault(); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Options/IGenerationOptions.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Options 2 | { 3 | public interface IGenerationOptions 4 | { 5 | TestFrameworkTypes FrameworkType { get; } 6 | 7 | MockingFrameworkType MockingFrameworkType { get; } 8 | 9 | bool CreateProjectAutomatically { get; } 10 | 11 | bool AddReferencesAutomatically { get; } 12 | 13 | bool AllowGenerationWithoutTargetProject { get; } 14 | 15 | string TestProjectNaming { get; } 16 | 17 | string TestFileNaming { get; } 18 | 19 | string TestTypeNaming { get; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Tests/SentryOne.UnitTestGenerator.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/AsyncMethod.txt: -------------------------------------------------------------------------------- 1 | namespace TestNamespace.SubNameSpace 2 | { 3 | public class TestClass 4 | { 5 | public System.Threading.Tasks.Task ThisIsAnAsyncMethod(string methodName, int methodValue) 6 | { 7 | System.Console.WriteLine("Testing this"); 8 | return System.Threading.Tasks.Task.CompletedTask; 9 | } 10 | 11 | public System.Threading.Tasks.Task ThisIsAnAsyncMethodWithReturnType(string methodName, int methodValue) 12 | { 13 | System.Console.WriteLine("Testing this"); 14 | return System.Threading.Tasks.Task.FromResult(0); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ValueGeneration/IValueGenerationStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.ValueGeneration 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | 8 | public interface IValueGenerationStrategy 9 | { 10 | IEnumerable SupportedTypeNames { get; } 11 | 12 | ExpressionSyntax CreateValueExpression(ITypeSymbol symbol, SemanticModel model, HashSet visitedTypes, IFrameworkSet frameworkSet); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /publishManifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/vsix-publish", 3 | "categories": [ "testing", "coding" ], 4 | "identity": { 5 | "internalName": "SentryOneUnitTestGenerator", 6 | "tags": [ "C#", "dependency injection", "FakeItEasy", "Moq", "MSTest", "NSUbstitue", "NUnit","Rhino Mocks", "unit testing", "xunit" ] 7 | }, 8 | "overview": "README.md", 9 | "priceCategory": "free", 10 | "publisher": "sentryone", 11 | "private": false, 12 | "qna": true, 13 | "repo": "https://github.com/sentryone/unittestgenerator" 14 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/GenerationResult.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System.Collections.Generic; 4 | using SentryOne.UnitTestGenerator.Core.Assets; 5 | 6 | public class GenerationResult 7 | { 8 | public GenerationResult(string fileContent) 9 | { 10 | FileContent = fileContent; 11 | } 12 | 13 | public string FileContent { get; } 14 | 15 | public IList RequiredAssets { get; } = new List(); 16 | 17 | public IList AssemblyReferences { get; } = new List(); 18 | } 19 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/IOperatorModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.CodeAnalysis.CSharp; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | 8 | public interface IOperatorModel : ITestableModel 9 | { 10 | string OperatorText { get; } 11 | 12 | IList Parameters { get; } 13 | 14 | ExpressionSyntax Invoke(ClassModel owner, bool suppressAwait, IFrameworkSet frameworkSet, params CSharpSyntaxNode[] arguments); 15 | } 16 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Options/IVersioningOptions.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Options 2 | { 3 | public interface IVersioningOptions 4 | { 5 | string NUnit2NugetPackageVersion { get; } 6 | 7 | string NUnit3NugetPackageVersion { get; } 8 | 9 | string XUnitNugetPackageVersion { get; } 10 | 11 | string MsTestNugetPackageVersion { get; } 12 | 13 | string FakeItEasyNugetPackageVersion { get; } 14 | 15 | string MoqNugetPackageVersion { get; } 16 | 17 | string NSubstituteNugetPackageVersion { get; } 18 | 19 | string RhinoMocksNugetPackageVersion { get; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/ChainedClassesTestFile.txt: -------------------------------------------------------------------------------- 1 | 2 | using System.Drawing; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Forms; 7 | using System.Data.SqlClient; 8 | 9 | namespace TestApp1 10 | { 11 | public class C1 12 | { 13 | public C1(C2 other) 14 | { 15 | 16 | } 17 | } 18 | public class C2 19 | { 20 | public C2(C3 other) 21 | { 22 | 23 | } 24 | } 25 | public class C3 26 | { 27 | public C3(SqlBulkCopy other) 28 | { 29 | 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.ruleset: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/AbstractSelfReferencingClass.txt: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace BasicProject 8 | { 9 | public abstract class AbsTest 10 | { 11 | protected static string GetString() 12 | { 13 | return "string"; 14 | } 15 | 16 | public AbsTest(IEnumerable childSelectors) 17 | { 18 | } 19 | } 20 | 21 | public class AbsTestThing : AbsTest 22 | { 23 | public AbsTestThing() : base(Enumerable.Empty()) 24 | { 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/IMethodModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.CodeAnalysis.CSharp; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | 8 | public interface IMethodModel : ITestableModel 9 | { 10 | bool IsAsync { get; } 11 | 12 | bool IsVoid { get; } 13 | 14 | IList Parameters { get; } 15 | 16 | ExpressionSyntax Invoke(ClassModel owner, bool suppressAwait, IFrameworkSet frameworkSet, params CSharpSyntaxNode[] arguments); 17 | } 18 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/MappingMethod.txt: -------------------------------------------------------------------------------- 1 | namespace TestApp1 2 | { 3 | public class InputClass 4 | { 5 | public string SomeProperty { get; } 6 | public string SomeOtherProperty { get; set; } 7 | public string WriteOnlyProperty { set { } } 8 | } 9 | 10 | public class OutputClass 11 | { 12 | public string SomeProperty { get; set; } 13 | public string SomeOtherProperty { get; set; } 14 | public string WriteOnlyProperty { get; set; } 15 | } 16 | public class C3 17 | { 18 | public OutputClass Map(InputClass inputClass) 19 | { 20 | return null; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/NugetPackageReference.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System; 4 | 5 | public class NugetPackageReference : INugetPackageReference 6 | { 7 | public NugetPackageReference(string name, string version) 8 | { 9 | if (string.IsNullOrWhiteSpace(name)) 10 | { 11 | throw new ArgumentNullException(nameof(name)); 12 | } 13 | 14 | Name = name; 15 | Version = string.IsNullOrWhiteSpace(version) ? null : version; 16 | } 17 | 18 | public string Name { get; } 19 | 20 | public string Version { get; } 21 | } 22 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/RefAndOutParameters.txt: -------------------------------------------------------------------------------- 1 | namespace TestNamespace.SubNameSpace 2 | { 3 | public class TestClass 4 | { 5 | public void RefParamMethodString(string stringProp, ref string refParam) 6 | { 7 | 8 | } 9 | 10 | public void OutParamMethodString(string stringProp, out string outParam) 11 | { 12 | outParam = ""; 13 | } 14 | 15 | public void RefParamMethodClass(string stringProp, ref TestClass refParam) 16 | { 17 | 18 | } 19 | 20 | public void OutParamMethodClass(string stringProp, out TestClass outParam) 21 | { 22 | outParam = null; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/Singleton.txt: -------------------------------------------------------------------------------- 1 | namespace WindowsFormsApp1 2 | { 3 | using System; 4 | 5 | public class TenantSharedTableProvider 6 | { 7 | static TenantSharedTableProvider() 8 | { 9 | Instance = new TenantSharedTableProvider(); 10 | } 11 | 12 | private TenantSharedTableProvider() 13 | { 14 | } 15 | 16 | public static TenantSharedTableProvider Instance { get; } 17 | 18 | public bool IsShared => true; 19 | 20 | public string GetTableName(string baseName, long tenantId) 21 | { 22 | if (string.IsNullOrWhiteSpace(baseName)) 23 | { 24 | throw new ArgumentNullException(nameof(baseName)); 25 | } 26 | 27 | return baseName; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/IEnumerableClass.txt: -------------------------------------------------------------------------------- 1 | 2 | using System.Drawing; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Collections; 8 | using System.Collections.Generic; 9 | 10 | namespace WindowsFormsApp1 11 | { 12 | public class Form1 : IEnumerable 13 | { 14 | public Form1() 15 | { 16 | 17 | } 18 | 19 | public IEnumerator GetEnumerator() 20 | { 21 | return Enumerable.Empty().GetEnumerator(); 22 | } 23 | 24 | IEnumerator IEnumerable.GetEnumerator() 25 | { 26 | return GetEnumerator(); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Options/UnitTestGeneratorOptions.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Options 2 | { 3 | using System; 4 | 5 | public class UnitTestGeneratorOptions : IUnitTestGeneratorOptions 6 | { 7 | public UnitTestGeneratorOptions(IGenerationOptions generationOptions, IVersioningOptions versioningOptions) 8 | { 9 | GenerationOptions = generationOptions ?? throw new ArgumentNullException(nameof(generationOptions)); 10 | VersioningOptions = versioningOptions ?? throw new ArgumentNullException(nameof(versioningOptions)); 11 | } 12 | 13 | public IGenerationOptions GenerationOptions { get; } 14 | 15 | public IVersioningOptions VersioningOptions { get; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/ParameterModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | 7 | public class ParameterModel : TestableModel 8 | { 9 | public ParameterModel(string name, ParameterSyntax node, string type, TypeInfo typeInfo) 10 | : base(name, node) 11 | { 12 | if (string.IsNullOrWhiteSpace(type)) 13 | { 14 | throw new ArgumentNullException(nameof(type)); 15 | } 16 | 17 | Type = type; 18 | 19 | TypeInfo = typeInfo; 20 | } 21 | 22 | public string Type { get; } 23 | 24 | public TypeInfo TypeInfo { get; } 25 | } 26 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/ConstructorModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | 7 | public class ConstructorModel : TestableModel, IConstructorModel 8 | { 9 | public ConstructorModel(string name, IList parameters, ConstructorDeclarationSyntax node) 10 | : base(name, node) 11 | { 12 | if (string.IsNullOrEmpty(name)) 13 | { 14 | throw new ArgumentNullException(nameof(name)); 15 | } 16 | 17 | Parameters = parameters ?? new List(); 18 | } 19 | 20 | public IList Parameters { get; } 21 | } 22 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/IUnitTestGeneratorPackage.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | using Microsoft.VisualStudio.LanguageServices; 6 | using Microsoft.VisualStudio.Threading; 7 | using NuGet.VisualStudio; 8 | using SentryOne.UnitTestGenerator.Core.Options; 9 | 10 | public interface IUnitTestGeneratorPackage : IServiceProvider 11 | { 12 | JoinableTaskFactory JoinableTaskFactory { get; } 13 | 14 | IUnitTestGeneratorOptions Options { get; } 15 | 16 | IVsPackageInstaller PackageInstaller { get; } 17 | 18 | IVsPackageInstallerServices PackageInstallerServices { get; } 19 | 20 | VisualStudioWorkspace Workspace { get; } 21 | 22 | Task GetServiceAsync(Type serviceType); 23 | } 24 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Helpers/StandardReferenceHelper.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Helpers 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using SentryOne.UnitTestGenerator.Core.Frameworks; 6 | using SentryOne.UnitTestGenerator.Core.Models; 7 | using SentryOne.UnitTestGenerator.Core.Options; 8 | 9 | public static class StandardReferenceHelper 10 | { 11 | public static IList GetReferencedNugetPackages(IUnitTestGeneratorOptions options) 12 | { 13 | var set = FrameworkSetFactory.Create(options); 14 | 15 | return set.TestFramework.ReferencedNugetPackages(options.VersioningOptions).Concat(set.MockingFramework.ReferencedNugetPackages(options.VersioningOptions)).ToList(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/VersionOptions.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Specs 2 | { 3 | using SentryOne.UnitTestGenerator.Core.Options; 4 | 5 | public class VersionOptions : IVersioningOptions 6 | { 7 | public string NUnit2NugetPackageVersion { get; } = string.Empty; 8 | public string NUnit3NugetPackageVersion { get; } = string.Empty; 9 | public string XUnitNugetPackageVersion { get; } = string.Empty; 10 | public string MsTestNugetPackageVersion { get; } = string.Empty; 11 | public string FakeItEasyNugetPackageVersion { get; } = string.Empty; 12 | public string MoqNugetPackageVersion { get; } = string.Empty; 13 | public string NSubstituteNugetPackageVersion { get; } = string.Empty; 14 | public string RhinoMocksNugetPackageVersion { get; } = string.Empty; 15 | } 16 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Resources; 4 | using System.Runtime.InteropServices; 5 | 6 | [assembly: AssemblyTitle("SentryOne.UnitTestGenerator")] 7 | [assembly: AssemblyDescription("SentryOne Unit Test Generator generates unit test boiler plate from existing code")] 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("SentryOne")] 10 | [assembly: AssemblyProduct("SentryOne.UnitTestGenerator")] 11 | [assembly: AssemblyCopyright("Coipyright © 2019 SentryOne")] 12 | [assembly: AssemblyTrademark("")] 13 | [assembly: AssemblyCulture("")] 14 | [assembly: NeutralResourcesLanguage("en-us")] 15 | 16 | [assembly: ComVisible(false)] 17 | [assembly: CLSCompliant(false)] 18 | 19 | [assembly: AssemblyVersion("1.0.0.0")] 20 | [assembly: AssemblyFileVersion("1.0.0.0")] 21 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/BaseContext.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Specs 2 | { 3 | using Microsoft.CodeAnalysis; 4 | using Microsoft.CodeAnalysis.CSharp.Syntax; 5 | using SentryOne.UnitTestGenerator.Core.Models; 6 | using SentryOne.UnitTestGenerator.Core.Options; 7 | 8 | public class BaseContext 9 | { 10 | public BaseContext() 11 | { 12 | TargetFramework = TestFrameworkTypes.NUnit3; 13 | MockFramework = MockingFrameworkType.NSubstitute; 14 | } 15 | 16 | public ClassModel ClassModel { get; set; } 17 | public SemanticModel SemanticModel { get; set; } 18 | public MethodDeclarationSyntax CurrentMethod { get; set; } 19 | public TestFrameworkTypes TargetFramework { get; set; } 20 | public MockingFrameworkType MockFramework { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Helper/AggregateLogger.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Helper 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.VisualStudio.Shell; 5 | using SentryOne.UnitTestGenerator.Core.Helpers; 6 | 7 | public class AggregateLogger : IMessageLogger 8 | { 9 | private readonly List _loggers = new List { new StatusBarMessageLogger(), new OutputWindowMessageLogger() }; 10 | 11 | public void Initialize() 12 | { 13 | ThreadHelper.ThrowIfNotOnUIThread(); 14 | 15 | _loggers.ForEach(x => x.Initialize()); 16 | } 17 | 18 | public void LogMessage(string message) 19 | { 20 | ThreadHelper.ThrowIfNotOnUIThread(); 21 | 22 | _loggers.ForEach(x => x.LogMessage(message)); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/PocoInitialization.txt: -------------------------------------------------------------------------------- 1 | namespace TestNamespace.SubNameSpace 2 | { 3 | using System; 4 | 5 | public class SomePoco 6 | { 7 | public int ThisIsAProperty {get;set;} 8 | public string ThisIsAProperty2 {get;set;} 9 | public Guid ThisIsAProperty3 {get;set;} 10 | public Guid? ThisIsAProperty4 {get;set;} 11 | public int ThisIsAProperty5 {get;private set;} 12 | private int ThisIsAProperty6 {get;set;} 13 | public Guid ThisIsAProperty7 {get;set;} 14 | public Guid ThisIsAProperty8 {get;set;} 15 | public Guid ThisIsAProperty9 {get;set;} 16 | } 17 | 18 | public class TestClass 19 | { 20 | SomePoco _poco; 21 | 22 | public TestClass(SomePoco poco) 23 | { 24 | _poco = poco; 25 | } 26 | 27 | public SomePoco Poco => _poco; 28 | } 29 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Frameworks/Test/XUnitTestFrameworkTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Frameworks.Test 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks.Test; 7 | using SentryOne.UnitTestGenerator.Core.Options; 8 | 9 | [TestFixture] 10 | public class XUnitTestFrameworkTests 11 | { 12 | private XUnitTestFramework _testClass; 13 | 14 | [SetUp] 15 | public void SetUp() 16 | { 17 | _testClass = new XUnitTestFramework(); 18 | } 19 | 20 | [Test] 21 | public void CannotCallReferencedNugetPackagesWithNullOptions() 22 | { 23 | Assert.Throws(() => _testClass.ReferencedNugetPackages(default(IVersioningOptions)).Consume()); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Frameworks/Test/MsTestTestFrameworkTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Frameworks.Test 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks.Test; 7 | using SentryOne.UnitTestGenerator.Core.Options; 8 | 9 | [TestFixture] 10 | public class MsTestTestFrameworkTests 11 | { 12 | private MsTestTestFramework _testClass; 13 | 14 | [SetUp] 15 | public void SetUp() 16 | { 17 | _testClass = new MsTestTestFramework(); 18 | } 19 | 20 | [Test] 21 | public void CannotCallReferencedNugetPackagesWithNullOptions() 22 | { 23 | Assert.Throws(() => _testClass.ReferencedNugetPackages(default(IVersioningOptions)).Consume()); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Frameworks/Test/NUnit2TestFrameworkTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Frameworks.Test 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks.Test; 7 | using SentryOne.UnitTestGenerator.Core.Options; 8 | 9 | [TestFixture] 10 | public class NUnit2TestFrameworkTests 11 | { 12 | private NUnit2TestFramework _testClass; 13 | 14 | [SetUp] 15 | public void SetUp() 16 | { 17 | _testClass = new NUnit2TestFramework(); 18 | } 19 | 20 | [Test] 21 | public void CannotCallReferencedNugetPackagesWithNullOptions() 22 | { 23 | Assert.Throws(() => _testClass.ReferencedNugetPackages(default(IVersioningOptions)).Consume()); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Frameworks/Test/NUnit3TestFrameworkTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Frameworks.Test 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks.Test; 7 | using SentryOne.UnitTestGenerator.Core.Options; 8 | 9 | [TestFixture] 10 | public class NUnit3TestFrameworkTests 11 | { 12 | private NUnit3TestFramework _testClass; 13 | 14 | [SetUp] 15 | public void SetUp() 16 | { 17 | _testClass = new NUnit3TestFramework(); 18 | } 19 | 20 | [Test] 21 | public void CannotCallReferencedNugetPackagesWithNullOptions() 22 | { 23 | Assert.Throws(() => _testClass.ReferencedNugetPackages(default(IVersioningOptions)).Consume()); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/AsyncMappingMethod.txt: -------------------------------------------------------------------------------- 1 | namespace TestApp1 2 | { 3 | using System.Threading.Tasks; 4 | 5 | public class InputClass 6 | { 7 | public int ID { get; } 8 | public string SomeProperty { get; } 9 | public string SomeOtherProperty { get; set; } 10 | public string WriteOnlyProperty { set { } } 11 | } 12 | 13 | public class OutputClass 14 | { 15 | public string SomeProperty { get; set; } 16 | public string SomeOtherProperty { get; set; } 17 | public string WriteOnlyProperty { get; set; } 18 | } 19 | public class C3 20 | { 21 | public async Task ShouldntMap(InputClass inputClass) 22 | { 23 | return; 24 | } 25 | 26 | public async Task MapActually(InputClass inputClass) 27 | { 28 | return null; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/IndexerTestFile.txt: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Collections; 9 | using System.Collections.Generic; 10 | 11 | namespace WindowsFormsApp1 12 | { 13 | public class Form1 14 | { 15 | public string this[string cookieName, Guid cookieValue, DateTime cookieExpirationTime] 16 | { 17 | set 18 | { 19 | } 20 | } 21 | 22 | public string this[string cookieName] 23 | { 24 | get { 25 | return "hello"; 26 | } 27 | } 28 | 29 | public string this[string cookieName, int cookieId] 30 | { 31 | get { 32 | return "hello"; 33 | } 34 | set { 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Models/OperatorModelTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Models 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | using NSubstitute; 9 | using NUnit.Framework; 10 | using SentryOne.UnitTestGenerator.Core.Frameworks; 11 | using SentryOne.UnitTestGenerator.Core.Models; 12 | 13 | [TestFixture] 14 | public class OperatorModelTests 15 | { 16 | [SetUp] 17 | public void SetUp() 18 | { 19 | } 20 | 21 | [Test] 22 | public void CannotConstructWithNullNode() 23 | { 24 | Assert.Throws(() => new OperatorModel("TestValue526920974", new List(), default(OperatorDeclarationSyntax), ClassModelProvider.Instance.SemanticModel)); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Options/EditorConfigFieldMapper.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Options 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | public static class EditorConfigFieldMapper 7 | { 8 | public static void ApplyTo(this Dictionary fileConfiguration, T target) 9 | where T : class 10 | { 11 | if (fileConfiguration == null) 12 | { 13 | throw new ArgumentNullException(nameof(fileConfiguration)); 14 | } 15 | 16 | if (target == null) 17 | { 18 | throw new ArgumentNullException(nameof(target)); 19 | } 20 | 21 | var mutator = new TypeMemberMutator(typeof(T)); 22 | foreach (var property in fileConfiguration) 23 | { 24 | mutator.Set(target, property.Key, property.Value); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/notes.md: -------------------------------------------------------------------------------- 1 | 1. Change the input class to support both string and file / resource input 2 | 2. Use a SpecFlow transform to convert a text strategy name to the actual strategy object 3 | Not sure I can do this, as I need a frameworkset to create and return the strategy. This might work via dependency injection for the context 4 | 5 | 3. Add full generation option support 6 | - Added test and mock framework support 7 | - still plenty of other options to add if we need them 8 | - Still need to look at the relationship between FrameworkSet and GenerationOptions - feels like we have to 9 | framework and mock types twice - why? And what happens if they are out of sync? 10 | 11 | 4. Get the actual generated class as a result, instead of just the methods from the strategy Create call 12 | 5. Add framework steps for checking the "shape" of the generated class 13 | = Added a basic method count assert - should be able to add additional ones as needed. 14 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/PropertyGenerator/SingleConstructorInitializedPropertyGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: SingleConstructorInitializedPropertyGeneration 2 | I am checking the Single Constructor Initialized Property Generation strategy 3 | 4 | 5 | Scenario: Single Constructor Initialized Property Generation 6 | Given I have a class defined as 7 | """ 8 | public class TestClass 9 | { 10 | string _str1; 11 | 12 | public TestClass(string str1) 13 | { 14 | _str1 = str1; 15 | } 16 | 17 | public string Str1 => _str1; 18 | } 19 | """ 20 | And I set my test framework to 'NUnit3' 21 | And I set my mock framework to 'FakeItEasy' 22 | When I generate tests for the property using the strategy 'SingleConstructorInitializedPropertyGenerationStrategy' 23 | Then I expect a method called 'Str1IsInitializedCorrectly' 24 | And I expect it to have the attribute 'Test' 25 | And I expect it to contain 1 statements called 'Assert.That(_testClass.Str1, Is.EqualTo(_str1));' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/InterfaceModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Microsoft.CodeAnalysis; 7 | using SentryOne.UnitTestGenerator.Core.Helpers; 8 | 9 | public class InterfaceModel : IInterfaceModel 10 | { 11 | public InterfaceModel(INamedTypeSymbol interfaceType) 12 | { 13 | InterfaceType = interfaceType ?? throw new ArgumentNullException(nameof(interfaceType)); 14 | InterfaceName = interfaceType.ToFullName(); 15 | GenericTypes = new List(interfaceType.TypeArguments); 16 | IsGeneric = GenericTypes.Count > 0; 17 | } 18 | 19 | public string InterfaceName { get; } 20 | 21 | public bool IsGeneric { get; } 22 | 23 | public IList GenericTypes { get; } 24 | 25 | public INamedTypeSymbol InterfaceType { get; } 26 | } 27 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/GenerationOptions.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Specs 2 | { 3 | using SentryOne.UnitTestGenerator.Core.Options; 4 | 5 | public class GenerationOptions : IGenerationOptions 6 | { 7 | public GenerationOptions(TestFrameworkTypes testFramework, MockingFrameworkType mockFramework) 8 | { 9 | FrameworkType = testFramework; 10 | MockingFrameworkType = mockFramework; 11 | } 12 | 13 | public TestFrameworkTypes FrameworkType { get; } 14 | public MockingFrameworkType MockingFrameworkType { get; } 15 | public bool CreateProjectAutomatically { get; } = true; 16 | public bool AddReferencesAutomatically { get; } = true; 17 | public bool AllowGenerationWithoutTargetProject { get; } = true; 18 | public string TestProjectNaming { get; } = "{0}.Tests"; 19 | public string TestFileNaming { get; } = "{0}Tests"; 20 | public string TestTypeNaming { get; } = "{0}Tests"; 21 | } 22 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/InterfaceImplementationTestFile.txt: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace AssemblyCore 4 | { 5 | public interface IDummyService { } 6 | 7 | public class InterfaceImplementation : IDummyService 8 | { 9 | public Task AsyncMethod() 10 | { 11 | return Task.FromResult("str"); 12 | } 13 | 14 | public async Task AsyncReturIntAsync() 15 | { 16 | await Task.Delay(500); 17 | return 300; 18 | } 19 | 20 | public async Task AsyncReturnStringAsync() 21 | { 22 | await Task.Delay(500); 23 | return "Sample String"; 24 | } 25 | 26 | public async Task AsyncReturnTaskAsync() 27 | { 28 | await Task.Delay(500); 29 | } 30 | 31 | public void NoReturnMethod() 32 | { 33 | 34 | } 35 | 36 | public int ReturnMetod() 37 | { 38 | return 300; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/AbstractChainTextFile.txt: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows; 3 | 4 | namespace TestNamespace { 5 | 6 | public abstract class TestClass1 7 | { 8 | protected TestClass1() 9 | { 10 | 11 | } 12 | 13 | public abstract int SomeMethodShouldNot(); 14 | 15 | public abstract int SomeMethodMaybe(int i); 16 | 17 | public abstract int SomeMethodMaybe(int i, int j); 18 | 19 | public abstract int SomeMethodMaybe(int i); 20 | 21 | public abstract int SomeMethodMaybe(int i, int j); 22 | 23 | } 24 | 25 | public abstract class TestClass2 : TestClass1 26 | { 27 | protected TestClass2() 28 | { 29 | 30 | } 31 | 32 | public override int SomeMethodShouldNot() { return 1; } 33 | 34 | public override int SomeMethodMaybe(int i, int j) { return 1; } 35 | 36 | public abstract int SomeMethodShould(); 37 | } 38 | 39 | public abstract class TestClass3 : TestClass2 40 | { 41 | protected TestClass3() 42 | { 43 | 44 | } 45 | 46 | public abstract int SomeMethodShould2(); 47 | } 48 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/IComparableTestFile.txt: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AssemblyCore 4 | { 5 | public class TestComparableGeneric : IComparable, IComparable, IComparable 6 | { 7 | public TestComparableGeneric(int value) 8 | { 9 | Value = value; 10 | } 11 | 12 | public int Value { get; } 13 | 14 | public int CompareTo(TestComparableGeneric obj) 15 | { 16 | if (obj == null) 17 | { 18 | throw new ArgumentNullException(); 19 | } 20 | 21 | return Value.CompareTo(obj.Value); 22 | } 23 | 24 | public int CompareTo(int value) 25 | { 26 | return Value.CompareTo(value); 27 | } 28 | 29 | public int CompareTo(object obj) 30 | { 31 | if (obj is null) 32 | { 33 | throw new ArgumentNullException(nameof(obj)); 34 | } 35 | 36 | return Value.CompareTo(obj); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/OperatorGeneration/OperatorGenerationStrategyFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.OperatorGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using SentryOne.UnitTestGenerator.Core.Frameworks; 6 | using SentryOne.UnitTestGenerator.Core.Models; 7 | 8 | public class OperatorGenerationStrategyFactory : ItemGenerationStrategyFactory 9 | { 10 | private readonly IFrameworkSet _frameworkSet; 11 | 12 | public OperatorGenerationStrategyFactory(IFrameworkSet frameworkSet) 13 | { 14 | _frameworkSet = frameworkSet ?? throw new ArgumentNullException(nameof(frameworkSet)); 15 | } 16 | 17 | protected override IEnumerable> Strategies => 18 | new IGenerationStrategy[] 19 | { 20 | new CanCallOperatorGenerationStrategy(_frameworkSet), 21 | new NullParameterCheckOperatorGenerationStrategy(_frameworkSet), 22 | }; 23 | } 24 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/AbstractProperty.txt: -------------------------------------------------------------------------------- 1 | namespace SentryOne.Document.Web.Services.Workflow.BackgroundTaskExecutors.AzureFunctions 2 | { 3 | using System; 4 | 5 | public abstract class AzureFunctionsBackgroundTaskExecutor 6 | { 7 | public AzureFunctionsBackgroundTaskExecutor() 8 | { 9 | } 10 | 11 | public abstract string SupportedStage { get; } 12 | 13 | public abstract string SupportedStage2 { get; } 14 | 15 | protected abstract string PropectedProperty { get; } 16 | 17 | public abstract string CreateMessage(string item, long tenantId); 18 | 19 | protected abstract string CreateMessage2(string item, long tenantId); 20 | } 21 | 22 | public abstract class AzureFunctionsBackgroundTaskExecutor2 : AzureFunctionsBackgroundTaskExecutor 23 | { 24 | public AzureFunctionsBackgroundTaskExecutor2() 25 | { 26 | } 27 | 28 | public override string SupportedStage => "hello"; 29 | 30 | public override string CreateMessage(string item, long tenantId) { return "hello"; } 31 | } 32 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ItemGenerationStrategyFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using SentryOne.UnitTestGenerator.Core.Models; 7 | 8 | public abstract class ItemGenerationStrategyFactory 9 | { 10 | protected abstract IEnumerable> Strategies { get; } 11 | 12 | public IEnumerable CreateFor(T property, ClassModel model) 13 | { 14 | var strategies = Strategies.Where(x => x.CanHandle(property, model)).OrderByDescending(x => x.Priority); 15 | foreach (var strategy in strategies) 16 | { 17 | foreach (var method in strategy.Create(property, model)) 18 | { 19 | yield return method; 20 | } 21 | 22 | if (strategy.IsExclusive) 23 | { 24 | break; 25 | } 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/IndexerGeneration/IndexerGenerationStrategyFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.IndexerGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using SentryOne.UnitTestGenerator.Core.Frameworks; 6 | using SentryOne.UnitTestGenerator.Core.Models; 7 | 8 | public class IndexerGenerationStrategyFactory : ItemGenerationStrategyFactory 9 | { 10 | private readonly IFrameworkSet _frameworkSet; 11 | 12 | public IndexerGenerationStrategyFactory(IFrameworkSet frameworkSet) 13 | { 14 | _frameworkSet = frameworkSet ?? throw new ArgumentNullException(nameof(frameworkSet)); 15 | } 16 | 17 | protected override IEnumerable> Strategies => new IGenerationStrategy[] 18 | { 19 | new ReadOnlyIndexerGenerationStrategy(_frameworkSet), 20 | new ReadWriteIndexerGenerationStrategy(_frameworkSet), 21 | new WriteOnlyIndexerGenerationStrategy(_frameworkSet), 22 | }; 23 | } 24 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/OverloadGenericDisambiguation.txt: -------------------------------------------------------------------------------- 1 | namespace TestNamespace.SubNameSpace 2 | { 3 | public static class TestClass 4 | { 5 | public static void ThisIsAMethod(string methodName) 6 | { 7 | System.Console.WriteLine("Testing this"); 8 | } 9 | 10 | public static void ThisIsAMethod(string methodName) 11 | { 12 | System.Console.WriteLine("Testing this"); 13 | } 14 | 15 | public static void ThisIsAMethod(string methodName, int methodValue) 16 | { 17 | System.Console.WriteLine("Testing this"); 18 | } 19 | 20 | public static void ThisIsAMethod(string methodName, int methodValue) 21 | { 22 | System.Console.WriteLine("Testing this"); 23 | } 24 | 25 | public static void ThisIsAMethod(int methodName, int methodValue) 26 | { 27 | System.Console.WriteLine("Testing this"); 28 | } 29 | 30 | public static void ThisIsAMethod(string methodName, int methodValue) 31 | { 32 | System.Console.WriteLine("Testing this"); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/SampleClassTestFile.txt: -------------------------------------------------------------------------------- 1 | namespace TestNamespace.SubNameSpace 2 | { 3 | 4 | public interface ITest 5 | { 6 | int ThisIsAProperty {get;set;} 7 | } 8 | 9 | public class TestClass 10 | { 11 | public TestClass(string stringProp, ITest iTest) 12 | { 13 | 14 | } 15 | 16 | public TestClass(int? nullableIntProp, ITest iTest) 17 | { 18 | 19 | } 20 | 21 | public TestClass(int thisIsAProperty, ITest iTest) 22 | { 23 | 24 | } 25 | 26 | public void ThisIsAMethod(string methodName, int methodValue) 27 | { 28 | System.Console.WriteLine("Testing this"); 29 | } 30 | 31 | public string WillReturnAString() 32 | { 33 | return "Hello"; 34 | } 35 | 36 | private string _thisIsAString = string.Empty; 37 | public string ThisIsAWriteOnlyString { set { _thisIsAString = value; }} 38 | 39 | public int ThisIsAProperty { get;set;} 40 | 41 | public ITest GetITest { get; } 42 | 43 | public TestClass ThisClass {get;set;} 44 | } 45 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Helpers/SymbolExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Helpers 2 | { 3 | using System.Linq; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using NUnit.Framework; 7 | using SentryOne.UnitTestGenerator.Core.Helpers; 8 | 9 | [TestFixture] 10 | public static class SymbolExtensionsTests 11 | { 12 | [Test] 13 | public static void CanCallIsAwaitableNonDynamic() 14 | { 15 | var symbols = TestSemanticModelFactory.Class.DescendantNodes().OfType().Select(node => TestSemanticModelFactory.Model.GetDeclaredSymbol(node)).OfType().ToList(); 16 | Assert.That(symbols.First(x => x.Name == "Method").IsAwaitableNonDynamic(), Is.False); 17 | Assert.That(symbols.First(x => x.Name == "AsyncMethod").IsAwaitableNonDynamic(), Is.True); 18 | } 19 | 20 | [Test] 21 | public static void CanCallIsAwaitableNonDynamicWithNullSymbol() 22 | { 23 | Assert.That(() => default(IMethodSymbol).IsAwaitableNonDynamic(), Is.False); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Frameworks/Test/NUnitTestFrameworkTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Frameworks.Test 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using NUnit.Framework; 7 | using SentryOne.UnitTestGenerator.Core.Frameworks.Test; 8 | using SentryOne.UnitTestGenerator.Core.Models; 9 | using SentryOne.UnitTestGenerator.Core.Options; 10 | 11 | [TestFixture] 12 | public class NUnitTestFrameworkTests 13 | { 14 | private class TestNUnitTestFramework : NUnitTestFramework 15 | { 16 | public override IEnumerable ReferencedNugetPackages(IVersioningOptions options) 17 | { 18 | return default(IEnumerable); 19 | } 20 | 21 | public override AttributeSyntax SingleThreadedApartmentAttribute { get; } 22 | } 23 | 24 | private TestNUnitTestFramework _testClass; 25 | 26 | [SetUp] 27 | public void SetUp() 28 | { 29 | _testClass = new TestNUnitTestFramework(); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ValueGeneration/BrushFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.ValueGeneration 2 | { 3 | using System; 4 | using Microsoft.CodeAnalysis.CSharp; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | 7 | public static class BrushFactory 8 | { 9 | private static readonly string[] ColorsArray = { "Red", "Orange", "Yellow", "Green", "Blue", "Purple", "Black", "Brown", "Cyan", "Magenta", "Gold", "White", "Teal", "Pink", "Lime" }; 10 | 11 | public static Func Brushes => () => RandomBrush("Brushes"); 12 | 13 | public static Func Color => () => RandomBrush("Color"); 14 | 15 | public static Func Colors => () => RandomBrush("Colors"); 16 | 17 | private static ExpressionSyntax RandomBrush(string typeName) 18 | { 19 | var identifier = ColorsArray[ValueGenerationStrategyFactory.Random.Next(ColorsArray.Length)]; 20 | 21 | return SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(typeName), SyntaxFactory.IdentifierName(identifier)); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/IndexerModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | 9 | public class IndexerModel : TestableModel, IIndexerModel 10 | { 11 | public IndexerModel(string name, List parameters, TypeInfo typeInfo, IndexerDeclarationSyntax node) 12 | : base(name, node) 13 | { 14 | TypeInfo = typeInfo; 15 | Parameters = parameters ?? new List(); 16 | } 17 | 18 | public bool HasGet => Node.AccessorList.Accessors.Any(x => x.IsKind(SyntaxKind.GetAccessorDeclaration) && !x.Modifiers.Any(m => m.IsKind(SyntaxKind.PrivateKeyword))); 19 | 20 | public bool HasSet => Node.AccessorList.Accessors.Any(x => x.IsKind(SyntaxKind.SetAccessorDeclaration) && !x.Modifiers.Any(m => m.IsKind(SyntaxKind.PrivateKeyword))); 21 | 22 | public IList Parameters { get; } 23 | 24 | public TypeInfo TypeInfo { get; } 25 | } 26 | } -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to the SentryOne Unit Test Generator 2 | Welcome! If you are here, we are assuming that you are interested in contributing to the SentryOne Unit Test Generator project. That's fantastic - thank you in advance for your effort! 3 | 4 | To contribute to the SentryOne Unit Test Generator, you will need to complete a Contributor License Agreement (CLA) - please see [our contributing guidelines](https://github.com/sentryone/sentryone/blob/master/contributing.md). 5 | 6 | Specifically, for the SentryOne Unit Test Generator, please follow these guidelines: 7 | 8 | * Smaller PRs that cover a single functionality enhancement are generally preferred 9 | * Please ensure that there are no Code Analysis warnings or test failures created by the code 10 | * Please add scenario tests to cover any new functionality 11 | * If adding any new options that control how tests are generated, please make sure that the defaults for those options reflect existing behavior. 12 | * Generators for third party scenarios (i.e. that require inspection of non-framework types) should not be part of the core test generator 13 | 14 | We are really excited to see what you come up with to take this project forward - so thank you again! -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/Generate.txt: -------------------------------------------------------------------------------- 1 | namespace Helpers 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | public static class Generate 8 | { 9 | public static IList Arguments(params string[] expressions) 10 | { 11 | return ArgumentList(expressions); 12 | } 13 | 14 | public static IList Arguments(IEnumerable expressions) 15 | { 16 | return ArgumentList(expressions); 17 | } 18 | 19 | private static IList ArgumentList(params string[] expressions) 20 | { 21 | return ArgumentList(expressions.AsEnumerable()); 22 | } 23 | 24 | private static IList ArgumentList(IEnumerable expressions) 25 | { 26 | var tokens = new List(); 27 | foreach (var expression in expressions) 28 | { 29 | if (tokens.Count > 0) 30 | { 31 | tokens.Add(","); 32 | } 33 | 34 | tokens.Add(expression); 35 | } 36 | 37 | return tokens; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Assets/PropertyTesterAsset.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Assets 2 | { 3 | using System; 4 | using SentryOne.UnitTestGenerator.Core.Options; 5 | 6 | public class PropertyTesterAsset : IAsset 7 | { 8 | public string AssetFileName => "PropertyTester.cs"; 9 | 10 | public string Content(string targetNamespace, TestFrameworkTypes testFrameworkTypes) 11 | { 12 | if (string.IsNullOrWhiteSpace(targetNamespace)) 13 | { 14 | throw new ArgumentNullException(nameof(targetNamespace)); 15 | } 16 | 17 | if ((testFrameworkTypes & TestFrameworkTypes.XUnit) > 0) 18 | { 19 | return AssetResources.PropertyTesterXUnit.Replace("%targetNamespace%", targetNamespace); 20 | } 21 | 22 | if ((testFrameworkTypes & (TestFrameworkTypes.NUnit2 | TestFrameworkTypes.NUnit3)) > 0) 23 | { 24 | return AssetResources.PropertyTesterNUnit.Replace("%targetNamespace%", targetNamespace); 25 | } 26 | 27 | return AssetResources.PropertyTesterMSTest.Replace("%targetNamespace%", targetNamespace); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Frameworks/FrameworkSet.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Frameworks 2 | { 3 | using System; 4 | using SentryOne.UnitTestGenerator.Core.Helpers; 5 | 6 | public class FrameworkSet : IFrameworkSet 7 | { 8 | public FrameworkSet(ITestFramework testFramework, IMockingFramework mockingFramework, IGenerationContext context, string testTypeNaming) 9 | { 10 | if (string.IsNullOrWhiteSpace(testTypeNaming)) 11 | { 12 | throw new ArgumentNullException(nameof(testTypeNaming)); 13 | } 14 | 15 | TestFramework = testFramework ?? throw new ArgumentNullException(nameof(testFramework)); 16 | MockingFramework = mockingFramework ?? throw new ArgumentNullException(nameof(mockingFramework)); 17 | Context = context ?? throw new ArgumentNullException(nameof(context)); 18 | TestTypeNaming = testTypeNaming; 19 | } 20 | 21 | public ITestFramework TestFramework { get; } 22 | 23 | public IMockingFramework MockingFramework { get; } 24 | 25 | public IGenerationContext Context { get; } 26 | 27 | public string TestTypeNaming { get; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/PropertyModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System.Linq; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | 8 | public class PropertyModel : TestableModel, IPropertyModel 9 | { 10 | public PropertyModel(string name, PropertyDeclarationSyntax node, TypeInfo typeInfo) 11 | : base(name, node) 12 | { 13 | TypeInfo = typeInfo; 14 | } 15 | 16 | public TypeInfo TypeInfo { get; } 17 | 18 | public bool HasGet => (Node.AccessorList?.Accessors != null && Node.AccessorList.Accessors.Any(x => x.IsKind(SyntaxKind.GetAccessorDeclaration) && !x.Modifiers.Any(m => m.IsKind(SyntaxKind.PrivateKeyword)))) || Node.ExpressionBody?.Expression != null; 19 | 20 | public bool HasSet => Node.AccessorList?.Accessors != null && Node.AccessorList.Accessors.Any(x => x.IsKind(SyntaxKind.SetAccessorDeclaration) && !x.Modifiers.Any(m => m.IsKind(SyntaxKind.PrivateKeyword))); 21 | 22 | public bool IsStatic => Node.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/MethodGeneration/MethodGenerationStrategyFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.MethodGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using SentryOne.UnitTestGenerator.Core.Frameworks; 6 | using SentryOne.UnitTestGenerator.Core.Models; 7 | 8 | public class MethodGenerationStrategyFactory : ItemGenerationStrategyFactory 9 | { 10 | private readonly IFrameworkSet _frameworkSet; 11 | 12 | public MethodGenerationStrategyFactory(IFrameworkSet frameworkSet) 13 | { 14 | _frameworkSet = frameworkSet ?? throw new ArgumentNullException(nameof(frameworkSet)); 15 | } 16 | 17 | protected override IEnumerable> Strategies => 18 | new IGenerationStrategy[] 19 | { 20 | new CanCallMethodGenerationStrategy(_frameworkSet), 21 | new NullParameterCheckMethodGenerationStrategy(_frameworkSet), 22 | new StringParameterCheckMethodGenerationStrategy(_frameworkSet), 23 | new MappingMethodGenerationStrategy(_frameworkSet), 24 | }; 25 | } 26 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/ValueGeneration/EnumFactoryTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.ValueGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.CodeAnalysis; 6 | using NSubstitute; 7 | using NUnit.Framework; 8 | using SentryOne.UnitTestGenerator.Core.Frameworks; 9 | using SentryOne.UnitTestGenerator.Core.Strategies.ValueGeneration; 10 | 11 | [TestFixture] 12 | public static class EnumFactoryTests 13 | { 14 | [Test] 15 | public static void CannotCallRandomWithNullTypeSymbol() 16 | { 17 | Assert.Throws(() => EnumFactory.Random(default(ITypeSymbol), ClassModelProvider.Instance.SemanticModel, new HashSet(StringComparer.OrdinalIgnoreCase), Substitute.For())); 18 | } 19 | 20 | [Test] 21 | public static void CannotCallRandomWithNullFrameworkSet() 22 | { 23 | Assert.Throws(() => EnumFactory.Random(Substitute.For(), ClassModelProvider.Instance.SemanticModel, new HashSet(StringComparer.OrdinalIgnoreCase), default(IFrameworkSet))); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/Regeneration/GenericRegeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: GenericRegeneration 2 | I am checking that regeneration does not add generic aliases that exist 3 | 4 | Scenario: Regeneration of a constructor 5 | Given I have a class defined as 6 | """ 7 | namespace TestNamespace 8 | { 9 | public class TestClass 10 | { 11 | public TestClass() 12 | { 13 | } 14 | 15 | public void Method() 16 | { 17 | } 18 | } 19 | } 20 | """ 21 | And an existing test class 22 | """ 23 | namespace TestNamespace.Tests 24 | { 25 | using T = System.String; 26 | using TestNamespace.SubNameSpace; 27 | using System; 28 | using NUnit.Framework; 29 | using NSubstitute; 30 | 31 | [TestFixture] 32 | public class TestClass_1Tests 33 | { 34 | private TestClass _testClass; 35 | 36 | [SetUp] 37 | public void SetUp() 38 | { 39 | _testClass = new TestClass(); 40 | } 41 | } 42 | } 43 | """ 44 | And I set my test framework to 'NUnit3' 45 | And I set my mock framework to 'NSubstitute' 46 | When I regenerate tests for all constructors 47 | Then I expect the method 'CanConstruct' 48 | And I expect only one generic type alias 49 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/MethodGeneration/MethodGenerationStrategyFactoryTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.MethodGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Strategies.MethodGeneration; 8 | 9 | [TestFixture] 10 | public class MethodGenerationStrategyFactoryTests 11 | { 12 | private MethodGenerationStrategyFactory _testClass; 13 | private IFrameworkSet _frameworkSet; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _frameworkSet = Substitute.For(); 19 | _testClass = new MethodGenerationStrategyFactory(_frameworkSet); 20 | } 21 | 22 | [Test] 23 | public void CanConstruct() 24 | { 25 | var instance = new MethodGenerationStrategyFactory(_frameworkSet); 26 | Assert.That(instance, Is.Not.Null); 27 | } 28 | 29 | [Test] 30 | public void CannotConstructWithNullFrameworkSet() 31 | { 32 | Assert.Throws(() => new MethodGenerationStrategyFactory(default(IFrameworkSet))); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/MethodBasedStrategyContext.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Specs 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using SentryOne.UnitTestGenerator.Core.Models; 7 | using SentryOne.UnitTestGenerator.Core.Options; 8 | 9 | public class MethodBasedStrategyContext 10 | { 11 | public MethodBasedStrategyContext(BaseContext baseContext) 12 | { 13 | BaseContext = baseContext ?? throw new ArgumentNullException(nameof(baseContext)); 14 | } 15 | 16 | public IEnumerable Result { get; set; } 17 | 18 | private BaseContext BaseContext { get; } 19 | 20 | public TestFrameworkTypes TargetFramework => BaseContext.TargetFramework; 21 | 22 | public MockingFrameworkType MockFramework => BaseContext.MockFramework; 23 | 24 | public ClassModel ClassModel => BaseContext.ClassModel; 25 | 26 | public MethodDeclarationSyntax CurrentMethod 27 | { 28 | get 29 | { 30 | return BaseContext.CurrentMethod; 31 | } 32 | set 33 | { 34 | BaseContext.CurrentMethod = value; 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/IndexerGeneration/IndexerGenerationStrategyFactoryTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.IndexerGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Strategies.IndexerGeneration; 8 | 9 | [TestFixture] 10 | public class IndexerGenerationStrategyFactoryTests 11 | { 12 | private IndexerGenerationStrategyFactory _testClass; 13 | private IFrameworkSet _frameworkSet; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _frameworkSet = Substitute.For(); 19 | _testClass = new IndexerGenerationStrategyFactory(_frameworkSet); 20 | } 21 | 22 | [Test] 23 | public void CanConstruct() 24 | { 25 | var instance = new IndexerGenerationStrategyFactory(_frameworkSet); 26 | Assert.That(instance, Is.Not.Null); 27 | } 28 | 29 | [Test] 30 | public void CannotConstructWithNullFrameworkSet() 31 | { 32 | Assert.Throws(() => new IndexerGenerationStrategyFactory(default(IFrameworkSet))); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/OperatorGeneration/OperatorGenerationStrategyFactoryTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.OperatorGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Strategies.OperatorGeneration; 8 | 9 | [TestFixture] 10 | public class OperatorGenerationStrategyFactoryTests 11 | { 12 | private OperatorGenerationStrategyFactory _testClass; 13 | private IFrameworkSet _frameworkSet; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _frameworkSet = Substitute.For(); 19 | _testClass = new OperatorGenerationStrategyFactory(_frameworkSet); 20 | } 21 | 22 | [Test] 23 | public void CanConstruct() 24 | { 25 | var instance = new OperatorGenerationStrategyFactory(_frameworkSet); 26 | Assert.That(instance, Is.Not.Null); 27 | } 28 | 29 | [Test] 30 | public void CannotConstructWithNullFrameworkSet() 31 | { 32 | Assert.Throws(() => new OperatorGenerationStrategyFactory(default(IFrameworkSet))); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/PropertyGeneration/PropertyGenerationStrategyFactoryTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.PropertyGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Strategies.PropertyGeneration; 8 | 9 | [TestFixture] 10 | public class PropertyGenerationStrategyFactoryTests 11 | { 12 | private PropertyGenerationStrategyFactory _testClass; 13 | private IFrameworkSet _frameworkSet; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _frameworkSet = Substitute.For(); 19 | _testClass = new PropertyGenerationStrategyFactory(_frameworkSet); 20 | } 21 | 22 | [Test] 23 | public void CanConstruct() 24 | { 25 | var instance = new PropertyGenerationStrategyFactory(_frameworkSet); 26 | Assert.That(instance, Is.Not.Null); 27 | } 28 | 29 | [Test] 30 | public void CannotConstructWithNullFrameworkSet() 31 | { 32 | Assert.Throws(() => new PropertyGenerationStrategyFactory(default(IFrameworkSet))); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ClassLevelGeneration/ClassLevelGenerationStrategyFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.ClassLevelGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using SentryOne.UnitTestGenerator.Core.Frameworks; 6 | using SentryOne.UnitTestGenerator.Core.Models; 7 | 8 | public class ClassLevelGenerationStrategyFactory : ItemGenerationStrategyFactory 9 | { 10 | private readonly IFrameworkSet _frameworkSet; 11 | 12 | public ClassLevelGenerationStrategyFactory(IFrameworkSet frameworkSet) 13 | { 14 | _frameworkSet = frameworkSet ?? throw new ArgumentNullException(nameof(frameworkSet)); 15 | } 16 | 17 | protected override IEnumerable> Strategies => new List> 18 | { 19 | new CanConstructNoConstructorGenerationStrategy(_frameworkSet), 20 | new CanConstructSingleConstructorGenerationStrategy(_frameworkSet), 21 | new CanConstructMultiConstructorGenerationStrategy(_frameworkSet), 22 | new NullParameterCheckConstructorGenerationStrategy(_frameworkSet), 23 | new StringParameterCheckConstructorGenerationStrategy(_frameworkSet), 24 | }; 25 | } 26 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/InterfaceGeneration/InterfaceGenerationStrategyFactoryTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.InterfaceGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Strategies.InterfaceGeneration; 8 | 9 | [TestFixture] 10 | public class InterfaceGenerationStrategyFactoryTests 11 | { 12 | private InterfaceGenerationStrategyFactory _testClass; 13 | private IFrameworkSet _frameworkSet; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _frameworkSet = Substitute.For(); 19 | _testClass = new InterfaceGenerationStrategyFactory(_frameworkSet); 20 | } 21 | 22 | [Test] 23 | public void CanConstruct() 24 | { 25 | var instance = new InterfaceGenerationStrategyFactory(_frameworkSet); 26 | Assert.That(instance, Is.Not.Null); 27 | } 28 | 29 | [Test] 30 | public void CannotConstructWithNullFrameworkSet() 31 | { 32 | Assert.Throws(() => new InterfaceGenerationStrategyFactory(default(IFrameworkSet))); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/ClassLevelGeneration/ClassLevelGenerationStrategyFactoryTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.ClassLevelGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Strategies.ClassLevelGeneration; 8 | 9 | [TestFixture] 10 | public class ClassLevelGenerationStrategyFactoryTests 11 | { 12 | private ClassLevelGenerationStrategyFactory _testClass; 13 | private IFrameworkSet _frameworkSet; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _frameworkSet = Substitute.For(); 19 | _testClass = new ClassLevelGenerationStrategyFactory(_frameworkSet); 20 | } 21 | 22 | [Test] 23 | public void CanConstruct() 24 | { 25 | var instance = new ClassLevelGenerationStrategyFactory(_frameworkSet); 26 | Assert.That(instance, Is.Not.Null); 27 | } 28 | 29 | [Test] 30 | public void CannotConstructWithNullFrameworkSet() 31 | { 32 | Assert.Throws(() => new ClassLevelGenerationStrategyFactory(default(IFrameworkSet))); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Frameworks/Test/NUnit2TestFramework.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Frameworks.Test 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using SentryOne.UnitTestGenerator.Core.Helpers; 7 | using SentryOne.UnitTestGenerator.Core.Models; 8 | using SentryOne.UnitTestGenerator.Core.Options; 9 | 10 | public class NUnit2TestFramework : NUnitTestFramework 11 | { 12 | public override AttributeSyntax SingleThreadedApartmentAttribute => Generate.Attribute("RequiresSTA"); 13 | 14 | public override IEnumerable ReferencedNugetPackages(IVersioningOptions options) 15 | { 16 | if (options == null) 17 | { 18 | throw new ArgumentNullException(nameof(options)); 19 | } 20 | 21 | // NUnit is a special case - because we want to support an older version. Hence if the version specified is 'latest' (i.e. null) we go with 2.6.4 22 | var version = options.NUnit2NugetPackageVersion; 23 | 24 | if (string.IsNullOrWhiteSpace(version)) 25 | { 26 | version = "2.6.4"; 27 | } 28 | 29 | yield return new NugetPackageReference("NUnit", version); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/ClassLevelGeneration/CanConstructSingleConstructorGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: CanConstructSingleConstructorGeneration 2 | I am checking the Can Construct Single Constructor Generation strategy 3 | 4 | 5 | Scenario: Can Construct Single Constructor Generation 6 | Given I have a class defined as 7 | """ 8 | using System.Drawing; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using System.Windows; 13 | using System.Collections; 14 | using System.Collections.Generic; 15 | 16 | namespace WindowsFormsApp1 17 | { 18 | public class Form1 : IEnumerable 19 | { 20 | public Form1() 21 | { 22 | 23 | } 24 | 25 | public IEnumerator GetEnumerator() 26 | { 27 | return Enumerable.Empty().GetEnumerator(); 28 | } 29 | 30 | IEnumerator IEnumerable.GetEnumerator() 31 | { 32 | return GetEnumerator(); 33 | } 34 | } 35 | } 36 | """ 37 | And I set my test framework to 'XUnit' 38 | And I set my mock framework to 'NSubstitute' 39 | When I generate unit tests for the class using strategy 'CanConstructSingleConstructorGenerationStrategy' 40 | Then I expect a method called 'CanConstruct' 41 | And I expect it to contain 1 statements called 'Assert.NotNull(instance);' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/InterfaceGeneration/EnumerableGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: EnumerableGeneration 2 | I am checking the Enumerable Generation strategy 3 | 4 | 5 | Scenario: Enumerable Generation 6 | Given I have a class defined as 7 | """ 8 | using System.Drawing; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using System.Windows; 13 | using System.Collections; 14 | using System.Collections.Generic; 15 | 16 | namespace WindowsFormsApp1 17 | { 18 | public class Form1 : IEnumerable 19 | { 20 | public Form1() 21 | { 22 | 23 | } 24 | 25 | public IEnumerator GetEnumerator() 26 | { 27 | return Enumerable.Empty().GetEnumerator(); 28 | } 29 | 30 | IEnumerator IEnumerable.GetEnumerator() 31 | { 32 | return GetEnumerator(); 33 | } 34 | } 35 | } 36 | """ 37 | And I set my test framework to 'NUnit3' 38 | And I set my mock framework to 'Moq' 39 | When I generate unit tests for the class using strategy 'EnumerableGenerationStrategy' 40 | Then I expect a method called 'ImplementsIEnumerable_Int32' 41 | And I expect it to contain the statement 'Assert.That(actualCount, Is.EqualTo(expectedCount));' 42 | And I expect it to contain a using statement with a 'while' token -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/PropertyGeneration/PropertyGenerationStrategyFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.PropertyGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using SentryOne.UnitTestGenerator.Core.Frameworks; 6 | using SentryOne.UnitTestGenerator.Core.Models; 7 | 8 | public class PropertyGenerationStrategyFactory : ItemGenerationStrategyFactory 9 | { 10 | private readonly IFrameworkSet _frameworkSet; 11 | 12 | public PropertyGenerationStrategyFactory(IFrameworkSet frameworkSet) 13 | { 14 | _frameworkSet = frameworkSet ?? throw new ArgumentNullException(nameof(frameworkSet)); 15 | } 16 | 17 | protected override IEnumerable> Strategies => new IGenerationStrategy[] 18 | { 19 | new NotifyPropertyChangedGenerationStrategy(_frameworkSet), 20 | new MultiConstructorInitializedPropertyGenerationStrategy(_frameworkSet), 21 | new SingleConstructorInitializedPropertyGenerationStrategy(_frameworkSet), 22 | new ReadWritePropertyGenerationStrategy(_frameworkSet), 23 | new ReadOnlyPropertyGenerationStrategy(_frameworkSet), 24 | new WriteOnlyPropertyGenerationStrategy(_frameworkSet), 25 | }; 26 | } 27 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Models/SemanticVersionTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Models 2 | { 3 | using System; 4 | using NUnit.Framework; 5 | using SentryOne.UnitTestGenerator.Core.Models; 6 | 7 | [TestFixture] 8 | public class SemanticVersionTests 9 | { 10 | [Test] 11 | public void CanCallParseAndCompare() 12 | { 13 | var version = "1.2.3-alpha.1"; 14 | var result = SemanticVersion.Parse(version); 15 | Assert.That(result.IsNewerThan(SemanticVersion.Parse("1.2.2"))); 16 | Assert.That(!result.IsNewerThan(SemanticVersion.Parse("1.2.3"))); 17 | Assert.That(!result.IsNewerThan(SemanticVersion.Parse("1.2.3-alpha.2"))); 18 | Assert.That(!result.IsNewerThan(SemanticVersion.Parse("1.2.3-beta.1"))); 19 | Assert.That(result.IsNewerThan(null)); 20 | 21 | var version2 = "1.2.3"; 22 | var result2 = SemanticVersion.Parse(version2); 23 | Assert.That(result2.IsNewerThan(SemanticVersion.Parse("1.2.3-alpha.1"))); 24 | } 25 | 26 | [TestCase(null)] 27 | [TestCase("")] 28 | [TestCase(" ")] 29 | public void CannotCallParseWithInvalidVersion(string value) 30 | { 31 | Assert.Throws(() => SemanticVersion.Parse(value)); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/InterfaceSampleTestFile.txt: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace AssemblyCore 4 | { 5 | public interface IDummyService 6 | { 7 | void NoReturnMethod(); 8 | 9 | int ReturnMetod(); 10 | 11 | Task AsyncMethod(); 12 | 13 | Task AsyncReturnTaskAsync(); 14 | 15 | Task AsyncReturIntAsync(); 16 | 17 | Task AsyncReturnStringAsync(); 18 | } 19 | 20 | public class InterfaceSample 21 | { 22 | private IDummyService _dummyService; 23 | 24 | public InterfaceSample(IDummyService dummyService) 25 | { 26 | _dummyService = dummyService; 27 | } 28 | 29 | public void SampleNoReturn() 30 | { 31 | _dummyService.NoReturnMethod(); 32 | } 33 | 34 | 35 | public Task SampleAsyncMethod() 36 | { 37 | return _dummyService.AsyncMethod(); 38 | } 39 | 40 | public int SampleReturnMethod() 41 | { 42 | return _dummyService.ReturnMetod(); 43 | } 44 | 45 | public async Task SampleAsyncIntReturnInt() 46 | { 47 | return await _dummyService.AsyncReturIntAsync(); 48 | } 49 | 50 | public async Task SampleAsyncIntReturnString() 51 | { 52 | return await _dummyService.AsyncReturnStringAsync(); 53 | } 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Options/EditorConfigFieldMapperTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Options 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using NSubstitute; 6 | using NUnit.Framework; 7 | using SentryOne.UnitTestGenerator.Core.Options; 8 | 9 | [TestFixture] 10 | public static class EditorConfigFieldMapperTests 11 | { 12 | [Test] 13 | public static void CanCallApplyTo() 14 | { 15 | var fileConfiguration = new Dictionary { { "test_project_naming", "SomeProject{0}" } }; 16 | var target = new MutableGenerationOptions(Substitute.For()); 17 | fileConfiguration.ApplyTo(target); 18 | Assert.That(target.TestProjectNaming, Is.EqualTo("SomeProject{0}")); 19 | } 20 | 21 | [Test] 22 | public static void CannotCallApplyToWithNullFileConfiguration() 23 | { 24 | var target = new MutableGenerationOptions(Substitute.For()); 25 | Assert.Throws(() => default(Dictionary).ApplyTo(target)); 26 | } 27 | 28 | [Test] 29 | public static void CannotCallApplyToWithNullTarget() 30 | { 31 | Assert.Throws(() => new Dictionary().ApplyTo(default(MutableGenerationOptions))); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/TestableModel.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System; 4 | using Microsoft.CodeAnalysis; 5 | using SentryOne.UnitTestGenerator.Core.Resources; 6 | 7 | public abstract class TestableModel : ITestableModel 8 | where T : SyntaxNode 9 | { 10 | protected TestableModel(string name, T node) 11 | { 12 | if (string.IsNullOrWhiteSpace(name)) 13 | { 14 | throw new ArgumentNullException(nameof(name)); 15 | } 16 | 17 | OriginalName = Name = name; 18 | Node = node ?? throw new ArgumentNullException(nameof(node)); 19 | } 20 | 21 | public string Name { get; private set; } 22 | 23 | public T Node { get; } 24 | 25 | public string OriginalName { get; private set; } 26 | 27 | public void MutateName(string newName) 28 | { 29 | if (string.IsNullOrWhiteSpace(newName)) 30 | { 31 | throw new ArgumentNullException(nameof(newName)); 32 | } 33 | 34 | if (!string.Equals(OriginalName, Name, StringComparison.Ordinal)) 35 | { 36 | throw new InvalidOperationException(Strings.TestableModel_MutateName_Cannot_mutate_name_more_than_once); 37 | } 38 | 39 | OriginalName = Name; 40 | Name = newName; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/MethodGeneration/MappingMethodGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: MappingMethodGeneration 2 | I am checking the Mapping Method Generation strategy 3 | 4 | 5 | Scenario: Can Call Method Generation 6 | Given I have a class defined as 7 | """ 8 | public class C3 9 | { 10 | public OutputClass Map(InputClass inputClass) 11 | { 12 | return null; 13 | } 14 | } 15 | public class InputClass 16 | { 17 | public string SomeProperty { get; } 18 | public string SomeOtherProperty { get; set; } 19 | public string WriteOnlyProperty { set { } } 20 | } 21 | 22 | public class OutputClass 23 | { 24 | public string SomeProperty { get; set; } 25 | public string SomeOtherProperty { get; set; } 26 | public string WriteOnlyProperty { get; set; } 27 | } 28 | """ 29 | And I set my test framework to 'NUnit3' 30 | And I set my mock framework to 'FakeItEasy' 31 | When I generate tests for the method using the strategy 'MappingMethodGenerationStrategy' 32 | Then I expect a method called 'MapPerformsMapping' 33 | And I expect it to contain the variable 'inputClass' 34 | And I expect it to contain the statement 'var result = _testClass.Map(inputClass);' 35 | And I expect it to contain the statement 'Assert.That(result.SomeProperty, Is.EqualTo(inputClass.SomeProperty));' 36 | And I expect it to contain the statement 'Assert.That(result.SomeOtherProperty, Is.EqualTo(inputClass.SomeOtherProperty));' 37 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ValueGeneration/EnumFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.ValueGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | using SentryOne.UnitTestGenerator.Core.Frameworks; 10 | using SentryOne.UnitTestGenerator.Core.Helpers; 11 | 12 | public static class EnumFactory 13 | { 14 | public static ExpressionSyntax Random(ITypeSymbol typeSymbol, SemanticModel model, HashSet visitedTypes, IFrameworkSet frameworkSet) 15 | { 16 | if (typeSymbol == null) 17 | { 18 | throw new ArgumentNullException(nameof(typeSymbol)); 19 | } 20 | 21 | if (frameworkSet == null) 22 | { 23 | throw new ArgumentNullException(nameof(frameworkSet)); 24 | } 25 | 26 | var enumMembers = typeSymbol.GetMembers().OfType().Select(x => x.Name).ToList(); 27 | 28 | var identifier = enumMembers[ValueGenerationStrategyFactory.Random.Next(enumMembers.Count)]; 29 | 30 | return SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, typeSymbol.ToTypeSyntax(frameworkSet.Context), SyntaxFactory.IdentifierName(identifier)); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/TestTextFile.txt: -------------------------------------------------------------------------------- 1 | using AssemblyCore.Interfaces; 2 | 3 | namespace AssemblyCore 4 | { 5 | public class InterfaceSample 6 | { 7 | private IDummyService _dummyService; 8 | 9 | public InterfaceSample(IDummyService dummyService) 10 | { 11 | _dummyService = dummyService; 12 | } 13 | 14 | public void SampleNoReturn() 15 | { 16 | _dummyService.NoReturnMethod(); 17 | } 18 | 19 | 20 | public Task SampleAsyncMethod() 21 | { 22 | return _dummyService.AsyncMethod(); ; 23 | } 24 | 25 | public int SampleReturnMethod() 26 | { 27 | return _dummyService.ReturnMetod(); 28 | } 29 | 30 | public async Task SampleAsyncIntReturnInt() 31 | { 32 | return await _dummyService.AsyncReturIntAsync(); 33 | } 34 | 35 | public async Task SampleAsyncIntReturnString() 36 | { 37 | return await _dummyService.AsyncReturnStringAsync(); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/ClassBasedStrategyContext.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Specs 2 | { 3 | using System; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using SentryOne.UnitTestGenerator.Core.Models; 7 | using SentryOne.UnitTestGenerator.Core.Options; 8 | 9 | public class ClassBasedStrategyContext 10 | { 11 | public ClassBasedStrategyContext(BaseContext baseContext) 12 | { 13 | BaseContext = baseContext ?? throw new ArgumentNullException(nameof(baseContext)); 14 | } 15 | public ClassDeclarationSyntax Result { get; set; } 16 | public ClassDeclarationSyntax CurrentClass { get; set; } 17 | private BaseContext BaseContext { get; } 18 | public SemanticModel TestModel { get; set; } 19 | public TestFrameworkTypes TargetFramework => BaseContext.TargetFramework; 20 | public MockingFrameworkType MockFramework => BaseContext.MockFramework; 21 | public ClassModel ClassModel => BaseContext.ClassModel; 22 | public MethodDeclarationSyntax CurrentMethod 23 | { 24 | get 25 | { 26 | return BaseContext.CurrentMethod; 27 | } 28 | set 29 | { 30 | BaseContext.CurrentMethod = value; 31 | } 32 | } 33 | 34 | public SemanticModel SemanticModel => BaseContext.SemanticModel; 35 | } 36 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/AbstractClassTestFile.txt: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows; 3 | 4 | namespace TestNamespace { 5 | 6 | 7 | public abstract class TestClass 8 | { 9 | protected TestClass(int intProperty, string value, Stream targetStream) 10 | { 11 | 12 | } 13 | 14 | public abstract int SomeMethod(); 15 | 16 | public abstract void SomeVoidMethod(); 17 | 18 | protected abstract void SomeProtectedAbstractMethod(); 19 | 20 | public int IntProperty { get; set; } 21 | 22 | protected int IntGetOnlyProperty { get; private set; } 23 | 24 | protected string Value { get; set; } 25 | 26 | protected string Value2 { get; private set; } 27 | 28 | protected string Value3 { private get; set; } 29 | 30 | protected abstract string AbstractValue { get; set; } 31 | 32 | protected abstract string AbstractValue2 { get; } 33 | 34 | protected abstract string AbstractValue3 { set; } 35 | 36 | protected Stream TargetStream { get; } 37 | 38 | protected string SomeMethod(int i, int j) { return string.Empty; } 39 | 40 | protected abstract string SomeAbstractMethod(int i, int j); 41 | 42 | public abstract string SomePublicAbstractMethod(int p, int r); 43 | 44 | protected void SomeMethodVoid(int s, int t) { } 45 | 46 | protected internal void SomeMethodVoid2(int s, int t) { } 47 | 48 | protected internal abstract void SomeMethodVoid3(int s, int t); 49 | 50 | private protected abstract void SomeMethodVoid4(int s, int t); 51 | } 52 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Models/GenerationResultTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Models 2 | { 3 | using System.Collections.Generic; 4 | using NUnit.Framework; 5 | using SentryOne.UnitTestGenerator.Core.Assets; 6 | using SentryOne.UnitTestGenerator.Core.Models; 7 | 8 | [TestFixture] 9 | public class GenerationResultTests 10 | { 11 | private GenerationResult _testClass; 12 | private string _fileContent; 13 | 14 | [SetUp] 15 | public void SetUp() 16 | { 17 | _fileContent = "TestValue1767881884"; 18 | _testClass = new GenerationResult(_fileContent); 19 | } 20 | 21 | [Test] 22 | public void CanConstruct() 23 | { 24 | var instance = new GenerationResult(_fileContent); 25 | Assert.That(instance, Is.Not.Null); 26 | } 27 | 28 | [Test] 29 | public void FileContentIsInitializedCorrectly() 30 | { 31 | Assert.That(_testClass.FileContent, Is.EqualTo(_fileContent)); 32 | } 33 | 34 | [Test] 35 | public void CanGetRequiredAssets() 36 | { 37 | Assert.That(_testClass.RequiredAssets, Is.InstanceOf>()); 38 | } 39 | 40 | [Test] 41 | public void CanGetAssemblyReferences() 42 | { 43 | Assert.That(_testClass.AssemblyReferences, Is.InstanceOf>()); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Helpers/NamespaceTransform.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Helpers 2 | { 3 | using System; 4 | 5 | public static class NamespaceTransform 6 | { 7 | public static Func Create(string sourceNameSpaceRoot, string targetNameSpaceRoot) 8 | { 9 | if (string.IsNullOrWhiteSpace(sourceNameSpaceRoot)) 10 | { 11 | throw new ArgumentNullException(nameof(sourceNameSpaceRoot)); 12 | } 13 | 14 | if (string.IsNullOrWhiteSpace(targetNameSpaceRoot)) 15 | { 16 | throw new ArgumentNullException(nameof(targetNameSpaceRoot)); 17 | } 18 | 19 | return sourceNameSpace => Transform(sourceNameSpaceRoot, targetNameSpaceRoot, sourceNameSpace); 20 | } 21 | 22 | private static string Transform(string sourceNameSpaceRoot, string targetNameSpaceRoot, string sourceNameSpace) 23 | { 24 | if (string.IsNullOrWhiteSpace(sourceNameSpace)) 25 | { 26 | return targetNameSpaceRoot; 27 | } 28 | 29 | if (sourceNameSpace.StartsWith(sourceNameSpaceRoot, StringComparison.OrdinalIgnoreCase) && sourceNameSpace.Length > sourceNameSpaceRoot.Length) 30 | { 31 | return targetNameSpaceRoot + sourceNameSpace.Substring(sourceNameSpaceRoot.Length); 32 | } 33 | 34 | return targetNameSpaceRoot; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Helpers/NameExtractorTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Helpers 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using NUnit.Framework; 8 | using SentryOne.UnitTestGenerator.Core.Helpers; 9 | 10 | [TestFixture] 11 | public static class NameExtractorTests 12 | { 13 | [Test] 14 | public static void CanCallGetClassName() 15 | { 16 | var declaration = TestSemanticModelFactory.Class; 17 | var result = declaration.GetClassName(); 18 | Assert.That(result, Is.EqualTo("ModelSource")); 19 | } 20 | 21 | [Test] 22 | public static void CannotCallGetClassNameWithNullDeclaration() 23 | { 24 | Assert.Throws(() => default(TypeDeclarationSyntax).GetClassName()); 25 | } 26 | 27 | [Test] 28 | public static async Task CanCallGetNamespace() 29 | { 30 | var model = TestSemanticModelFactory.Model; 31 | var result = await model.GetNamespace().ConfigureAwait(true); 32 | Assert.That(result, Is.EqualTo("Test")); 33 | } 34 | 35 | [Test] 36 | public static void CannotCallGetNamespaceWithNullModel() 37 | { 38 | Assert.ThrowsAsync(() => default(SemanticModel).GetNamespace()); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/OperatorOverloading.txt: -------------------------------------------------------------------------------- 1 | namespace TestNamespace.SubNameSpace 2 | { 3 | using System; 4 | 5 | class Calculator { 6 | 7 | public int number = 0; 8 | 9 | // parameterized constructor 10 | public Calculator(int n) 11 | { 12 | number = n; 13 | } 14 | 15 | public static Calculator operator + (Calculator Calc1, 16 | Calculator Calc2) 17 | { 18 | Calculator Calc3 = new Calculator(0); 19 | Calc3.number = Calc2.number + Calc1.number; 20 | return Calc3; 21 | } 22 | 23 | public static Calculator operator - (Calculator Calc1, 24 | Calculator Calc2) 25 | { 26 | Calculator Calc3 = new Calculator(0); 27 | Calc3.number = Calc2.number - Calc1.number; 28 | return Calc3; 29 | } 30 | 31 | public static Calculator operator - (Calculator Calc1) 32 | { 33 | Calculator Calc3 = new Calculator(0); 34 | Calc3.number = Calc1.number * -1; 35 | return Calc3; 36 | } 37 | 38 | public static Calculator operator * (Calculator Calc1, 39 | Calculator Calc2) 40 | { 41 | Calculator Calc3 = new Calculator(0); 42 | Calc3.number = Calc2.number * Calc1.number; 43 | return Calc3; 44 | } 45 | 46 | public static Calculator operator / (Calculator Calc1, 47 | Calculator Calc2) 48 | { 49 | Calculator Calc3 = new Calculator(0); 50 | Calc3.number = Calc2.number / Calc1.number; 51 | return Calc3; 52 | } 53 | 54 | } 55 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/ReferencedAssembly.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System; 4 | using System.Globalization; 5 | 6 | public class ReferencedAssembly : IReferencedAssembly 7 | { 8 | public ReferencedAssembly(string name, Version version, string location) 9 | { 10 | if (string.IsNullOrWhiteSpace(name)) 11 | { 12 | throw new ArgumentNullException(nameof(name)); 13 | } 14 | 15 | if (version == null) 16 | { 17 | throw new ArgumentNullException(nameof(version)); 18 | } 19 | 20 | if (string.IsNullOrWhiteSpace(location)) 21 | { 22 | throw new ArgumentNullException(nameof(location)); 23 | } 24 | 25 | Name = name; 26 | Version = version; 27 | Location = location; 28 | } 29 | 30 | public string Name { get; } 31 | 32 | public string LocatableName 33 | { 34 | get 35 | { 36 | if (!string.Equals(Name, "nunit.framework", StringComparison.OrdinalIgnoreCase)) 37 | { 38 | return Name; 39 | } 40 | 41 | return string.Format(CultureInfo.InvariantCulture, "nunit.framework({0})", Version.Major); 42 | } 43 | } 44 | 45 | public Version Version { get; } 46 | 47 | public string Location { get; } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Helpers/SymbolExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Helpers 2 | { 3 | using System.Linq; 4 | using Microsoft.CodeAnalysis; 5 | 6 | public static class SymbolExtensions 7 | { 8 | public static bool IsAwaitableNonDynamic(this IMethodSymbol symbol) 9 | { 10 | if (symbol == null) 11 | { 12 | return false; 13 | } 14 | 15 | return symbol.ReturnType.GetMembers(WellKnownMemberNames.GetAwaiter).OfType().Where(x => !x.Parameters.Any()).Any(VerifyGetAwaiter); 16 | } 17 | 18 | private static bool VerifyGetAwaiter(IMethodSymbol getAwaiter) 19 | { 20 | var returnType = getAwaiter.ReturnType; 21 | if (returnType != null) 22 | { 23 | if (returnType.GetMembers().OfType().Any(p => p.Name == WellKnownMemberNames.IsCompleted && p.Type.SpecialType == SpecialType.System_Boolean && p.GetMethod != null)) 24 | { 25 | var methods = returnType.GetMembers().OfType().ToList(); 26 | 27 | return methods.Any(x => x.Name == WellKnownMemberNames.OnCompleted && x.ReturnsVoid && x.Parameters.Length == 1 && x.Parameters.First().Type.TypeKind == TypeKind.Delegate) && methods.Any(m => m.Name == WellKnownMemberNames.GetResult && !m.Parameters.Any()); 28 | } 29 | } 30 | 31 | return false; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/ClassGeneration/ClassGenerationStrategyFactoryTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.ClassGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Models; 8 | using SentryOne.UnitTestGenerator.Core.Strategies.ClassGeneration; 9 | 10 | [TestFixture] 11 | public class ClassGenerationStrategyFactoryTests 12 | { 13 | private ClassGenerationStrategyFactory _testClass; 14 | private IFrameworkSet _frameworkSet; 15 | 16 | [SetUp] 17 | public void SetUp() 18 | { 19 | _frameworkSet = Substitute.For(); 20 | _testClass = new ClassGenerationStrategyFactory(_frameworkSet); 21 | } 22 | 23 | [Test] 24 | public void CanConstruct() 25 | { 26 | var instance = new ClassGenerationStrategyFactory(_frameworkSet); 27 | Assert.That(instance, Is.Not.Null); 28 | } 29 | 30 | [Test] 31 | public void CannotConstructWithNullFrameworkSet() 32 | { 33 | Assert.Throws(() => new ClassGenerationStrategyFactory(default(IFrameworkSet))); 34 | } 35 | 36 | [Test] 37 | public void CannotCallCreateForWithNullModel() 38 | { 39 | Assert.Throws(() => _testClass.CreateFor(default(ClassModel))); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/ClassLevelGeneration/CanConstructNoConstructorGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: CanConstructNoConstructorGeneration 2 | I am checking the Can Construct No Constructor Generation Strategy 3 | 4 | 5 | Scenario: Can Construct No Constructor Generation 6 | Given I have a class defined as 7 | """ 8 | namespace TestNamespace.SubNameSpace 9 | { 10 | using System; 11 | 12 | public class SomePoco 13 | { 14 | public int ThisIsAProperty {get;set;} 15 | public string ThisIsAProperty2 {get;set;} 16 | public Guid ThisIsAProperty3 {get;set;} 17 | public Guid? ThisIsAProperty4 {get;set;} 18 | public int ThisIsAProperty5 {get;private set;} 19 | private int ThisIsAProperty6 {get;set;} 20 | public Guid ThisIsAProperty7 {get;set;} 21 | public Guid ThisIsAProperty8 {get;set;} 22 | public Guid ThisIsAProperty9 {get;set;} 23 | } 24 | 25 | public class TestClass 26 | { 27 | SomePoco _poco; 28 | 29 | public TestClass(SomePoco poco) 30 | { 31 | _poco = poco; 32 | } 33 | 34 | public SomePoco Poco => _poco; 35 | } 36 | } 37 | """ 38 | And I set my test framework to 'XUnit' 39 | And I set my mock framework to 'FakeItEasy' 40 | When I generate unit tests for the class using strategy 'CanConstructNoConstructorGenerationStrategy' 41 | Then I expect a method called 'CanConstruct' 42 | And I expect it to contain the statement 'var instance = new SomePoco();' 43 | And I expect it to contain 1 statements called 'Assert.NotNull(instance);' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("SentryOne.UnitTestGenerator.Core.Tests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("SentryOne.UnitTestGenerator.Core.Tests")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("bda96138-2ceb-44b3-ad1f-8b253f736054")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Options/MutableGenerationOptions.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Options 2 | { 3 | using System; 4 | 5 | public class MutableGenerationOptions : IGenerationOptions 6 | { 7 | public MutableGenerationOptions(IGenerationOptions options) 8 | { 9 | if (options == null) 10 | { 11 | throw new ArgumentNullException(nameof(options)); 12 | } 13 | 14 | FrameworkType = options.FrameworkType; 15 | MockingFrameworkType = options.MockingFrameworkType; 16 | CreateProjectAutomatically = options.CreateProjectAutomatically; 17 | AddReferencesAutomatically = options.AddReferencesAutomatically; 18 | AllowGenerationWithoutTargetProject = options.AllowGenerationWithoutTargetProject; 19 | TestProjectNaming = options.TestProjectNaming; 20 | TestFileNaming = options.TestFileNaming; 21 | TestTypeNaming = options.TestTypeNaming; 22 | } 23 | 24 | public TestFrameworkTypes FrameworkType { get; set; } 25 | 26 | public MockingFrameworkType MockingFrameworkType { get; set; } 27 | 28 | public bool CreateProjectAutomatically { get; set; } 29 | 30 | public bool AddReferencesAutomatically { get; set; } 31 | 32 | public bool AllowGenerationWithoutTargetProject { get; set; } 33 | 34 | public string TestProjectNaming { get; set; } 35 | 36 | public string TestFileNaming { get; set; } 37 | 38 | public string TestTypeNaming { get; set; } 39 | } 40 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/ClassGeneration/StaticClassGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: StaticClassGeneration 2 | I am checking the Static Class Generation strategy 3 | 4 | Scenario: Static Class Generation 5 | Given I have a class defined as 6 | """ 7 | namespace TestNamespace.SubNameSpace 8 | { 9 | 10 | public interface ITest 11 | { 12 | int ThisIsAProperty {get;set;} 13 | } 14 | 15 | public class TestClass 16 | { 17 | public TestClass(string stringProp, ITest iTest) 18 | { 19 | 20 | } 21 | 22 | public TestClass(int? nullableIntProp, ITest iTest) 23 | { 24 | 25 | } 26 | 27 | public TestClass(int thisIsAProperty, ITest iTest) 28 | { 29 | 30 | } 31 | public void ThisIsAMethod(string methodName, int methodValue) 32 | { 33 | System.Console.WriteLine("Testing this"); 34 | } 35 | 36 | public string WillReturnAString() 37 | { 38 | return "Hello"; 39 | } 40 | 41 | private string _thisIsAString = string.Empty; 42 | public string ThisIsAWriteOnlyString { set { _thisIsAString = value; }} 43 | 44 | public int ThisIsAProperty { get;set;} 45 | 46 | public ITest GetITest { get; } 47 | 48 | public TestClass ThisClass {get;set;} 49 | } 50 | } 51 | """ 52 | And I set my test framework to 'NUnit3' 53 | And I set my mock framework to 'NSubstitute' 54 | When I generate tests for the class using strategy 'StaticClassGenerationStrategy' 55 | Then I expect the class to have the modifier 'static' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ClassDecoration/ClassDecorationStrategyFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.ClassDecoration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using SentryOne.UnitTestGenerator.Core.Frameworks; 8 | using SentryOne.UnitTestGenerator.Core.Models; 9 | 10 | public class ClassDecorationStrategyFactory 11 | { 12 | private readonly IList _strategies; 13 | 14 | public ClassDecorationStrategyFactory(IFrameworkSet frameworkSet) 15 | { 16 | var frameworkSet1 = frameworkSet ?? throw new ArgumentNullException(nameof(frameworkSet)); 17 | 18 | _strategies = new List 19 | { 20 | new RequiresStaGenerationStrategy(frameworkSet1), 21 | }; 22 | } 23 | 24 | public TypeDeclarationSyntax Apply(TypeDeclarationSyntax syntax, ClassModel model) 25 | { 26 | var strategies = _strategies.OrderByDescending(x => x.Priority); 27 | 28 | foreach (var strategy in strategies) 29 | { 30 | if (strategy.CanHandle(syntax, model)) 31 | { 32 | syntax = strategy.Apply(syntax, model); 33 | } 34 | 35 | if (strategy.IsExclusive) 36 | { 37 | break; 38 | } 39 | } 40 | 41 | return syntax; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Helpers/NamespaceTransformTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Helpers 2 | { 3 | using System; 4 | using NUnit.Framework; 5 | using SentryOne.UnitTestGenerator.Core.Helpers; 6 | 7 | [TestFixture] 8 | public static class NamespaceTransformTests 9 | { 10 | [Test] 11 | public static void CanCallCreate() 12 | { 13 | var sourceNameSpaceRoot = "TestValue1446777119"; 14 | var targetNameSpaceRoot = "TestValue70491992"; 15 | var result = NamespaceTransform.Create(sourceNameSpaceRoot, targetNameSpaceRoot); 16 | Assert.That(result("TestValue1446777119.Some.Other.Bit"), Is.EqualTo("TestValue70491992.Some.Other.Bit")); 17 | Assert.That(result("TestValue1446777119"), Is.EqualTo("TestValue70491992")); 18 | Assert.That(result(string.Empty), Is.EqualTo("TestValue70491992")); 19 | } 20 | 21 | [TestCase(null)] 22 | [TestCase("")] 23 | [TestCase(" ")] 24 | public static void CannotCallCreateWithInvalidSourceNameSpaceRoot(string value) 25 | { 26 | Assert.Throws(() => NamespaceTransform.Create(value, "TestValue1220339710")); 27 | } 28 | 29 | [TestCase(null)] 30 | [TestCase("")] 31 | [TestCase(" ")] 32 | public static void CannotCallCreateWithInvalidTargetNameSpaceRoot(string value) 33 | { 34 | Assert.Throws(() => NamespaceTransform.Create("TestValue2131007467", value)); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ValueGeneration/SimpleValueGenerationStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.ValueGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using SentryOne.UnitTestGenerator.Core.Frameworks; 8 | 9 | public class SimpleValueGenerationStrategy : IValueGenerationStrategy 10 | { 11 | private readonly Func _factory; 12 | 13 | public SimpleValueGenerationStrategy(Func factory, params string[] typeNames) 14 | { 15 | _factory = factory ?? throw new ArgumentNullException(nameof(factory)); 16 | SupportedTypeNames = typeNames ?? throw new ArgumentNullException(nameof(typeNames)); 17 | } 18 | 19 | public IEnumerable SupportedTypeNames { get; } 20 | 21 | public ExpressionSyntax CreateValueExpression(ITypeSymbol symbol, SemanticModel model, HashSet visitedTypes, IFrameworkSet frameworkSet) 22 | { 23 | if (symbol is null) 24 | { 25 | throw new ArgumentNullException(nameof(symbol)); 26 | } 27 | 28 | if (model is null) 29 | { 30 | throw new ArgumentNullException(nameof(model)); 31 | } 32 | 33 | if (frameworkSet is null) 34 | { 35 | throw new ArgumentNullException(nameof(frameworkSet)); 36 | } 37 | 38 | return _factory(); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/ClassLevelGeneration/NullParameterCheckConstructorGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: NullParameterCheckConstructorGeneration 2 | I am checking the Null Parameter Check Construction Generation strategy 3 | 4 | 5 | Scenario: Null Parameter Check Constructor Generation 6 | Given I have a class defined as 7 | """ 8 | public class TestClass 9 | { 10 | public TestClass(string stringProp, ITest iTest) 11 | { 12 | 13 | } 14 | 15 | public TestClass(int? nullableIntProp, ITest iTest) 16 | { 17 | 18 | } 19 | 20 | public TestClass(int thisIsAProperty, ITest iTest) 21 | { 22 | 23 | } 24 | 25 | public void ThisIsAMethod(string methodName, int methodValue) 26 | { 27 | System.Console.WriteLine("Testing this"); 28 | } 29 | 30 | public string WillReturnAString() 31 | { 32 | return "Hello"; 33 | } 34 | 35 | private string _thisIsAString = string.Empty; 36 | public string ThisIsAWriteOnlyString { set { _thisIsAString = value; }} 37 | 38 | public int ThisIsAProperty { get;set;} 39 | 40 | public ITest GetITest { get; } 41 | 42 | public TestClass ThisClass {get;set;} 43 | } 44 | """ 45 | And I set my test framework to 'MS Test' 46 | And I set my mock framework to 'Moq' 47 | When I generate unit tests for the class using strategy 'NullParameterCheckConstructorGenerationStrategy' 48 | Then I expect a method called 'CannotConstructWithNullITest' 49 | And I expect it to have the attribute 'TestMethod' 50 | And I expect it to contain a statement like 'Assert.ThrowsException(() => new TestClass({{{AnyString}}}, default(ITest)));' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Options/MutableVersioningOptions.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Options 2 | { 3 | using System; 4 | 5 | public class MutableVersioningOptions : IVersioningOptions 6 | { 7 | public MutableVersioningOptions(IVersioningOptions options) 8 | { 9 | if (options == null) 10 | { 11 | throw new ArgumentNullException(nameof(options)); 12 | } 13 | 14 | NUnit2NugetPackageVersion = options.NUnit2NugetPackageVersion; 15 | NUnit3NugetPackageVersion = options.NUnit3NugetPackageVersion; 16 | XUnitNugetPackageVersion = options.XUnitNugetPackageVersion; 17 | MsTestNugetPackageVersion = options.MsTestNugetPackageVersion; 18 | FakeItEasyNugetPackageVersion = options.FakeItEasyNugetPackageVersion; 19 | MoqNugetPackageVersion = options.MoqNugetPackageVersion; 20 | NSubstituteNugetPackageVersion = options.NSubstituteNugetPackageVersion; 21 | RhinoMocksNugetPackageVersion = options.RhinoMocksNugetPackageVersion; 22 | } 23 | 24 | public string NUnit2NugetPackageVersion { get; set; } 25 | 26 | public string NUnit3NugetPackageVersion { get; set; } 27 | 28 | public string XUnitNugetPackageVersion { get; set; } 29 | 30 | public string MsTestNugetPackageVersion { get; set; } 31 | 32 | public string FakeItEasyNugetPackageVersion { get; set; } 33 | 34 | public string MoqNugetPackageVersion { get; set; } 35 | 36 | public string NSubstituteNugetPackageVersion { get; set; } 37 | 38 | public string RhinoMocksNugetPackageVersion { get; set; } 39 | } 40 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Helpers/GenerationContext.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Helpers 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.CodeAnalysis; 6 | 7 | public class GenerationContext : IGenerationContext 8 | { 9 | private readonly List _emittedTypes = new List(); 10 | private readonly HashSet _emittedTypeFullNames = new HashSet(); 11 | private readonly HashSet _genericTypes = new HashSet(); 12 | 13 | public IEnumerable EmittedTypes => _emittedTypes; 14 | 15 | public IEnumerable GenericTypes => _genericTypes; 16 | 17 | public bool MocksUsed { get; set; } 18 | 19 | public void AddEmittedType(ITypeSymbol typeInfo) 20 | { 21 | if (typeInfo == null) 22 | { 23 | throw new ArgumentNullException(nameof(typeInfo)); 24 | } 25 | 26 | var fullName = typeInfo.ToDisplayString(new SymbolDisplayFormat( 27 | SymbolDisplayGlobalNamespaceStyle.Omitted, 28 | SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, 29 | SymbolDisplayGenericsOptions.IncludeTypeParameters, 30 | miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes)); 31 | 32 | if (_emittedTypeFullNames.Add(fullName)) 33 | { 34 | _emittedTypes.Add(typeInfo); 35 | } 36 | } 37 | 38 | public void AddGenericType(string identifier) 39 | { 40 | _genericTypes.Add(identifier); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Helper/StatusBarMessageLogger.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Helper 2 | { 3 | using System; 4 | using Microsoft.VisualStudio.Shell; 5 | using Microsoft.VisualStudio.Shell.Interop; 6 | using SentryOne.UnitTestGenerator.Core.Helpers; 7 | 8 | public class StatusBarMessageLogger : IMessageLogger 9 | { 10 | private IVsStatusbar _vsStatusBar; 11 | 12 | public void Initialize() 13 | { 14 | ThreadHelper.ThrowIfNotOnUIThread(); 15 | 16 | try 17 | { 18 | _vsStatusBar = (IVsStatusbar)Package.GetGlobalService(typeof(SVsStatusbar)); 19 | } 20 | #pragma warning disable CA1031 // Do not catch general exception types 21 | catch (Exception) 22 | #pragma warning restore CA1031 // Do not catch general exception types 23 | { 24 | _vsStatusBar = null; 25 | } 26 | } 27 | 28 | public void LogMessage(string message) 29 | { 30 | if (_vsStatusBar == null || string.IsNullOrWhiteSpace(message)) 31 | { 32 | return; 33 | } 34 | 35 | ThreadHelper.ThrowIfNotOnUIThread(); 36 | 37 | if (_vsStatusBar.IsFrozen(out var frozen) != 0 || frozen != 0) 38 | { 39 | return; 40 | } 41 | 42 | try 43 | { 44 | Ignore.HResult(_vsStatusBar.SetText(message)); 45 | Ignore.HResult(_vsStatusBar.FreezeOutput(1)); 46 | } 47 | finally 48 | { 49 | Ignore.HResult(_vsStatusBar.FreezeOutput(0)); 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ClassGeneration/ClassGenerationStrategyFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.ClassGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using SentryOne.UnitTestGenerator.Core.Frameworks; 8 | using SentryOne.UnitTestGenerator.Core.Models; 9 | 10 | public class ClassGenerationStrategyFactory 11 | { 12 | private readonly IList _strategies; 13 | 14 | public ClassGenerationStrategyFactory(IFrameworkSet frameworkSet) 15 | { 16 | var frameworkSet1 = frameworkSet ?? throw new ArgumentNullException(nameof(frameworkSet)); 17 | 18 | _strategies = new List 19 | { 20 | new StandardClassGenerationStrategy(frameworkSet1), 21 | new AbstractClassGenerationStrategy(frameworkSet1), 22 | new StaticClassGenerationStrategy(frameworkSet1), 23 | }; 24 | } 25 | 26 | public TypeDeclarationSyntax CreateFor(ClassModel model) 27 | { 28 | if (model == null) 29 | { 30 | throw new ArgumentNullException(nameof(model)); 31 | } 32 | 33 | var strategy = _strategies.Where(x => x.CanHandle(model)).OrderByDescending(x => x.Priority).FirstOrDefault(); 34 | if (strategy == null) 35 | { 36 | throw new InvalidOperationException("Cannot find a strategy for generation for the type " + model.ClassName); 37 | } 38 | 39 | return strategy.Create(model); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Helpers/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Helpers 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | public static class StringExtensions 8 | { 9 | public static string ToCamelCase(this string source) 10 | { 11 | if (string.IsNullOrWhiteSpace(source)) 12 | { 13 | return source; 14 | } 15 | 16 | if (source.Length > 1) 17 | { 18 | #pragma warning disable CA1308 // Normalize strings to uppercase 19 | return source.Substring(0, 1).ToLowerInvariant() + source.Substring(1); 20 | #pragma warning restore CA1308 // Normalize strings to uppercase 21 | } 22 | 23 | #pragma warning disable CA1308 // Normalize strings to uppercase 24 | return source.ToLowerInvariant(); 25 | #pragma warning restore CA1308 // Normalize strings to uppercase 26 | } 27 | 28 | public static string ToPascalCase(this string source) 29 | { 30 | if (string.IsNullOrWhiteSpace(source)) 31 | { 32 | return source; 33 | } 34 | 35 | if (source.Length > 1) 36 | { 37 | return source.Substring(0, 1).ToUpperInvariant() + source.Substring(1); 38 | } 39 | 40 | return source.ToUpperInvariant(); 41 | } 42 | 43 | public static IEnumerable Lines(this string input) 44 | { 45 | return string.IsNullOrEmpty(input) ? 46 | Enumerable.Empty() : 47 | input.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/ValueGeneration/TypedValueGenerationStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.ValueGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using SentryOne.UnitTestGenerator.Core.Frameworks; 8 | 9 | public class TypedValueGenerationStrategy : IValueGenerationStrategy 10 | { 11 | private readonly Func, IFrameworkSet, ExpressionSyntax> _factory; 12 | 13 | public TypedValueGenerationStrategy(Func, IFrameworkSet, ExpressionSyntax> factory, params string[] typeNames) 14 | { 15 | _factory = factory ?? throw new ArgumentNullException(nameof(factory)); 16 | SupportedTypeNames = typeNames ?? throw new ArgumentNullException(nameof(typeNames)); 17 | } 18 | 19 | public IEnumerable SupportedTypeNames { get; } 20 | 21 | public ExpressionSyntax CreateValueExpression(ITypeSymbol symbol, SemanticModel model, HashSet visitedTypes, IFrameworkSet frameworkSet) 22 | { 23 | if (symbol is null) 24 | { 25 | throw new ArgumentNullException(nameof(symbol)); 26 | } 27 | 28 | if (model is null) 29 | { 30 | throw new ArgumentNullException(nameof(model)); 31 | } 32 | 33 | if (frameworkSet is null) 34 | { 35 | throw new ArgumentNullException(nameof(frameworkSet)); 36 | } 37 | 38 | return _factory(symbol, model, visitedTypes, frameworkSet); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Helpers/NameExtractor.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Helpers 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | using SentryOne.UnitTestGenerator.Core.Resources; 10 | 11 | public static class NameExtractor 12 | { 13 | public static string GetClassName(this TypeDeclarationSyntax declaration) 14 | { 15 | if (declaration == null) 16 | { 17 | throw new ArgumentNullException(nameof(declaration)); 18 | } 19 | 20 | var classIdentifierToken = declaration.ChildTokens().FirstOrDefault(n => n.Kind() == SyntaxKind.IdentifierToken); 21 | if (classIdentifierToken == default(SyntaxToken)) 22 | { 23 | throw new InvalidOperationException(Strings.NameExtractor_GetClassName_Could_not_find_type_identifier_); 24 | } 25 | 26 | return classIdentifierToken.Text; 27 | } 28 | 29 | public static async Task GetNamespace(this SemanticModel model) 30 | { 31 | if (model == null) 32 | { 33 | throw new ArgumentNullException(nameof(model)); 34 | } 35 | 36 | var root = await model.SyntaxTree.GetRootAsync().ConfigureAwait(true); 37 | var namespaceDeclaration = root.DescendantNodes().FirstOrDefault(node => node.IsKind(SyntaxKind.NamespaceDeclaration)); 38 | 39 | var namespaceString = ((NamespaceDeclarationSyntax)namespaceDeclaration)?.Name.ToString(); 40 | 41 | return namespaceString; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Strategies/InterfaceGeneration/InterfaceGenerationStrategyFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Strategies.InterfaceGeneration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Microsoft.CodeAnalysis; 7 | using SentryOne.UnitTestGenerator.Core.Frameworks; 8 | using SentryOne.UnitTestGenerator.Core.Helpers; 9 | using SentryOne.UnitTestGenerator.Core.Models; 10 | 11 | public class InterfaceGenerationStrategyFactory : ItemGenerationStrategyFactory 12 | { 13 | private static readonly Dictionary>> StrategyFactories = new Dictionary>> 14 | { 15 | { "System.IComparable", frameworkSet => new ComparableGenerationStrategy(frameworkSet) }, 16 | { "System.Collections.Generic.IEnumerable", frameworkSet => new EnumerableGenerationStrategy(frameworkSet) }, 17 | }; 18 | 19 | private readonly IFrameworkSet _frameworkSet; 20 | 21 | public InterfaceGenerationStrategyFactory(IFrameworkSet frameworkSet) 22 | { 23 | _frameworkSet = frameworkSet ?? throw new ArgumentNullException(nameof(frameworkSet)); 24 | } 25 | 26 | protected override IEnumerable> Strategies => StrategyFactories.Values.Select(x => x(_frameworkSet)).ToList(); 27 | 28 | public static bool Supports(TypeInfo typeInfo) 29 | { 30 | if (typeInfo.Type == null) 31 | { 32 | return false; 33 | } 34 | 35 | return StrategyFactories.ContainsKey(typeInfo.Type.ToFullName()); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/BaseSteps.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Specs 2 | { 3 | using System.Linq; 4 | using Microsoft.CodeAnalysis.CSharp; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using SentryOne.UnitTestGenerator.Core.Helpers; 7 | using SentryOne.UnitTestGenerator.Core.Options; 8 | using TechTalk.SpecFlow; 9 | 10 | [Binding] 11 | public class BaseSteps 12 | { 13 | private readonly BaseContext _context; 14 | 15 | public BaseSteps(BaseContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | [Given(@"I have a class defined as")] 21 | public void GivenIHaveAClassThatImplements(string classAsText) 22 | { 23 | var syntaxTree = CSharpSyntaxTree.ParseText(classAsText); 24 | var compilation = CSharpCompilation.Create("MyTest", new[] { syntaxTree }, SemanticModelHelper.References.Value); 25 | var model = compilation.GetSemanticModel(syntaxTree); 26 | _context.SemanticModel = model; 27 | 28 | var extractor = new TestableItemExtractor(syntaxTree, model); 29 | _context.ClassModel = extractor.Extract(syntaxTree.GetRoot().DescendantNodes().OfType().First()).First(); 30 | } 31 | 32 | [Given(@"I set my test framework to '(.*)'")] 33 | public void GivenISetMyGenerationFrameworkTo(TestFrameworkTypes frameworkType) 34 | { 35 | _context.TargetFramework = frameworkType; 36 | } 37 | 38 | [Given(@"I set my mock framework to '(.*)'")] 39 | public void GivenISetMyGenerationMockFrameworkTo(MockingFrameworkType mockType) 40 | { 41 | _context.MockFramework = mockType; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/IndexerGeneration/WriteOnlyIndexerGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: WriteOnlyIndexerGeneration 2 | I am checking the Write Only Indexer Generation strategy 3 | 4 | 5 | Scenario: Write Only Indexer Generation 6 | Given I have a class defined as 7 | """ 8 | using System; 9 | using System.Drawing; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | using System.Windows; 14 | using System.Collections; 15 | using System.Collections.Generic; 16 | 17 | namespace WindowsFormsApp1 18 | { 19 | public class Form1 20 | { 21 | public string this[string cookieName, Guid cookieValue, DateTime cookieExpirationTime] 22 | { 23 | set 24 | { 25 | } 26 | } 27 | 28 | public string this[string cookieName] 29 | { 30 | get { 31 | return "hello"; 32 | } 33 | } 34 | 35 | public string this[string cookieName, int cookieId] 36 | { 37 | get { 38 | return "hello"; 39 | } 40 | set { 41 | } 42 | } 43 | } 44 | } 45 | """ 46 | And I set my test framework to 'NUnit3' 47 | And I set my mock framework to 'FakeItEasy' 48 | When I generate tests for the indexer using the strategy 'WriteOnlyIndexerGenerationStrategy' 49 | Then I expect a method called 'CanSetIndexerForStringAndGuidAndDateTime' 50 | And I expect it to have the attribute 'Test' 51 | And I expect it to contain the statement 'Assert.Fail("Create or modify test");' 52 | And I expect it to contain a statement like '_testClass[{{{AnyString}}}, new Guid({{{AnyString}}}), new DateTime({{{AnyInteger}}})] = {{{AnyString}}};' 53 | And I expect no method with a name like '.*StringAndInt.*' 54 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/InterfaceGeneration/ComparableGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: ComparableGeneration 2 | I am checking the Comparable Generation strategy 3 | 4 | Scenario: Comparable Generation 5 | Given I have a class defined as 6 | """ 7 | using System; 8 | 9 | namespace AssemblyCore 10 | { 11 | public class TestComparableGeneric : IComparable, IComparable, IComparable 12 | { 13 | public TestComparableGeneric(int value) 14 | { 15 | Value = value; 16 | } 17 | 18 | public int Value { get; } 19 | 20 | public int CompareTo(TestComparableGeneric obj) 21 | { 22 | if (obj == null) 23 | { 24 | throw new ArgumentNullException(); 25 | } 26 | 27 | return Value.CompareTo(obj.Value); 28 | } 29 | 30 | public int CompareTo(int value) 31 | { 32 | return Value.CompareTo(value); 33 | } 34 | 35 | public int CompareTo(object obj) 36 | { 37 | if (obj is null) 38 | { 39 | throw new ArgumentNullException(nameof(obj)); 40 | } 41 | 42 | return Value.CompareTo(obj); 43 | } 44 | } 45 | } 46 | """ 47 | And I set my test framework to 'NUnit2' 48 | And I set my mock framework to 'NSubstitute' 49 | When I generate unit tests for the class using strategy 'ComparableGenerationStrategy' 50 | Then I expect a method called 'ImplementsIComparable' 51 | And I expect it to contain the statement 'Assert.That(baseValue.CompareTo(equalToBaseValue), Is.EqualTo(0));' 52 | And I expect it to have the attribute 'Test' 53 | And I expect a method called 'ImplementsIComparable_Int32' 54 | And I expect it to contain the statement 'int greaterThanBaseValue = default(int);' 55 | And I expect a method called 'ImplementsIComparable_TestComparableGeneric' 56 | And I expect it to contain the variable 'baseValue' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/NestedClassTestFile.txt: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AssemblyCore 4 | { 5 | public class NestedClass 6 | { 7 | public InnerPublicClass innerPubClass { get; } 8 | public InnerPublicClass InnerPubliClassOne { get; } 9 | public InnerPublicClass InnerPublicClassTwo { get; } 10 | 11 | public NestedClass() 12 | { 13 | 14 | } 15 | 16 | public NestedClass(InnerPublicClass innerPublicClass) 17 | { 18 | innerPubClass = innerPublicClass; 19 | } 20 | public NestedClass(InnerPublicClass innerPubliClassOne, InnerPublicClass innerPublicClassTwo) 21 | { 22 | InnerPubliClassOne = innerPubliClassOne; 23 | InnerPublicClassTwo = innerPublicClassTwo; 24 | } 25 | 26 | private class InnerPrivateClass 27 | { 28 | public string ArgumentOne { get; } 29 | public int ArgumentTwo { get; } 30 | 31 | public InnerPrivateClass() 32 | { 33 | 34 | } 35 | 36 | public InnerPrivateClass(string argumentOne, int argumentTwo) 37 | { 38 | ArgumentOne = argumentOne; 39 | ArgumentTwo = argumentTwo; 40 | } 41 | 42 | } 43 | public class InnerPublicClass 44 | { 45 | public string ArgumentOne { get; } 46 | public int ArgumentTwo { get; } 47 | 48 | public InnerPublicClass() 49 | { 50 | 51 | } 52 | 53 | public InnerPublicClass(string argumentOne, int argumentTwo) 54 | { 55 | ArgumentOne = argumentOne; 56 | ArgumentTwo = argumentTwo; 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/IndexerGeneration/ReadOnlyIndexerGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: ReadOnlyIndexerGeneration 2 | I am checking the Read Only Indexer Generation strategy 3 | 4 | 5 | Scenario: Read Only Indexer Generation 6 | Given I have a class defined as 7 | """ 8 | using System; 9 | using System.Drawing; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | using System.Windows; 14 | using System.Collections; 15 | using System.Collections.Generic; 16 | 17 | namespace WindowsFormsApp1 18 | { 19 | public class Form1 20 | { 21 | public string this[string cookieName, Guid cookieValue, DateTime cookieExpirationTime] 22 | { 23 | set 24 | { 25 | } 26 | } 27 | 28 | public string this[string cookieName] 29 | { 30 | get { 31 | return "hello"; 32 | } 33 | } 34 | 35 | public string this[string cookieName, int cookieId] 36 | { 37 | get { 38 | return "hello"; 39 | } 40 | set { 41 | } 42 | } 43 | } 44 | } 45 | """ 46 | And I set my test framework to 'NUnit3' 47 | And I set my mock framework to 'FakeItEasy' 48 | When I generate tests for the indexer using the strategy 'ReadOnlyIndexerGenerationStrategy' 49 | Then I expect a method called 'CanGetIndexerForString' 50 | And I expect it to have the attribute 'Test' 51 | And I expect it to contain the statement 'Assert.Fail("Create or modify test");' 52 | And I expect it to contain a statement like 'Assert.That(_testClass[{{{AnyString}}}], Is.InstanceOf());' 53 | And I expect no method with a name like '.*StringAndGuidAndDateTime.*' 54 | And I expect no method with a name like '.*StringAndInt.*' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/ClassLevelGeneration/CanConstructMultiConstructorGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: CanConstructMultiConstructorGeneration 2 | I am checking the Can Construct Multi Constructor Generation strategy 3 | 4 | 5 | Scenario: Can Construct Multi Constructor Generation 6 | Given I have a class defined as 7 | """ 8 | public class TestClass 9 | { 10 | public TestClass(string stringProp, ITest iTest) 11 | { 12 | 13 | } 14 | 15 | public TestClass(int? nullableIntProp, ITest iTest) 16 | { 17 | 18 | } 19 | 20 | public TestClass(int thisIsAProperty, ITest iTest) 21 | { 22 | 23 | } 24 | 25 | public void ThisIsAMethod(string methodName, int methodValue) 26 | { 27 | System.Console.WriteLine("Testing this"); 28 | } 29 | 30 | public string WillReturnAString() 31 | { 32 | return "Hello"; 33 | } 34 | 35 | private string _thisIsAString = string.Empty; 36 | public string ThisIsAWriteOnlyString { set { _thisIsAString = value; }} 37 | 38 | public int ThisIsAProperty { get;set;} 39 | 40 | public ITest GetITest { get; } 41 | 42 | public TestClass ThisClass {get;set;} 43 | } 44 | """ 45 | And I set my test framework to 'XUnit' 46 | And I set my mock framework to 'RhinoMocks' 47 | When I generate unit tests for the class using strategy 'CanConstructMultiConstructorGenerationStrategy' 48 | Then I expect a method called 'CanConstruct' 49 | And I expect it to contain the statement 'var instance = new TestClass(_stringProp, _iTest);' 50 | And I expect it to contain the statement 'instance = new TestClass(_nullableIntProp, _iTest);' 51 | And I expect it to contain the statement 'instance = new TestClass(_thisIsAProperty, _iTest);' 52 | And I expect it to contain 3 statements called 'Assert.NotNull(instance);' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Assets/PropertyTesterAssetTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Assets 2 | { 3 | using System; 4 | using NUnit.Framework; 5 | using SentryOne.UnitTestGenerator.Core.Assets; 6 | using SentryOne.UnitTestGenerator.Core.Options; 7 | 8 | [TestFixture] 9 | public class PropertyTesterAssetTests 10 | { 11 | private PropertyTesterAsset _testClass; 12 | 13 | [SetUp] 14 | public void SetUp() 15 | { 16 | _testClass = new PropertyTesterAsset(); 17 | } 18 | 19 | [Test] 20 | public void CanConstruct() 21 | { 22 | var instance = new PropertyTesterAsset(); 23 | Assert.That(instance, Is.Not.Null); 24 | } 25 | 26 | [Test] 27 | [TestCase(TestFrameworkTypes.NUnit2)] 28 | [TestCase(TestFrameworkTypes.NUnit3)] 29 | [TestCase(TestFrameworkTypes.XUnit)] 30 | [TestCase(TestFrameworkTypes.MsTest)] 31 | public void CanCallContent(TestFrameworkTypes frameworkTypes) 32 | { 33 | var targetNamespace = "TestValue927446416"; 34 | var result = _testClass.Content(targetNamespace, frameworkTypes); 35 | Assert.That(result, Contains.Substring(targetNamespace)); 36 | } 37 | 38 | [TestCase(null)] 39 | [TestCase("")] 40 | [TestCase(" ")] 41 | public void CannotCallContentWithInvalidTargetNamespace(string value) 42 | { 43 | Assert.Throws(() => _testClass.Content(value, default(TestFrameworkTypes))); 44 | } 45 | 46 | [Test] 47 | public void CanGetAssetFileName() 48 | { 49 | Assert.That(_testClass.AssetFileName, Is.EqualTo("PropertyTester.cs")); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/ClassLevelGeneration/StringParameterCheckConstructorGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: StringParameterCheckConstructorGeneration 2 | I am checking the String Parameter Check Constructor Generation strategy 3 | 4 | 5 | Scenario: String Parameter Check Constructor Generation 6 | Given I have a class defined as 7 | """ 8 | public class TestClass 9 | { 10 | public TestClass(string stringProp, ITest iTest) 11 | { 12 | 13 | } 14 | 15 | public TestClass(int? nullableIntProp, ITest iTest) 16 | { 17 | 18 | } 19 | 20 | public TestClass(int thisIsAProperty, ITest iTest) 21 | { 22 | 23 | } 24 | 25 | public void ThisIsAMethod(string methodName, int methodValue) 26 | { 27 | System.Console.WriteLine("Testing this"); 28 | } 29 | 30 | public string WillReturnAString() 31 | { 32 | return "Hello"; 33 | } 34 | 35 | private string _thisIsAString = string.Empty; 36 | public string ThisIsAWriteOnlyString { set { _thisIsAString = value; }} 37 | 38 | public int ThisIsAProperty { get;set;} 39 | 40 | public ITest GetITest { get; } 41 | 42 | public TestClass ThisClass {get;set;} 43 | } 44 | """ 45 | And I set my test framework to 'MS Test' 46 | And I set my mock framework to 'NSubstitute' 47 | When I generate unit tests for the class using strategy 'StringParameterCheckConstructorGenerationStrategy' 48 | Then I expect a method called 'CannotConstructWithInvalidStringProp' 49 | And I expect it to have the attribute 'DataTestMethod' 50 | And I expect it to have the attribute 'DataRow(null)' 51 | And I expect it to have the attribute 'DataRow("")' 52 | And I expect it to have the attribute 'DataRow(" ")' 53 | And I expect it to contain the statement 'Assert.ThrowsException(() => newTestClass(value, default(ITest)));' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Helpers/StringExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Helpers 2 | { 3 | using System.Linq; 4 | using NUnit.Framework; 5 | using SentryOne.UnitTestGenerator.Core.Helpers; 6 | 7 | [TestFixture] 8 | public static class StringExtensionsTests 9 | { 10 | [Test] 11 | public static void CanCallToCamelCase() 12 | { 13 | Assert.That("TestValue541057933".ToCamelCase(), Is.EqualTo("testValue541057933")); 14 | Assert.That("testValue541057933".ToCamelCase(), Is.EqualTo("testValue541057933")); 15 | Assert.That("T".ToCamelCase(), Is.EqualTo("t")); 16 | Assert.That("t".ToCamelCase(), Is.EqualTo("t")); 17 | Assert.That(string.Empty.ToCamelCase(), Is.EqualTo(string.Empty)); 18 | } 19 | 20 | [Test] 21 | public static void CanCallToPascalCase() 22 | { 23 | Assert.That("TestValue541057933".ToPascalCase(), Is.EqualTo("TestValue541057933")); 24 | Assert.That("testValue541057933".ToPascalCase(), Is.EqualTo("TestValue541057933")); 25 | Assert.That("T".ToPascalCase(), Is.EqualTo("T")); 26 | Assert.That("t".ToPascalCase(), Is.EqualTo("T")); 27 | Assert.That(string.Empty.ToPascalCase(), Is.EqualTo(string.Empty)); 28 | } 29 | 30 | [Test] 31 | public static void CanCallLines() 32 | { 33 | var input = "Test\rValue\nOne"; 34 | var result = input.Lines(); 35 | Assert.That(result.SequenceEqual(new[] { "Test", "Value", "One" })); 36 | } 37 | 38 | [TestCase(null)] 39 | [TestCase("")] 40 | public static void CanCallLinesWithInvalidInput(string value) 41 | { 42 | Assert.That(value.Lines(), Is.Empty); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Options/UnitTestGeneratorOptionsFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Options 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using EditorConfig.Core; 7 | 8 | public static class UnitTestGeneratorOptionsFactory 9 | { 10 | public static IUnitTestGeneratorOptions Create(string solutionFilePath, IGenerationOptions generationOptions, IVersioningOptions versioningOptions) 11 | { 12 | if (generationOptions == null) 13 | { 14 | throw new ArgumentNullException(nameof(generationOptions)); 15 | } 16 | 17 | if (versioningOptions == null) 18 | { 19 | throw new ArgumentNullException(nameof(versioningOptions)); 20 | } 21 | 22 | var mutableGenerationOptions = new MutableGenerationOptions(generationOptions); 23 | var mutableVersioningOptions = new MutableVersioningOptions(versioningOptions); 24 | 25 | if (!string.IsNullOrWhiteSpace(solutionFilePath)) 26 | { 27 | var allFiles = new EditorConfigParser(".unitTestGeneratorConfig").GetConfigurationFilesTillRoot(solutionFilePath); 28 | var allProperties = allFiles.SelectMany(x => x.Sections).SelectMany(x => x); 29 | var properties = new Dictionary(); 30 | foreach (var pair in allProperties) 31 | { 32 | properties[pair.Key] = pair.Value; 33 | } 34 | 35 | properties.ApplyTo(mutableGenerationOptions); 36 | properties.ApplyTo(mutableVersioningOptions); 37 | } 38 | 39 | return new UnitTestGeneratorOptions(mutableGenerationOptions, mutableVersioningOptions); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Frameworks/ITestFramework.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Frameworks 2 | { 3 | using System.Collections.Generic; 4 | using Microsoft.CodeAnalysis.CSharp.Syntax; 5 | using SentryOne.UnitTestGenerator.Core.Models; 6 | using SentryOne.UnitTestGenerator.Core.Options; 7 | 8 | public interface ITestFramework 9 | { 10 | bool SupportsStaticTestClasses { get; } 11 | 12 | bool AssertThrowsAsyncIsAwaitable { get; } 13 | 14 | AttributeSyntax SingleThreadedApartmentAttribute { get; } 15 | 16 | string TestClassAttribute { get; } 17 | 18 | StatementSyntax AssertEqual(ExpressionSyntax actual, ExpressionSyntax expected); 19 | 20 | StatementSyntax AssertFail(string message); 21 | 22 | StatementSyntax AssertGreaterThan(ExpressionSyntax actual, ExpressionSyntax expected); 23 | 24 | StatementSyntax AssertIsInstanceOf(ExpressionSyntax value, TypeSyntax type); 25 | 26 | StatementSyntax AssertLessThan(ExpressionSyntax actual, ExpressionSyntax expected); 27 | 28 | StatementSyntax AssertNotNull(ExpressionSyntax value); 29 | 30 | StatementSyntax AssertThrows(TypeSyntax exceptionType, ExpressionSyntax methodCall); 31 | 32 | StatementSyntax AssertThrowsAsync(TypeSyntax exceptionType, ExpressionSyntax methodCall); 33 | 34 | BaseMethodDeclarationSyntax CreateSetupMethod(string targetTypeName); 35 | 36 | MethodDeclarationSyntax CreateTestCaseMethod(string name, bool isAsync, bool isStatic, TypeSyntax valueType, IEnumerable testValues); 37 | 38 | MethodDeclarationSyntax CreateTestMethod(string name, bool isAsync, bool isStatic); 39 | 40 | IEnumerable GetUsings(); 41 | 42 | IEnumerable ReferencedNugetPackages(IVersioningOptions options); 43 | } 44 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Models/NugetPackageReferenceTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Models 2 | { 3 | using System; 4 | using NUnit.Framework; 5 | using SentryOne.UnitTestGenerator.Core.Models; 6 | 7 | [TestFixture] 8 | public class NugetPackageReferenceTests 9 | { 10 | private NugetPackageReference _testClass; 11 | private string _name; 12 | private string _version; 13 | 14 | [SetUp] 15 | public void SetUp() 16 | { 17 | _name = "TestValue371271030"; 18 | _version = "TestValue67196216"; 19 | _testClass = new NugetPackageReference(_name, _version); 20 | } 21 | 22 | [Test] 23 | public void CanConstruct() 24 | { 25 | var instance = new NugetPackageReference(_name, _version); 26 | Assert.That(instance, Is.Not.Null); 27 | } 28 | 29 | [TestCase(null)] 30 | [TestCase("")] 31 | [TestCase(" ")] 32 | public void CannotConstructWithInvalidName(string value) 33 | { 34 | Assert.Throws(() => new NugetPackageReference(value, "TestValue1390261023")); 35 | } 36 | 37 | [TestCase(null)] 38 | [TestCase("")] 39 | [TestCase(" ")] 40 | public void CanConstructWithInvalidVersion(string value) 41 | { 42 | Assert.That(new NugetPackageReference("TestValue1554148770", value).Version, Is.Null); 43 | } 44 | 45 | [Test] 46 | public void NameIsInitializedCorrectly() 47 | { 48 | Assert.That(_testClass.Name, Is.EqualTo(_name)); 49 | } 50 | 51 | [Test] 52 | public void VersionIsInitializedCorrectly() 53 | { 54 | Assert.That(_testClass.Version, Is.EqualTo(_version)); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/PropertyChangeTestFile.txt: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows.Media; 3 | 4 | namespace AssemblyCore 5 | { 6 | public class PropertyChange : INotifyPropertyChanged 7 | { 8 | private string name; 9 | 10 | public string Name 11 | { 12 | get { return name; } 13 | set 14 | { 15 | name = value; 16 | OnPropertChanged("Name"); 17 | OnPropertChanged("FullName"); 18 | } 19 | } 20 | 21 | private string lastname; 22 | 23 | public string LastName 24 | { 25 | get { return lastname; } 26 | set 27 | { 28 | lastname = value; 29 | OnPropertChanged("LastName"); 30 | OnPropertChanged("FullName"); 31 | } 32 | } 33 | 34 | private string fullName; 35 | 36 | public string FullName 37 | { 38 | get { return fullName; } 39 | set 40 | { 41 | fullName = value; 42 | OnPropertChanged("FullName"); 43 | } 44 | } 45 | 46 | private Color color; 47 | 48 | public Color Color 49 | { 50 | get { return color; } 51 | set 52 | { 53 | color = value; 54 | OnPropertChanged("Color"); 55 | } 56 | } 57 | 58 | public PropertyChange() 59 | { 60 | 61 | } 62 | 63 | public event PropertyChangedEventHandler PropertyChanged; 64 | 65 | private void OnPropertChanged(string propertyName) 66 | { 67 | if (PropertyChanged != null) 68 | PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Helpers/GenerationContextTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Helpers 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Microsoft.CodeAnalysis; 7 | using NUnit.Framework; 8 | using SentryOne.UnitTestGenerator.Core.Helpers; 9 | 10 | [TestFixture] 11 | public class GenerationContextTests 12 | { 13 | private GenerationContext _testClass; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _testClass = new GenerationContext(); 19 | } 20 | 21 | [Test] 22 | public void CanConstruct() 23 | { 24 | var instance = new GenerationContext(); 25 | Assert.That(instance, Is.Not.Null); 26 | } 27 | 28 | [Test] 29 | public void CanCallAddEmittedType() 30 | { 31 | var typeInfo = TestSemanticModelFactory.Model.GetDeclaredSymbol(TestSemanticModelFactory.Class) as ITypeSymbol; 32 | _testClass.AddEmittedType(typeInfo); 33 | Assert.That(_testClass.EmittedTypes.Contains(typeInfo)); 34 | } 35 | 36 | [Test] 37 | public void CannotCallAddEmittedTypeWithNullTypeInfo() 38 | { 39 | Assert.Throws(() => _testClass.AddEmittedType(default(ITypeSymbol))); 40 | } 41 | 42 | [Test] 43 | public void CanGetEmittedTypes() 44 | { 45 | Assert.That(_testClass.EmittedTypes, Is.InstanceOf>()); 46 | } 47 | 48 | [Test] 49 | public void CanSetAndGetMocksUsed() 50 | { 51 | Assert.That(_testClass.MocksUsed, Is.InstanceOf()); 52 | _testClass.MocksUsed = true; 53 | Assert.That(_testClass.MocksUsed, Is.EqualTo(true)); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/ClassGeneration/StaticClassGenerationStrategyTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.ClassGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Models; 8 | using SentryOne.UnitTestGenerator.Core.Strategies.ClassGeneration; 9 | 10 | [TestFixture] 11 | public class StaticClassGenerationStrategyTests 12 | { 13 | private StaticClassGenerationStrategy _testClass; 14 | private IFrameworkSet _frameworkSet; 15 | 16 | [SetUp] 17 | public void SetUp() 18 | { 19 | _frameworkSet = Substitute.For(); 20 | _testClass = new StaticClassGenerationStrategy(_frameworkSet); 21 | } 22 | 23 | [Test] 24 | public void CanConstruct() 25 | { 26 | var instance = new StaticClassGenerationStrategy(_frameworkSet); 27 | Assert.That(instance, Is.Not.Null); 28 | } 29 | 30 | [Test] 31 | public void CannotConstructWithNullFrameworkSet() 32 | { 33 | Assert.Throws(() => new StaticClassGenerationStrategy(default(IFrameworkSet))); 34 | } 35 | 36 | [Test] 37 | public void CannotCallCanHandleWithNullModel() 38 | { 39 | Assert.Throws(() => _testClass.CanHandle(default(ClassModel))); 40 | } 41 | 42 | [Test] 43 | public void CannotCallCreateWithNullModel() 44 | { 45 | Assert.Throws(() => _testClass.Create(default(ClassModel))); 46 | } 47 | 48 | [Test] 49 | public void CanGetPriority() 50 | { 51 | Assert.That(_testClass.Priority, Is.EqualTo(1)); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/ClassGeneration/AbstractClassGenerationStrategyTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.ClassGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Models; 8 | using SentryOne.UnitTestGenerator.Core.Strategies.ClassGeneration; 9 | 10 | [TestFixture] 11 | public class AbstractClassGenerationStrategyTests 12 | { 13 | private AbstractClassGenerationStrategy _testClass; 14 | private IFrameworkSet _frameworkSet; 15 | 16 | [SetUp] 17 | public void SetUp() 18 | { 19 | _frameworkSet = Substitute.For(); 20 | _testClass = new AbstractClassGenerationStrategy(_frameworkSet); 21 | } 22 | 23 | [Test] 24 | public void CanConstruct() 25 | { 26 | var instance = new AbstractClassGenerationStrategy(_frameworkSet); 27 | Assert.That(instance, Is.Not.Null); 28 | } 29 | 30 | [Test] 31 | public void CannotConstructWithNullFrameworkSet() 32 | { 33 | Assert.Throws(() => new AbstractClassGenerationStrategy(default(IFrameworkSet))); 34 | } 35 | 36 | [Test] 37 | public void CannotCallCanHandleWithNullModel() 38 | { 39 | Assert.Throws(() => _testClass.CanHandle(default(ClassModel))); 40 | } 41 | 42 | [Test] 43 | public void CannotCallCreateWithNullModel() 44 | { 45 | Assert.Throws(() => _testClass.Create(default(ClassModel))); 46 | } 47 | 48 | [Test] 49 | public void CanGetPriority() 50 | { 51 | Assert.That(_testClass.Priority, Is.EqualTo(1)); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/ClassGeneration/StandardClassGenerationStrategyTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.ClassGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Models; 8 | using SentryOne.UnitTestGenerator.Core.Strategies.ClassGeneration; 9 | 10 | [TestFixture] 11 | public class StandardClassGenerationStrategyTests 12 | { 13 | private StandardClassGenerationStrategy _testClass; 14 | private IFrameworkSet _frameworkSet; 15 | 16 | [SetUp] 17 | public void SetUp() 18 | { 19 | _frameworkSet = Substitute.For(); 20 | _testClass = new StandardClassGenerationStrategy(_frameworkSet); 21 | } 22 | 23 | [Test] 24 | public void CanConstruct() 25 | { 26 | var instance = new StandardClassGenerationStrategy(_frameworkSet); 27 | Assert.That(instance, Is.Not.Null); 28 | } 29 | 30 | [Test] 31 | public void CannotConstructWithNullFrameworkSet() 32 | { 33 | Assert.Throws(() => new StandardClassGenerationStrategy(default(IFrameworkSet))); 34 | } 35 | 36 | [Test] 37 | public void CannotCallCanHandleWithNullModel() 38 | { 39 | Assert.Throws(() => _testClass.CanHandle(default(ClassModel))); 40 | } 41 | 42 | [Test] 43 | public void CannotCallCreateWithNullModel() 44 | { 45 | Assert.Throws(() => _testClass.Create(default(ClassModel))); 46 | } 47 | 48 | [Test] 49 | public void CanGetPriority() 50 | { 51 | Assert.That(_testClass.Priority, Is.EqualTo(1)); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/GenericCollection.txt: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Collections.Concurrent; 5 | using System.Linq; 6 | 7 | namespace QueueCrash 8 | { 9 | public class DelayedConcurrentQueue : IProducerConsumerCollection 10 | { 11 | private readonly TimeSpan _delay; 12 | private readonly ConcurrentQueue> _internalQueue; 13 | private int _count; 14 | private bool _isSynchronized; 15 | private object _syncRoot; 16 | 17 | public void CopyTo(Array destinationArray, int index) 18 | { 19 | if (destinationArray.Length - index <= _internalQueue.Count) 20 | { 21 | throw new 22 | ArgumentException("Destination destinationArray was not long enough. Check the destination index, length, and the destinationArray's lower bounds. (Parameter 'destinationArray')"); 23 | } 24 | 25 | var source = _internalQueue.Select(t => t.Item2).ToArray(); 26 | Array.Copy(source, destinationArray, index); 27 | } 28 | 29 | int ICollection.Count => _count; 30 | 31 | bool ICollection.IsSynchronized => _isSynchronized; 32 | 33 | object ICollection.SyncRoot => _syncRoot; 34 | 35 | IEnumerator IEnumerable.GetEnumerator() 36 | { 37 | throw new NotImplementedException(); 38 | } 39 | 40 | IEnumerator IEnumerable.GetEnumerator() 41 | { 42 | throw new NotImplementedException(); 43 | } 44 | 45 | void IProducerConsumerCollection.CopyTo(T[] array, int index) 46 | { 47 | throw new NotImplementedException(); 48 | } 49 | 50 | T[] IProducerConsumerCollection.ToArray() 51 | { 52 | throw new NotImplementedException(); 53 | } 54 | 55 | bool IProducerConsumerCollection.TryAdd(T item) 56 | { 57 | throw new NotImplementedException(); 58 | } 59 | 60 | bool IProducerConsumerCollection.TryTake(out T item) 61 | { 62 | throw new NotImplementedException(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/MockGeneration/MockGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: Mock Generation 2 | I am checking to see if different Mock types work 3 | 4 | Scenario Outline: Mock Generation Test 5 | Given I have a class defined as 6 | """ 7 | namespace TestNamespace.SubNameSpace 8 | { 9 | 10 | public interface ITest 11 | { 12 | int ThisIsAProperty {get;set;} 13 | } 14 | 15 | public class TestClass 16 | { 17 | public TestClass(string stringProp, ITest iTest) 18 | { 19 | 20 | } 21 | 22 | public TestClass(int? nullableIntProp, ITest iTest) 23 | { 24 | 25 | } 26 | 27 | public TestClass(int thisIsAProperty, ITest iTest) 28 | { 29 | 30 | } 31 | public void ThisIsAMethod(string methodName, int methodValue) 32 | { 33 | System.Console.WriteLine("Testing this"); 34 | } 35 | 36 | public string WillReturnAString() 37 | { 38 | return "Hello"; 39 | } 40 | 41 | private string _thisIsAString = string.Empty; 42 | public string ThisIsAWriteOnlyString { set { _thisIsAString = value; }} 43 | 44 | public int ThisIsAProperty { get;set;} 45 | 46 | public ITest GetITest { get; } 47 | 48 | public TestClass ThisClass {get;set;} 49 | } 50 | } 51 | """ 52 | And I set my test framework to 'NUnit3' 53 | And I set my mock framework to '' 54 | When I generate tests for the class using strategy 'StandardClassGenerationStrategy' 55 | Then I expect the method 'SetUp' 56 | And I expect it to contain the statement '' 57 | 58 | Examples: 59 | | mock | statement | 60 | | FakeItEasy | _iTest = A.Fake(); | 61 | | Moq | _iTest = new Mock().Object; | 62 | | NSubstitute | _iTest = Substitute.For(); | 63 | | RhinoMocks | _iTest = MockRepository.GenerateStub(); | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/IndexerGeneration/ReadWriteIndexGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: ReadWriteIndexerGeneration 2 | I am checking the Read Write Indexer Generation strategy 3 | 4 | 5 | Scenario: Read Write Indexer Generation 6 | Given I have a class defined as 7 | """ 8 | using System; 9 | using System.Drawing; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | using System.Windows; 14 | using System.Collections; 15 | using System.Collections.Generic; 16 | 17 | namespace WindowsFormsApp1 18 | { 19 | public class Form1 20 | { 21 | public string this[string cookieName, Guid cookieValue, DateTime cookieExpirationTime] 22 | { 23 | set 24 | { 25 | } 26 | } 27 | 28 | public string this[string cookieName] 29 | { 30 | get { 31 | return "hello"; 32 | } 33 | } 34 | 35 | public string this[string cookieName, int cookieId] 36 | { 37 | get { 38 | return "hello"; 39 | } 40 | set { 41 | } 42 | } 43 | } 44 | } 45 | """ 46 | And I set my test framework to 'NUnit3' 47 | And I set my mock framework to 'FakeItEasy' 48 | When I generate tests for the indexer using the strategy 'ReadWriteIndexerGenerationStrategy' 49 | Then I expect a method called 'CanSetAndGetIndexerForStringAndInt' 50 | And I expect it to have the attribute 'Test' 51 | And I expect it to contain the variable 'testValue' 52 | And I expect it to contain a statement like 'Assert.That(_testClass[{{{AnyString}}}, {{{AnyInteger}}}], Is.InstanceOf());' 53 | And I expect it to contain a statement like 'Assert.That(_testClass[{{{AnyString}}}, {{{AnyInteger}}}], Is.EqualTo(testValue));' 54 | And I expect it to contain a statement like '_testClass[{{{AnyString}}}, {{{AnyInteger}}}] = testValue;' 55 | And I expect no method with a name like '.*StringAndGuidAndDateTime.*' 56 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Frameworks/Test/NUnit3TestFramework.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Frameworks.Test 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.CodeAnalysis.CSharp; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using SentryOne.UnitTestGenerator.Core.Helpers; 8 | using SentryOne.UnitTestGenerator.Core.Models; 9 | using SentryOne.UnitTestGenerator.Core.Options; 10 | using SentryOne.UnitTestGenerator.Core.Resources; 11 | 12 | public class NUnit3TestFramework : NUnitTestFramework 13 | { 14 | private bool _requiresSystemThreading; 15 | 16 | public override AttributeSyntax SingleThreadedApartmentAttribute 17 | { 18 | get 19 | { 20 | _requiresSystemThreading = true; 21 | return Generate.Attribute("Apartment", SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("ApartmentState"), SyntaxFactory.IdentifierName("STA"))); 22 | } 23 | } 24 | 25 | public override IEnumerable GetUsings() 26 | { 27 | foreach (var usingDirectiveSyntax in base.GetUsings()) 28 | { 29 | yield return usingDirectiveSyntax; 30 | } 31 | 32 | if (_requiresSystemThreading) 33 | { 34 | yield return SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(Strings.NUnit3TestFramework_GetUsings_System_Threading)); 35 | } 36 | } 37 | 38 | public override IEnumerable ReferencedNugetPackages(IVersioningOptions options) 39 | { 40 | if (options == null) 41 | { 42 | throw new ArgumentNullException(nameof(options)); 43 | } 44 | 45 | yield return new NugetPackageReference("NUnit", options.NUnit3NugetPackageVersion); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SentryOne Unit Test Generator 6 | SentryOne Unit Test Generator generates boiler plate unit test code for existing classes. 7 | Resources\UnitTestGeneratorPackage.png 8 | Resources\UnitTestGeneratorPackage.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/ConstructorSamplesTestFile.txt: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace AssemblyCore 6 | { 7 | public class ConstructorSamples 8 | { 9 | public string ArgumentOne { get; } 10 | public string ArgumentTwo { get; } 11 | public string NamedArgument { get; } 12 | public string OptionalArgument { get; } 13 | public string[] Args { get; } 14 | public int[] ArgInt { get; } 15 | public string ArguemntOne { get; } 16 | public string ArguemntPrivateSet { get;private set; } 17 | 18 | public ConstructorSamples() 19 | { 20 | 21 | } 22 | 23 | public ConstructorSamples(params string[] args) 24 | { 25 | Args = args; 26 | } 27 | 28 | public ConstructorSamples(params int[] argInt) 29 | { 30 | ArgInt = argInt; 31 | } 32 | 33 | public ConstructorSamples(string argumentOne, string argumentTwo) 34 | { 35 | ArgumentOne = argumentOne; 36 | ArgumentTwo = argumentTwo; 37 | } 38 | 39 | 40 | public ConstructorSamples(string argumentOne, string argumentTwo, string optionalArgument = "Optional_Argument") 41 | { 42 | ArgumentOne = argumentOne; 43 | ArgumentTwo = argumentTwo; 44 | OptionalArgument = optionalArgument; 45 | } 46 | 47 | public ConstructorSamples(string argumentOne, string argumentTwo, string namedArgument, string optionalArgument = "Optional_Argument") 48 | { 49 | ArgumentOne = argumentOne; 50 | ArgumentTwo = argumentTwo; 51 | NamedArgument = namedArgument; 52 | OptionalArgument = optionalArgument; 53 | } 54 | 55 | public ConstructorSamples(string arguemntPrivateSet) 56 | { 57 | ArguemntPrivateSet = arguemntPrivateSet; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Helpers/StandardReferenceHelperTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Helpers 2 | { 3 | using System; 4 | using System.Linq; 5 | using NSubstitute; 6 | using NUnit.Framework; 7 | using SentryOne.UnitTestGenerator.Core.Helpers; 8 | using SentryOne.UnitTestGenerator.Core.Options; 9 | 10 | [TestFixture] 11 | public static class StandardReferenceHelperTests 12 | { 13 | [Test] 14 | [TestCase(TestFrameworkTypes.MsTest, MockingFrameworkType.FakeItEasy, "MSTest.TestFramework", "FakeItEasy")] 15 | [TestCase(TestFrameworkTypes.NUnit2, MockingFrameworkType.Moq, "NUnit", "Moq")] 16 | [TestCase(TestFrameworkTypes.NUnit3, MockingFrameworkType.NSubstitute, "NUnit", "NSubstitute")] 17 | [TestCase(TestFrameworkTypes.XUnit, MockingFrameworkType.RhinoMocks, "xunit", "RhinoMocks")] 18 | public static void CanCallGetReferencedAssemblies(TestFrameworkTypes testFramework, MockingFrameworkType mockingFramework, string expectedTestFramework, string expectedMockingFramework) 19 | { 20 | var options = Substitute.For(); 21 | options.GenerationOptions.TestTypeNaming.Returns("{0}Tests"); 22 | options.GenerationOptions.FrameworkType.Returns(testFramework); 23 | options.GenerationOptions.MockingFrameworkType.Returns(mockingFramework); 24 | var result = StandardReferenceHelper.GetReferencedNugetPackages(options); 25 | Assert.That(result.Any(x => string.Equals(x.Name, expectedTestFramework, StringComparison.OrdinalIgnoreCase))); 26 | Assert.That(result.Any(x => string.Equals(x.Name, expectedMockingFramework, StringComparison.OrdinalIgnoreCase))); 27 | } 28 | 29 | [Test] 30 | public static void CannotCallGetReferencedAssembliesWithNullOptions() 31 | { 32 | Assert.Throws(() => StandardReferenceHelper.GetReferencedNugetPackages(default(IUnitTestGeneratorOptions))); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Strategies/InterfaceGeneration/EnumerableGenerationStrategyTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Strategies.InterfaceGeneration 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Frameworks; 7 | using SentryOne.UnitTestGenerator.Core.Models; 8 | using SentryOne.UnitTestGenerator.Core.Strategies.InterfaceGeneration; 9 | 10 | [TestFixture] 11 | public class EnumerableGenerationStrategyTests 12 | { 13 | private EnumerableGenerationStrategy _testClass; 14 | private IFrameworkSet _frameworkSet; 15 | 16 | [SetUp] 17 | public void SetUp() 18 | { 19 | _frameworkSet = Substitute.For(); 20 | _testClass = new EnumerableGenerationStrategy(_frameworkSet); 21 | } 22 | 23 | [Test] 24 | public void CanConstruct() 25 | { 26 | var instance = new EnumerableGenerationStrategy(_frameworkSet); 27 | Assert.That(instance, Is.Not.Null); 28 | } 29 | 30 | [Test] 31 | public void CannotConstructWithNullFrameworkSet() 32 | { 33 | Assert.Throws(() => new EnumerableGenerationStrategy(default(IFrameworkSet))); 34 | } 35 | 36 | [Test] 37 | public void CannotCallCreateWithNullClassModel() 38 | { 39 | Assert.Throws(() => _testClass.Create(default(ClassModel), ClassModelProvider.Instance).Consume()); 40 | } 41 | 42 | [Test] 43 | public void CannotCallCreateWithNullModel() 44 | { 45 | Assert.Throws(() => _testClass.Create(ClassModelProvider.Instance, default(ClassModel)).Consume()); 46 | } 47 | 48 | [Test] 49 | public void CanGetSupportedInterfaceName() 50 | { 51 | Assert.That(_testClass.SupportedInterfaceName, Is.EqualTo("System.Collections.Generic.IEnumerable")); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Options/UnitTestGeneratorOptionsTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Options 2 | { 3 | using System; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | using SentryOne.UnitTestGenerator.Core.Options; 7 | 8 | [TestFixture] 9 | public class UnitTestGeneratorOptionsTests 10 | { 11 | private UnitTestGeneratorOptions _testClass; 12 | private IGenerationOptions _generationOptions; 13 | private IVersioningOptions _versioningOptions; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _generationOptions = Substitute.For(); 19 | _versioningOptions = Substitute.For(); 20 | _testClass = new UnitTestGeneratorOptions(_generationOptions, _versioningOptions); 21 | } 22 | 23 | [Test] 24 | public void CanConstruct() 25 | { 26 | var instance = new UnitTestGeneratorOptions(_generationOptions, _versioningOptions); 27 | Assert.That(instance, Is.Not.Null); 28 | } 29 | 30 | [Test] 31 | public void CannotConstructWithNullGenerationOptions() 32 | { 33 | Assert.Throws(() => new UnitTestGeneratorOptions(default(IGenerationOptions), Substitute.For())); 34 | } 35 | 36 | [Test] 37 | public void CannotConstructWithNullVersioningOptions() 38 | { 39 | Assert.Throws(() => new UnitTestGeneratorOptions(Substitute.For(), default(IVersioningOptions))); 40 | } 41 | 42 | [Test] 43 | public void GenerationOptionsIsInitializedCorrectly() 44 | { 45 | Assert.That(_testClass.GenerationOptions, Is.EqualTo(_generationOptions)); 46 | } 47 | 48 | [Test] 49 | public void VersioningOptionsIsInitializedCorrectly() 50 | { 51 | Assert.That(_testClass.VersioningOptions, Is.EqualTo(_versioningOptions)); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator/Helper/OutputWindowMessageLogger.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Helper 2 | { 3 | using System; 4 | using Microsoft.VisualStudio; 5 | using Microsoft.VisualStudio.Shell; 6 | using Microsoft.VisualStudio.Shell.Interop; 7 | using SentryOne.UnitTestGenerator.Core.Helpers; 8 | 9 | public sealed class OutputWindowMessageLogger : IMessageLogger 10 | { 11 | private IVsOutputWindow _outputWindow; 12 | private IVsOutputWindowPane _testingOutputPane; 13 | 14 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "External exception types unknown")] 15 | public void Initialize() 16 | { 17 | ThreadHelper.ThrowIfNotOnUIThread(); 18 | try 19 | { 20 | _outputWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow; 21 | } 22 | catch (Exception) 23 | { 24 | _outputWindow = null; 25 | } 26 | 27 | if (_outputWindow == null) 28 | { 29 | return; 30 | } 31 | 32 | var generatorOutputWindowPaneId = new Guid("D6002C1E-2DB8-4C9D-996D-A29364FB8DAC"); 33 | 34 | ErrorHandler.ThrowOnFailure(_outputWindow.CreatePane(ref generatorOutputWindowPaneId, "Unit Test Generator", 0, 1)); 35 | ErrorHandler.ThrowOnFailure(_outputWindow.GetPane(ref generatorOutputWindowPaneId, out _testingOutputPane)); 36 | 37 | if (_testingOutputPane != null) 38 | { 39 | ErrorHandler.ThrowOnFailure(_testingOutputPane.Clear()); 40 | ErrorHandler.ThrowOnFailure(_testingOutputPane.Activate()); 41 | } 42 | } 43 | 44 | public void LogMessage(string message) 45 | { 46 | ThreadHelper.ThrowIfNotOnUIThread(); 47 | if (_testingOutputPane != null) 48 | { 49 | ErrorHandler.ThrowOnFailure(_testingOutputPane.OutputStringThreadSafe(message + Environment.NewLine)); 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/Regeneration/Regeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: Regeneration 2 | I am checking that regeneration adds fields 3 | 4 | Scenario: Regeneration of a constructor 5 | Given I have a class defined as 6 | """ 7 | namespace TestNamespace 8 | { 9 | public interface ITest 10 | { 11 | int ThisIsAProperty {get;set;} 12 | } 13 | 14 | public interface ITest2 15 | { 16 | int ThisIsAProperty {get;set;} 17 | } 18 | 19 | public class TestClass 20 | { 21 | public TestClass(ITest test, ITest2 otherTest) 22 | { 23 | 24 | } 25 | 26 | public ITest Test { get; } 27 | 28 | public ITest2 OtherTest { get; } 29 | } 30 | } 31 | """ 32 | And an existing test class 33 | """ 34 | namespace TestNamespace.Tests 35 | { 36 | using TestNamespace.SubNameSpace; 37 | using System; 38 | using NUnit.Framework; 39 | using NSubstitute; 40 | 41 | [TestFixture] 42 | public class TestClassTests 43 | { 44 | private TestClass _testClass; 45 | private ITest _test; 46 | 47 | [SetUp] 48 | public void SetUp() 49 | { 50 | _test = Substitute.For(); 51 | _testClass = new TestClass(_test); 52 | } 53 | 54 | [Test] 55 | public void CanConstruct() 56 | { 57 | var instance = new TestClass(_test); 58 | Assert.That(instance, Is.Not.Null); 59 | } 60 | 61 | [Test] 62 | public void CannotConstructWithNullITest() 63 | { 64 | Assert.Throws(() => new TestClass(default(ITest))); 65 | } 66 | 67 | [Test] 68 | public void TestIsInitializedCorrectly() 69 | { 70 | Assert.That(_testClass.Test, Is.EqualTo(_test)); 71 | } 72 | } 73 | } 74 | """ 75 | And I set my test framework to 'NUnit3' 76 | And I set my mock framework to 'NSubstitute' 77 | When I regenerate tests for all constructors 78 | Then I expect a field of type 'ITest2' with name '_otherTest' 79 | And I expect the method 'SetUp' 80 | And I expect it to contain an assignment for '_otherTest' 81 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/ClassGeneration/StandardClassGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: StandardClassGeneration 2 | I am checking the Standard Class Generation strategy 3 | 4 | Scenario: Standard Class Generation 5 | Given I have a class defined as 6 | """ 7 | namespace TestNamespace.SubNameSpace 8 | { 9 | 10 | public interface ITest 11 | { 12 | int ThisIsAProperty {get;set;} 13 | } 14 | 15 | public class TestClass 16 | { 17 | public TestClass(string stringProp, ITest iTest) 18 | { 19 | 20 | } 21 | 22 | public TestClass(int? nullableIntProp, ITest iTest) 23 | { 24 | 25 | } 26 | 27 | public TestClass(int thisIsAProperty, ITest iTest) 28 | { 29 | 30 | } 31 | public void ThisIsAMethod(string methodName, int methodValue) 32 | { 33 | System.Console.WriteLine("Testing this"); 34 | } 35 | 36 | public string WillReturnAString() 37 | { 38 | return "Hello"; 39 | } 40 | 41 | private string _thisIsAString = string.Empty; 42 | public string ThisIsAWriteOnlyString { set { _thisIsAString = value; }} 43 | 44 | public int ThisIsAProperty { get;set;} 45 | 46 | public ITest GetITest { get; } 47 | 48 | public TestClass ThisClass {get;set;} 49 | } 50 | } 51 | """ 52 | And I set my test framework to 'NUnit3' 53 | And I set my mock framework to 'NSubstitute' 54 | When I generate tests for the class using strategy 'StandardClassGenerationStrategy' 55 | Then I expect a field of type 'string' with name '_stringProp' 56 | And I expect a field of type 'int' with name '_thisIsAProperty' 57 | And I expect a field of type 'int?' with name '_nullableIntProp' 58 | And I expect a field of type 'ITest' with name '_iTest' 59 | And I expect a field of type 'TestClass' with name '_testClass' 60 | And I expect the method 'SetUp' 61 | And I expect it to have the attribute 'SetUp' 62 | And I expect it to contain an assignment for '_stringProp' 63 | And I expect it to contain an assignment for '_thisIsAProperty' 64 | And I expect it to contain an assignment for '_nullableIntProp' 65 | And I expect it to contain an assignment for '_iTest' 66 | And I expect it to contain an assignment for '_testClass' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Specs/Strategies/PropertyGenerator/ReadOnlyPropertyGeneration.feature: -------------------------------------------------------------------------------- 1 | Feature: ReadOnlyPropertyGeneration 2 | I am checking the Read Only Property Generation strategy 3 | 4 | 5 | Scenario: Read Only Property Generation 6 | Given I have a class defined as 7 | """ 8 | namespace SentryOne.Document.Web.Services.Workflow.BackgroundTaskExecutors.AzureFunctions 9 | { 10 | using System; 11 | 12 | public abstract class AzureFunctionsBackgroundTaskExecutor 13 | { 14 | public AzureFunctionsBackgroundTaskExecutor() 15 | { 16 | } 17 | 18 | public abstract string SupportedStage { get; } 19 | 20 | public abstract string SupportedStage2 { get; } 21 | 22 | protected abstract string ProtectedProperty { get; } 23 | 24 | public string SomeOtherProperty { get; set; } 25 | 26 | public abstract string CreateMessage(string item, long tenantId); 27 | 28 | protected abstract string CreateMessage2(string item, long tenantId); 29 | } 30 | 31 | public abstract class AzureFunctionsBackgroundTaskExecutor2 : AzureFunctionsBackgroundTaskExecutor 32 | { 33 | public AzureFunctionsBackgroundTaskExecutor2() 34 | { 35 | } 36 | 37 | public override string SupportedStage => "hello"; 38 | 39 | public override string CreateMessage(string item, long tenantId) { return "hello"; } 40 | } 41 | } 42 | """ 43 | And I set my test framework to 'NUnit3' 44 | And I set my mock framework to 'FakeItEasy' 45 | When I generate tests for the property using the strategy 'ReadOnlyPropertyGenerationStrategy' 46 | Then I expect a method called 'CanGetSupportedStage' 47 | And I expect it to contain the statement 'Assert.That(_testClass.SupportedStage,Is.InstanceOf());' 48 | And I expect it to contain the statement 'Assert.Fail("Create or modify test");' 49 | And I expect a method called 'CanGetSupportedStage2' 50 | And I expect it to have the attribute 'Test' 51 | And I expect a method called 'CanGetProtectedProperty' 52 | And I expect it to contain the statement 'Assert.That(_testClass.ProtectedProperty, Is.InstanceOf());' 53 | And I expect it to contain the statement 'Assert.Fail("Create or modify test");' 54 | And I expect no method with a name like '.*SomeOtherProperty.*' -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Resources/SemanticVersion.txt: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System; 4 | using System.Text.RegularExpressions; 5 | 6 | public class SemanticVersion 7 | { 8 | private const RegexOptions Flags = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture; 9 | private static readonly Regex SemanticVersionRegex = new Regex(@"^(?\d+(\s*\.\s*\d+){0,3})(?-[a-z][0-9a-z-]*)?$", Flags); 10 | 11 | private SemanticVersion(Version version, string specialVersion) 12 | { 13 | _version = new Version(version.Major, version.Minor, Math.Max(version.Build, 0), Math.Max(version.Revision, 0)); 14 | _extension = specialVersion ?? string.Empty; 15 | } 16 | 17 | private readonly Version _version; 18 | private readonly string _extension; 19 | 20 | public static SemanticVersion Parse(string version) 21 | { 22 | if (string.IsNullOrWhiteSpace(version)) 23 | { 24 | throw new FormatException(); 25 | } 26 | 27 | var match = SemanticVersionRegex.Match(version.Trim()); 28 | if (!match.Success || !Version.TryParse(match.Groups["Version"].Value, out var versionValue)) 29 | { 30 | throw new FormatException(); 31 | } 32 | 33 | return new SemanticVersion(versionValue, match.Groups["Release"].Value.TrimStart('-')); 34 | } 35 | 36 | public bool IsNewerThan(SemanticVersion other) 37 | { 38 | if (other == null) 39 | { 40 | return true; 41 | } 42 | 43 | var result = _version.CompareTo(other._version); 44 | 45 | if (result != 0) 46 | { 47 | return result > 0; 48 | } 49 | 50 | if (string.IsNullOrEmpty(other._extension)) 51 | { 52 | return false; 53 | } 54 | 55 | if (string.IsNullOrEmpty(_extension)) 56 | { 57 | return true; 58 | } 59 | 60 | return StringComparer.OrdinalIgnoreCase.Compare(_extension, other._extension) > 0; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core.Tests/Models/PropertyModelTests.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Tests.Models 2 | { 3 | using System; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using NUnit.Framework; 8 | using SentryOne.UnitTestGenerator.Core.Models; 9 | 10 | [TestFixture] 11 | public class PropertyModelTests 12 | { 13 | private PropertyModel _testClass; 14 | private string _name; 15 | private PropertyDeclarationSyntax _node; 16 | private TypeInfo _typeInfo; 17 | 18 | [SetUp] 19 | public void SetUp() 20 | { 21 | _name = "TestValue1619496715"; 22 | _node = TestSemanticModelFactory.Property; 23 | _typeInfo = default(TypeInfo); 24 | _testClass = new PropertyModel(_name, _node, _typeInfo); 25 | } 26 | 27 | [Test] 28 | public void CanConstruct() 29 | { 30 | var instance = new PropertyModel(_name, _node, _typeInfo); 31 | Assert.That(instance, Is.Not.Null); 32 | } 33 | 34 | [Test] 35 | public void CannotConstructWithNullNode() 36 | { 37 | Assert.Throws(() => new PropertyModel("TestValue1565919566", default(PropertyDeclarationSyntax), default(TypeInfo))); 38 | } 39 | 40 | [TestCase(null)] 41 | [TestCase("")] 42 | [TestCase(" ")] 43 | public void CannotConstructWithInvalidName(string value) 44 | { 45 | Assert.Throws(() => new PropertyModel(value, SyntaxFactory.PropertyDeclaration(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword)), "name"), default(TypeInfo))); 46 | } 47 | 48 | [Test] 49 | public void TypeInfoIsInitializedCorrectly() 50 | { 51 | Assert.That(_testClass.TypeInfo, Is.EqualTo(_typeInfo)); 52 | } 53 | 54 | [Test] 55 | public void CanGetHasGet() 56 | { 57 | Assert.That(_testClass.HasGet, Is.True); 58 | } 59 | 60 | [Test] 61 | public void CanGetHasSet() 62 | { 63 | Assert.That(_testClass.HasSet, Is.False); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /src/SentryOne.UnitTestGenerator.Core/Models/SemanticVersion.cs: -------------------------------------------------------------------------------- 1 | namespace SentryOne.UnitTestGenerator.Core.Models 2 | { 3 | using System; 4 | using System.Text.RegularExpressions; 5 | 6 | public class SemanticVersion 7 | { 8 | private const RegexOptions Flags = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture; 9 | private static readonly Regex SemanticVersionRegex = new Regex(@"^(?\d+(\s*\.\s*\d+){0,3})(?-[a-z][0-9a-z-.]*)?$", Flags); 10 | 11 | private readonly string _extension; 12 | 13 | private readonly Version _version; 14 | 15 | private SemanticVersion(Version version, string specialVersion) 16 | { 17 | _version = new Version(version.Major, version.Minor, Math.Max(version.Build, 0), Math.Max(version.Revision, 0)); 18 | _extension = specialVersion ?? string.Empty; 19 | } 20 | 21 | public static SemanticVersion Parse(string version) 22 | { 23 | if (string.IsNullOrWhiteSpace(version)) 24 | { 25 | throw new ArgumentNullException(nameof(version)); 26 | } 27 | 28 | var match = SemanticVersionRegex.Match(version.Trim()); 29 | if (!match.Success || !Version.TryParse(match.Groups["Version"].Value, out var versionValue)) 30 | { 31 | throw new FormatException(); 32 | } 33 | 34 | return new SemanticVersion(versionValue, match.Groups["Release"].Value.TrimStart('-')); 35 | } 36 | 37 | public bool IsNewerThan(SemanticVersion other) 38 | { 39 | if (other == null) 40 | { 41 | return true; 42 | } 43 | 44 | var result = _version.CompareTo(other._version); 45 | 46 | if (result != 0) 47 | { 48 | return result > 0; 49 | } 50 | 51 | if (string.IsNullOrEmpty(other._extension)) 52 | { 53 | return false; 54 | } 55 | 56 | if (string.IsNullOrEmpty(_extension)) 57 | { 58 | return true; 59 | } 60 | 61 | return StringComparer.OrdinalIgnoreCase.Compare(_extension, other._extension) > 0; 62 | } 63 | } 64 | } --------------------------------------------------------------------------------