From fd2219d425e348431e4a371ae746cea5eb94fbec Mon Sep 17 00:00:00 2001 From: Andrei Ivascu <7030530+aivascu@users.noreply.github.com> Date: Mon, 7 Sep 2026 00:31:38 +0300 Subject: [PATCH 1/5] Upgrade TUnit and harden Auto* data sources, including generic attributes. --- .../AutoArgumentsAttribute.cs | 4 +- .../AutoArgumentsAttribute{T}.cs | 36 +++++ .../AutoClassDataSourceAttribute.cs | 7 +- .../AutoClassDataSourceAttribute{T}.cs | 41 ++++++ .../AutoDataSourceAttribute.cs | 7 +- .../AutoFixture.TUnit.csproj | 2 +- .../AutoMemberDataSourceAttribute.cs | 17 +-- .../AutoMemberDataSourceAttribute{T}.cs | 38 ++++++ .../BaseDataSourceAttribute.cs | 5 +- .../CompositeDataSourceAttribute.cs | 4 +- src/AutoFixture.TUnit/CustomizeAttribute.cs | 4 +- src/AutoFixture.TUnit/FavorArraysAttribute.cs | 4 +- .../FavorEnumerablesAttribute.cs | 4 +- src/AutoFixture.TUnit/FavorListsAttribute.cs | 4 +- src/AutoFixture.TUnit/FrozenAttribute.cs | 4 +- src/AutoFixture.TUnit/GreedyAttribute.cs | 4 +- src/AutoFixture.TUnit/Internal/Argument.cs | 2 +- .../Internal/AutoDataSource.cs | 16 ++- .../Internal/ClassDataSource.cs | 12 +- .../Internal/CustomizationExtensions.cs | 2 +- .../Internal/CustomizeAttributeComparer.cs | 4 +- .../DataGeneratorMetadataExtensions.cs | 40 +++++- src/AutoFixture.TUnit/Internal/DataSource.cs | 129 +++++++++++++++++- .../Internal/EnumerableExtensions.cs | 8 +- .../Internal/FieldDataSource.cs | 13 +- .../Internal/FrozenValueCustomization.cs | 2 +- src/AutoFixture.TUnit/Internal/IDataSource.cs | 4 +- .../Internal/InlineDataSource.cs | 6 +- .../Internal/MemberDataSource.cs | 11 +- .../Internal/MethodDataSource.cs | 10 +- .../Internal/NullCustomization.cs | 2 +- .../Internal/ParameterFilter.cs | 2 +- .../Internal/ParameterMatcherBuilder.cs | 2 +- .../Internal/PropertyDataSource.cs | 10 +- .../Internal/ReflectionExtensions.cs | 22 --- .../Internal/TestParameter.cs | 2 +- src/AutoFixture.TUnit/Matching.cs | 4 +- src/AutoFixture.TUnit/ModestAttribute.cs | 4 +- .../NoAutoPropertiesAttribute.cs | 4 +- 39 files changed, 359 insertions(+), 137 deletions(-) create mode 100644 src/AutoFixture.TUnit/AutoArgumentsAttribute{T}.cs create mode 100644 src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs create mode 100644 src/AutoFixture.TUnit/AutoMemberDataSourceAttribute{T}.cs delete mode 100644 src/AutoFixture.TUnit/Internal/ReflectionExtensions.cs diff --git a/src/AutoFixture.TUnit/AutoArgumentsAttribute.cs b/src/AutoFixture.TUnit/AutoArgumentsAttribute.cs index 9d41b0b..6093d7e 100644 --- a/src/AutoFixture.TUnit/AutoArgumentsAttribute.cs +++ b/src/AutoFixture.TUnit/AutoArgumentsAttribute.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit; @@ -48,4 +48,4 @@ protected AutoArgumentsAttribute(Func fixtureFactory, params object?[] return new AutoDataSource(this.FixtureFactory, new InlineDataSource(this.Values)) .GetDataRowsAsync(dataGeneratorMetadata); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/AutoArgumentsAttribute{T}.cs b/src/AutoFixture.TUnit/AutoArgumentsAttribute{T}.cs new file mode 100644 index 0000000..1a06bf8 --- /dev/null +++ b/src/AutoFixture.TUnit/AutoArgumentsAttribute{T}.cs @@ -0,0 +1,36 @@ +using System.Diagnostics.CodeAnalysis; + +namespace AutoFixture.TUnit; + +/// +/// Generic form of that supplies a single strongly typed inline value, +/// with remaining parameters filled by AutoFixture. +/// +/// The type of the inline value. +/// +/// Requires C# 11 or later to use the [AutoArguments<T>] attribute syntax. +/// +[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", + Justification = "This attribute is the root of a potential attribute hierarchy.")] +public class AutoArgumentsAttribute : AutoArgumentsAttribute +{ + /// + /// Initializes a new instance of the class. + /// + /// The typed value to pass as the first theory argument. + public AutoArgumentsAttribute(T value) + : base([value]) + { + } + + /// + /// Initializes a new instance of the class + /// with a custom fixture factory. + /// + /// The fixture factory. + /// The typed value to pass as the first theory argument. + protected AutoArgumentsAttribute(Func fixtureFactory, T value) + : base(fixtureFactory, [value]) + { + } +} diff --git a/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs index ff575a7..00d8fbc 100644 --- a/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs +++ b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs @@ -1,11 +1,12 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit; /// /// Provides a data source for a data theory, with the data coming from a class -/// which must implement IEnumerable<object?[]>, +/// that yields test cases in any shape supported by TUnit MethodDataSource +/// (for example IEnumerable<object?[]>, IEnumerable<T>, or tuples), /// combined with auto-generated data specimens generated by AutoFixture. /// [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", @@ -90,4 +91,4 @@ protected AutoClassDataSourceAttribute(Func fixtureFactory, Type sourc return source.GetDataRowsAsync(dataGeneratorMetadata); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs new file mode 100644 index 0000000..b553b37 --- /dev/null +++ b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs @@ -0,0 +1,41 @@ +using System.Diagnostics.CodeAnalysis; + +namespace AutoFixture.TUnit; + +/// +/// Generic form of that takes the data provider type +/// as a type argument instead of . +/// +/// +/// The data provider type that yields test rows (for example an +/// of object arrays). +/// This is not the same as TUnit's ClassDataSource<T>, which injects an instance of +/// as a dependency. +/// +/// +/// Requires C# 11 or later to use the [AutoClassDataSource<T>] attribute syntax. +/// +[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", + Justification = "This attribute is the root of a potential attribute hierarchy.")] +public class AutoClassDataSourceAttribute : AutoClassDataSourceAttribute +{ + /// + /// Initializes a new instance of the class. + /// + /// The parameters passed to the data provider class constructor. + public AutoClassDataSourceAttribute(params object?[] parameters) + : base(typeof(T), parameters) + { + } + + /// + /// Initializes a new instance of the class + /// with a custom fixture factory. + /// + /// The fixture factory that provides missing data from . + /// The parameters passed to the data provider class constructor. + protected AutoClassDataSourceAttribute(Func fixtureFactory, params object?[] parameters) + : base(fixtureFactory, typeof(T), parameters) + { + } +} diff --git a/src/AutoFixture.TUnit/AutoDataSourceAttribute.cs b/src/AutoFixture.TUnit/AutoDataSourceAttribute.cs index a09281f..91d946d 100644 --- a/src/AutoFixture.TUnit/AutoDataSourceAttribute.cs +++ b/src/AutoFixture.TUnit/AutoDataSourceAttribute.cs @@ -1,11 +1,10 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit; /// -/// Provides auto-generated data specimens generated by AutoFixture as an extension to -/// xUnit.net's Theory attribute. +/// Provides auto-generated data specimens generated by AutoFixture as a TUnit data source. /// [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "This attribute is the root of a potential attribute hierarchy.")] @@ -48,4 +47,4 @@ protected AutoDataSourceAttribute(Func fixtureFactory) return source.GetDataRowsAsync(dataGeneratorMetadata); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/AutoFixture.TUnit.csproj b/src/AutoFixture.TUnit/AutoFixture.TUnit.csproj index c5515f8..48cce03 100644 --- a/src/AutoFixture.TUnit/AutoFixture.TUnit.csproj +++ b/src/AutoFixture.TUnit/AutoFixture.TUnit.csproj @@ -16,7 +16,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute.cs b/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute.cs index 8202518..7d6b3a8 100644 --- a/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute.cs +++ b/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit; @@ -9,7 +9,8 @@ namespace AutoFixture.TUnit; /// 1. A static property /// 2. A static field /// 3. A static method (with parameters) -/// The member must return something compatible with IEnumerable<object?[]> with the test data. +/// The member must return test data in any shape supported by TUnit MethodDataSource +/// (for example IEnumerable<object?[]>, IEnumerable<T>, tuples, or a single value). /// [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "This attribute is the root of a potential attribute hierarchy.")] @@ -59,7 +60,7 @@ protected AutoMemberDataSourceAttribute(Func fixtureFactory, Type? mem { this.FixtureFactory = fixtureFactory ?? throw new ArgumentNullException(nameof(fixtureFactory)); this.MemberName = memberName ?? throw new ArgumentNullException(nameof(memberName)); - this.Parameters = parameters ?? [null!]; + this.Parameters = parameters ?? [null]; this.MemberType = memberType; } @@ -86,12 +87,8 @@ protected AutoMemberDataSourceAttribute(Func fixtureFactory, Type? mem /// public override IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata) { - var testMethod = dataGeneratorMetadata.GetMethod(); - - if (testMethod is null) - { - throw new ArgumentNullException(nameof(dataGeneratorMetadata), "The test method cannot be null."); - } + var testMethod = dataGeneratorMetadata.GetMethod() + ?? throw new ArgumentNullException(nameof(dataGeneratorMetadata), "The test method cannot be null."); var sourceType = this.MemberType ?? testMethod.DeclaringType ?? throw new InvalidOperationException("Source type cannot be null."); @@ -102,4 +99,4 @@ protected AutoMemberDataSourceAttribute(Func fixtureFactory, Type? mem return source.GetDataRowsAsync(dataGeneratorMetadata); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute{T}.cs b/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute{T}.cs new file mode 100644 index 0000000..0db0aba --- /dev/null +++ b/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute{T}.cs @@ -0,0 +1,38 @@ +using System.Diagnostics.CodeAnalysis; + +namespace AutoFixture.TUnit; + +/// +/// Generic form of that takes the member-declaring type +/// as a type argument instead of . +/// +/// The type that declares the static member providing test data. +/// +/// Requires C# 11 or later to use the [AutoMemberDataSource<T>] attribute syntax. +/// +[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", + Justification = "This attribute is the root of a potential attribute hierarchy.")] +public class AutoMemberDataSourceAttribute : AutoMemberDataSourceAttribute +{ + /// + /// Initializes a new instance of the class. + /// + /// The name of the public static member on that will provide the test data. + /// The parameters for the member (only supported for methods; ignored for everything else). + public AutoMemberDataSourceAttribute(string memberName, params object?[] parameters) + : base(typeof(T), memberName, parameters) + { + } + + /// + /// Initializes a new instance of the class + /// with a custom fixture factory. + /// + /// The fixture factory delegate. + /// The name of the public static member on that will provide the test data. + /// The parameters for the member (only supported for methods; ignored for everything else). + protected AutoMemberDataSourceAttribute(Func fixtureFactory, string memberName, params object?[] parameters) + : base(fixtureFactory, typeof(T), memberName, parameters) + { + } +} diff --git a/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs b/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs index 39d8fc6..af7ba41 100644 --- a/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs +++ b/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs @@ -1,4 +1,4 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit; @@ -23,6 +23,9 @@ public abstract class BaseDataSourceAttribute : Attribute, IDataSourceAttribute, /// public bool SkipIfEmpty { get; set; } + /// + public bool DeferEnumeration { get; set; } + /// public async IAsyncEnumerable>> GetDataRowsAsync(DataGeneratorMetadata dataGeneratorMetadata) { diff --git a/src/AutoFixture.TUnit/CompositeDataSourceAttribute.cs b/src/AutoFixture.TUnit/CompositeDataSourceAttribute.cs index 97c8e0f..2523b98 100644 --- a/src/AutoFixture.TUnit/CompositeDataSourceAttribute.cs +++ b/src/AutoFixture.TUnit/CompositeDataSourceAttribute.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit; @@ -65,4 +65,4 @@ public CompositeDataSourceAttribute(params BaseDataSourceAttribute[] attributes) yield return () => Task.FromResult(row); } } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/CustomizeAttribute.cs b/src/AutoFixture.TUnit/CustomizeAttribute.cs index 57f6f67..62bba45 100644 --- a/src/AutoFixture.TUnit/CustomizeAttribute.cs +++ b/src/AutoFixture.TUnit/CustomizeAttribute.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace AutoFixture.TUnit; @@ -15,4 +15,4 @@ public abstract class CustomizeAttribute : Attribute, IParameterCustomizationSou /// The parameter for which the customization is requested. /// A customization for the parameter. public abstract ICustomization GetCustomization(ParameterInfo parameter); -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/FavorArraysAttribute.cs b/src/AutoFixture.TUnit/FavorArraysAttribute.cs index d5eece8..24dd83d 100644 --- a/src/AutoFixture.TUnit/FavorArraysAttribute.cs +++ b/src/AutoFixture.TUnit/FavorArraysAttribute.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using AutoFixture.Kernel; namespace AutoFixture.TUnit; @@ -26,4 +26,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter) return new ConstructorCustomization(parameter.ParameterType, new ArrayFavoringConstructorQuery()); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/FavorEnumerablesAttribute.cs b/src/AutoFixture.TUnit/FavorEnumerablesAttribute.cs index d19dbb4..7ee0b29 100644 --- a/src/AutoFixture.TUnit/FavorEnumerablesAttribute.cs +++ b/src/AutoFixture.TUnit/FavorEnumerablesAttribute.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using AutoFixture.Kernel; namespace AutoFixture.TUnit; @@ -26,4 +26,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter) return new ConstructorCustomization(parameter.ParameterType, new EnumerableFavoringConstructorQuery()); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/FavorListsAttribute.cs b/src/AutoFixture.TUnit/FavorListsAttribute.cs index 0b497d9..45da169 100644 --- a/src/AutoFixture.TUnit/FavorListsAttribute.cs +++ b/src/AutoFixture.TUnit/FavorListsAttribute.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using AutoFixture.Kernel; namespace AutoFixture.TUnit; @@ -26,4 +26,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter) return new ConstructorCustomization(parameter.ParameterType, new ListFavoringConstructorQuery()); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/FrozenAttribute.cs b/src/AutoFixture.TUnit/FrozenAttribute.cs index 4061cf8..9f8f95f 100644 --- a/src/AutoFixture.TUnit/FrozenAttribute.cs +++ b/src/AutoFixture.TUnit/FrozenAttribute.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using AutoFixture.TUnit.Internal; @@ -66,4 +66,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter) return new FreezeOnMatchCustomization(parameter, matcher); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/GreedyAttribute.cs b/src/AutoFixture.TUnit/GreedyAttribute.cs index 9dc31d0..fedf18e 100644 --- a/src/AutoFixture.TUnit/GreedyAttribute.cs +++ b/src/AutoFixture.TUnit/GreedyAttribute.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using AutoFixture.Kernel; namespace AutoFixture.TUnit; @@ -26,4 +26,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter) return new ConstructorCustomization(parameter.ParameterType, new GreedyConstructorQuery()); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/Argument.cs b/src/AutoFixture.TUnit/Internal/Argument.cs index 67f58e1..08197e4 100644 --- a/src/AutoFixture.TUnit/Internal/Argument.cs +++ b/src/AutoFixture.TUnit/Internal/Argument.cs @@ -14,4 +14,4 @@ public Argument(TestParameter parameter, object? value) public ICustomization GetCustomization() => this.Parameter.GetCustomization(this.Value); -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/AutoDataSource.cs b/src/AutoFixture.TUnit/Internal/AutoDataSource.cs index 00c75c8..411cead 100644 --- a/src/AutoFixture.TUnit/Internal/AutoDataSource.cs +++ b/src/AutoFixture.TUnit/Internal/AutoDataSource.cs @@ -56,9 +56,19 @@ public AutoDataSource(Func createFixture, IDataSource? source = null) await foreach (var testDataFunc in source.GetData(metadata)) { - var testData = await testDataFunc(); + if (testDataFunc is null) + throw new InvalidOperationException("The source member yielded a null test data."); - var customizations = parameters.Take(testData!.Length) + var testData = await testDataFunc() + ?? throw new InvalidOperationException("The source member yielded a null test data."); + + if (testData.Length > parameters.Length) + { + throw new InvalidOperationException( + "The number of arguments provided exceeds the number of parameters."); + } + + var customizations = parameters.Take(testData.Length) .Zip(testData, (parameter, value) => new Argument(parameter, value)) .Select(argument => argument.GetCustomization()) .Where(x => x is not NullCustomization); @@ -90,4 +100,4 @@ private static object GenerateAutoValue(TestParameter parameter, IFixture fixtur return fixture.Resolve(parameter.ParameterInfo); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/ClassDataSource.cs b/src/AutoFixture.TUnit/Internal/ClassDataSource.cs index 2b194f8..42e7612 100644 --- a/src/AutoFixture.TUnit/Internal/ClassDataSource.cs +++ b/src/AutoFixture.TUnit/Internal/ClassDataSource.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace AutoFixture.TUnit.Internal; @@ -37,12 +37,6 @@ public ClassDataSource(Type type, params object?[] parameters) public override IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata) { var instance = Activator.CreateInstance(type: this.Type, args: this.parameters); - - if (instance is not IEnumerable enumerable) - { - throw new InvalidOperationException($"Data source type \"{this.Type}\" should implement the \"{typeof(IEnumerable)}\" interface."); - } - - return enumerable.ToAsyncDataSource(); + return ToAsyncDataRows(instance); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/CustomizationExtensions.cs b/src/AutoFixture.TUnit/Internal/CustomizationExtensions.cs index b447722..5ded7c8 100644 --- a/src/AutoFixture.TUnit/Internal/CustomizationExtensions.cs +++ b/src/AutoFixture.TUnit/Internal/CustomizationExtensions.cs @@ -6,4 +6,4 @@ internal static class CustomizationExtensions { public static object Resolve(this IFixture source, object request) => new SpecimenContext(source).Resolve(request); -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/CustomizeAttributeComparer.cs b/src/AutoFixture.TUnit/Internal/CustomizeAttributeComparer.cs index 0303179..2f979ed 100644 --- a/src/AutoFixture.TUnit/Internal/CustomizeAttributeComparer.cs +++ b/src/AutoFixture.TUnit/Internal/CustomizeAttributeComparer.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Internal; +namespace AutoFixture.TUnit.Internal; internal sealed class CustomizeAttributeComparer : Comparer { @@ -11,4 +11,4 @@ public override int Compare(IParameterCustomizationSource? x, IParameterCustomiz _ => 0 }; } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/DataGeneratorMetadataExtensions.cs b/src/AutoFixture.TUnit/Internal/DataGeneratorMetadataExtensions.cs index 96e7d9c..4a55ab5 100644 --- a/src/AutoFixture.TUnit/Internal/DataGeneratorMetadataExtensions.cs +++ b/src/AutoFixture.TUnit/Internal/DataGeneratorMetadataExtensions.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using TUnit.Core.Enums; using TUnit.Core.Extensions; @@ -8,16 +8,46 @@ internal static class DataGeneratorMetadataExtensions { public static MethodBase GetMethod(this DataGeneratorMetadata dataGeneratorMetadata) { - if (dataGeneratorMetadata.TestInformation == null) + if (dataGeneratorMetadata.TestInformation is null) { throw new InvalidOperationException("Not a test method"); } - + if (dataGeneratorMetadata.Type == DataGeneratorType.ClassParameters) { - return dataGeneratorMetadata.TestInformation.Class.Type.GetConstructors().First(); + var constructors = dataGeneratorMetadata.TestInformation.Class.Type.GetConstructors(); + var members = dataGeneratorMetadata.MembersToGenerate; + + return constructors.FirstOrDefault(constructor => MatchesMembers(constructor, members)) + ?? throw new InvalidOperationException( + "Could not find a constructor matching the class parameters to generate."); } return dataGeneratorMetadata.TestInformation.GetReflectionInfo(); } -} \ No newline at end of file + + private static bool MatchesMembers(ConstructorInfo constructor, IMemberMetadata[] members) + { + var parameters = constructor.GetParameters(); + if (parameters.Length != members.Length) + { + return false; + } + + for (var i = 0; i < parameters.Length; i++) + { + if (members[i] is not ParameterMetadata parameterMetadata) + { + return false; + } + + if (parameters[i].ParameterType != parameterMetadata.Type + || !string.Equals(parameters[i].Name, parameterMetadata.Name, StringComparison.Ordinal)) + { + return false; + } + } + + return true; + } +} diff --git a/src/AutoFixture.TUnit/Internal/DataSource.cs b/src/AutoFixture.TUnit/Internal/DataSource.cs index a7cd44b..d620062 100644 --- a/src/AutoFixture.TUnit/Internal/DataSource.cs +++ b/src/AutoFixture.TUnit/Internal/DataSource.cs @@ -1,4 +1,7 @@ -using System.Diagnostics.CodeAnalysis; +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using TUnit.Core.Helpers; namespace AutoFixture.TUnit.Internal; @@ -9,4 +12,126 @@ namespace AutoFixture.TUnit.Internal; Justification = "The type is not a collection.")] [SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix", Justification = "The type is not a collection.")] -public abstract class DataSource : BaseDataSourceAttribute; \ No newline at end of file +public abstract class DataSource : BaseDataSourceAttribute +{ + /// + /// Converts a TUnit-compatible data source result into async row factories. + /// + /// + /// The raw data source result (for example a sequence, tuple, scalar, task, or async enumerable). + /// + /// + /// A token used to cancel async enumeration of the data rows. + /// + /// + /// An asynchronous sequence of factories that each produce one object?[] test case row. + /// + protected static async IAsyncEnumerable>> ToAsyncDataRows( + object? value, + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + while (value is Task task) + { + await task.ConfigureAwait(false); + value = GetTaskResult(task); + } + + if (value is null) + { + yield return static () => Task.FromResult([null]); + yield break; + } + + if (TryGetAsyncElementType(value, out var elementType)) + { + var convert = typeof(DataConversionHelper) + .GetMethod(nameof(DataConversionHelper.ConvertAsyncEnumerableToObjectArrays))! + .MakeGenericMethod(elementType); + + var rows = (IAsyncEnumerable)convert + .Invoke(null, [value, cancellationToken])!; + + await foreach (var row in rows.WithCancellation(cancellationToken).ConfigureAwait(false)) + { + var captured = ExpandCollapsedRow(row); + yield return () => Task.FromResult(captured); + } + + yield break; + } + + if (IsRowSequence(value)) + { + foreach (var row in DataConversionHelper.ConvertToObjectArrays(value)) + { + var captured = ExpandCollapsedRow(row); + yield return () => Task.FromResult(captured); + } + + yield break; + } + + var singleRow = DataSourceHelpers.ToObjectArray(value); + yield return () => Task.FromResult(singleRow); + } + + // TUnit Convert*ToObjectArrays can leave a ValueTuple or object[] as one cell. + private static object?[] ExpandCollapsedRow(object?[] row) + { + if (row is not [var only]) + { + return row; + } + + if (DataSourceHelpers.IsTuple(only)) + { + return DataSourceHelpers.ToObjectArray(only); + } + + if (only is object[] alreadyRow) + { + return alreadyRow; + } + + return row; + } + + private static object? GetTaskResult(Task task) + { + var resultProperty = task.GetType().GetProperty("Result"); + return resultProperty?.GetValue(task); + } + + private static bool IsRowSequence(object value) + { + if (value is string) + { + return false; + } + + if (DataSourceHelpers.IsTuple(value)) + { + return false; + } + + return value is IEnumerable; + } + + private static bool TryGetAsyncElementType(object value, out Type elementType) + { + var asyncEnumerable = ( + from type in value.GetType().GetInterfaces() + where type.IsGenericType + && type.GetGenericTypeDefinition() == typeof(IAsyncEnumerable<>) + select type).FirstOrDefault(); + + if (asyncEnumerable is null) + { + elementType = null!; + return false; + } + + elementType = asyncEnumerable.GetGenericArguments()[0]; + return true; + } +} diff --git a/src/AutoFixture.TUnit/Internal/EnumerableExtensions.cs b/src/AutoFixture.TUnit/Internal/EnumerableExtensions.cs index 81c218c..46a12cc 100644 --- a/src/AutoFixture.TUnit/Internal/EnumerableExtensions.cs +++ b/src/AutoFixture.TUnit/Internal/EnumerableExtensions.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Internal; +namespace AutoFixture.TUnit.Internal; internal static class EnumerableExtensions { @@ -41,9 +41,8 @@ internal static IEnumerable Collapse(this IEnumerable> sequ } } - #pragma warning disable CS1998 // Async method lacks 'await' - required for IAsyncEnumerable yield +#pragma warning disable CS1998 // Async method lacks 'await' - required for IAsyncEnumerable yield internal static async IAsyncEnumerable>> ToAsyncDataSource( - #pragma warning restore CS1998 this IEnumerable source) { foreach (var item in source) @@ -51,4 +50,5 @@ internal static IEnumerable Collapse(this IEnumerable> sequ yield return () => Task.FromResult(item); } } -} \ No newline at end of file +#pragma warning restore CS1998 +} diff --git a/src/AutoFixture.TUnit/Internal/FieldDataSource.cs b/src/AutoFixture.TUnit/Internal/FieldDataSource.cs index 9784b2d..df2ecfe 100644 --- a/src/AutoFixture.TUnit/Internal/FieldDataSource.cs +++ b/src/AutoFixture.TUnit/Internal/FieldDataSource.cs @@ -31,18 +31,9 @@ public FieldDataSource(FieldInfo fieldInfo) /// Gets the test data from the source field. /// /// Returns a sequence of argument collections. - /// - /// Thrown when the field does not return an enumerable value. - /// public override IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata) { var value = this.FieldInfo.GetValue(null); - - if (value is not IEnumerable enumerable) - { - throw new InvalidCastException("Member does not return an enumerable value."); - } - - return enumerable.ToAsyncDataSource(); + return ToAsyncDataRows(value); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/FrozenValueCustomization.cs b/src/AutoFixture.TUnit/Internal/FrozenValueCustomization.cs index 4717352..1a00323 100644 --- a/src/AutoFixture.TUnit/Internal/FrozenValueCustomization.cs +++ b/src/AutoFixture.TUnit/Internal/FrozenValueCustomization.cs @@ -21,4 +21,4 @@ public void Customize(IFixture fixture) fixture.Customizations.Insert(0, builder); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/IDataSource.cs b/src/AutoFixture.TUnit/Internal/IDataSource.cs index aea9f87..1fba501 100644 --- a/src/AutoFixture.TUnit/Internal/IDataSource.cs +++ b/src/AutoFixture.TUnit/Internal/IDataSource.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Internal; +namespace AutoFixture.TUnit.Internal; /// /// Exposes the factory method for a sequence of test data. @@ -11,4 +11,4 @@ public interface IDataSource /// The target method for which to provide the arguments. /// Returns a sequence of argument collections. IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata); -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/InlineDataSource.cs b/src/AutoFixture.TUnit/Internal/InlineDataSource.cs index a59f1d8..88eeed9 100644 --- a/src/AutoFixture.TUnit/Internal/InlineDataSource.cs +++ b/src/AutoFixture.TUnit/Internal/InlineDataSource.cs @@ -29,9 +29,9 @@ public InlineDataSource(object?[] values) public IReadOnlyList Values => Array.AsReadOnly(this.values); /// - #pragma warning disable CS1998 // Async method lacks 'await' - required for IAsyncEnumerable yield +#pragma warning disable CS1998 // Async method lacks 'await' - required for IAsyncEnumerable yield public override async IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata) - #pragma warning restore CS1998 +#pragma warning restore CS1998 { if (dataGeneratorMetadata is null) { @@ -47,4 +47,4 @@ public InlineDataSource(object?[] values) yield return () => Task.FromResult(this.values); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/MemberDataSource.cs b/src/AutoFixture.TUnit/Internal/MemberDataSource.cs index e8ded91..6823f96 100644 --- a/src/AutoFixture.TUnit/Internal/MemberDataSource.cs +++ b/src/AutoFixture.TUnit/Internal/MemberDataSource.cs @@ -60,15 +60,6 @@ private DataSource GetTestDataSource() throw new ArgumentException(message); } - var returnType = sourceMember.GetReturnType(); - if (!typeof(IEnumerable).IsAssignableFrom(returnType)) - { - var message = string.Format( - CultureInfo.CurrentCulture, - "Member {0} on {1} does not return IEnumerable", this.Name, this.Type.FullName); - throw new ArgumentException(message); - } - return sourceMember switch { FieldInfo fieldInfo => new FieldDataSource(fieldInfo), @@ -83,4 +74,4 @@ private DataSource GetTestDataSource() { return this.Source.GetDataRowsAsync(dataGeneratorMetadata); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/MethodDataSource.cs b/src/AutoFixture.TUnit/Internal/MethodDataSource.cs index 91a6221..9a852b8 100644 --- a/src/AutoFixture.TUnit/Internal/MethodDataSource.cs +++ b/src/AutoFixture.TUnit/Internal/MethodDataSource.cs @@ -37,12 +37,6 @@ public MethodDataSource(MethodInfo methodInfo, params object?[] arguments) public override IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata) { var value = this.MethodInfo.Invoke(null, this.arguments); - - if (value is not IEnumerable enumerable) - { - throw new InvalidCastException("Member does not return an enumerable value."); - } - - return enumerable.ToAsyncDataSource(); + return ToAsyncDataRows(value); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/NullCustomization.cs b/src/AutoFixture.TUnit/Internal/NullCustomization.cs index 18b2b09..afb3fd0 100644 --- a/src/AutoFixture.TUnit/Internal/NullCustomization.cs +++ b/src/AutoFixture.TUnit/Internal/NullCustomization.cs @@ -16,4 +16,4 @@ public void Customize(IFixture fixture) { // intentionally left blank } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/ParameterFilter.cs b/src/AutoFixture.TUnit/Internal/ParameterFilter.cs index 1a15d59..9310c1b 100644 --- a/src/AutoFixture.TUnit/Internal/ParameterFilter.cs +++ b/src/AutoFixture.TUnit/Internal/ParameterFilter.cs @@ -39,4 +39,4 @@ public bool IsSatisfiedBy(object request) { return this.matcherSpecification.IsSatisfiedBy(request); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/ParameterMatcherBuilder.cs b/src/AutoFixture.TUnit/Internal/ParameterMatcherBuilder.cs index faf4e02..e3833ba 100644 --- a/src/AutoFixture.TUnit/Internal/ParameterMatcherBuilder.cs +++ b/src/AutoFixture.TUnit/Internal/ParameterMatcherBuilder.cs @@ -195,4 +195,4 @@ public bool Equals(Type? x, Type? y) public int GetHashCode(Type obj) => 0; } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/PropertyDataSource.cs b/src/AutoFixture.TUnit/Internal/PropertyDataSource.cs index f6ee139..f303cc5 100644 --- a/src/AutoFixture.TUnit/Internal/PropertyDataSource.cs +++ b/src/AutoFixture.TUnit/Internal/PropertyDataSource.cs @@ -29,12 +29,6 @@ public PropertyDataSource(PropertyInfo propertyInfo) public override IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata) { var value = this.PropertyInfo.GetValue(null); - - if (value is not IEnumerable enumerable) - { - throw new InvalidCastException("Member does not return an enumerable value."); - } - - return enumerable.ToAsyncDataSource(); + return ToAsyncDataRows(value); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Internal/ReflectionExtensions.cs b/src/AutoFixture.TUnit/Internal/ReflectionExtensions.cs deleted file mode 100644 index 213b173..0000000 --- a/src/AutoFixture.TUnit/Internal/ReflectionExtensions.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Reflection; - -namespace AutoFixture.TUnit.Internal; - -internal static class ReflectionExtensions -{ - public static Type GetReturnType(this MemberInfo member) - { - if (member is null) - { - throw new ArgumentNullException(nameof(member)); - } - - return member switch - { - MethodInfo methodInfo => methodInfo.ReturnType, - PropertyInfo propertyInfo => propertyInfo.PropertyType, - FieldInfo fieldInfo => fieldInfo.FieldType, - _ => throw new ArgumentException("Member is not a method, property, or field.", nameof(member)) - }; - } -} \ No newline at end of file diff --git a/src/AutoFixture.TUnit/Internal/TestParameter.cs b/src/AutoFixture.TUnit/Internal/TestParameter.cs index 0509b0b..6690382 100644 --- a/src/AutoFixture.TUnit/Internal/TestParameter.cs +++ b/src/AutoFixture.TUnit/Internal/TestParameter.cs @@ -52,4 +52,4 @@ private static ICustomization GetCustomization(ParameterInfo parameter) } public static TestParameter From(ParameterInfo parameterInfo) => new(parameterInfo); -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/Matching.cs b/src/AutoFixture.TUnit/Matching.cs index e284d4a..911e95e 100644 --- a/src/AutoFixture.TUnit/Matching.cs +++ b/src/AutoFixture.TUnit/Matching.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace AutoFixture.TUnit; @@ -58,4 +58,4 @@ public enum Matching /// and has a specific name. /// MemberName = ParameterName | PropertyName | FieldName -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/ModestAttribute.cs b/src/AutoFixture.TUnit/ModestAttribute.cs index a1fa8ba..844e37b 100644 --- a/src/AutoFixture.TUnit/ModestAttribute.cs +++ b/src/AutoFixture.TUnit/ModestAttribute.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using AutoFixture.Kernel; namespace AutoFixture.TUnit; @@ -26,4 +26,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter) return new ConstructorCustomization(parameter.ParameterType, new ModestConstructorQuery()); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/NoAutoPropertiesAttribute.cs b/src/AutoFixture.TUnit/NoAutoPropertiesAttribute.cs index b8039f9..ece786d 100644 --- a/src/AutoFixture.TUnit/NoAutoPropertiesAttribute.cs +++ b/src/AutoFixture.TUnit/NoAutoPropertiesAttribute.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace AutoFixture.TUnit; @@ -27,4 +27,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter) var targetType = parameter.ParameterType; return new NoAutoPropertiesCustomization(targetType); } -} \ No newline at end of file +} From 0a153c3d556786d06be4500a1d4dff499fee34c5 Mon Sep 17 00:00:00 2001 From: Andrei Ivascu <7030530+aivascu@users.noreply.github.com> Date: Mon, 7 Sep 2026 00:31:38 +0300 Subject: [PATCH 2/5] Harden Nuke/CI tooling and simplify analyzer setup for tests. --- .editorconfig | 19 +- .github/pull_request_template.md | 4 +- .github/workflows/continuous.yml | 8 +- .github/workflows/release.yml | 14 +- AutoFixture.TUnit.Tests.globalconfig | 654 --------------------------- AutoFixture.TUnit.globalconfig | 78 ++-- AutoFixture.TUnit.sln.DotSettings | 10 +- Common.Test.props | 18 +- Common.props | 3 +- build/Build.cs | 11 +- build/_build.csproj | 6 +- 11 files changed, 92 insertions(+), 733 deletions(-) delete mode 100644 AutoFixture.TUnit.Tests.globalconfig diff --git a/.editorconfig b/.editorconfig index d627e2a..205e89f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,8 +7,11 @@ indent_style = space [*.cs] indent_size = 4 indent_style = space +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true -# Require "this." keyword qualification in code +# Prefer "this." qualification in product-style code dotnet_style_qualification_for_field = true:suggestion dotnet_style_qualification_for_property = true:suggestion dotnet_style_qualification_for_method = true:suggestion @@ -16,3 +19,17 @@ dotnet_style_qualification_for_event = true:suggestion dotnet_diagnostic.CA1510.severity = suggestion dotnet_diagnostic.CA1859.severity = suggestion + +# Prefer classic constructors on classes; primary constructors are fine on records. +csharp_style_prefer_primary_constructors = false +dotnet_diagnostic.IDE0290.severity = none + +# Tests: keep analyzers visible in the IDE, but do not fail Verify builds. +# StyleCop is not referenced for test projects. +[tests/**/*.cs] +dotnet_analyzer_diagnostic.severity = suggestion +dotnet_diagnostic.IDE0058.severity = none + +# Fixture/helpers intentionally break design rules (delegates, public fields, odd shapes). +[tests/AutoFixture.TUnit.Tests/TestTypes/**.cs] +dotnet_analyzer_diagnostic.severity = none diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b29aad6..45e3f37 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,8 +6,8 @@ ### Checklist -- [ ] Reviewed the [contribution guidelines](https://github.com/AutoFixture/AutoFixture/blob/master/CONTRIBUTING.md) +- [ ] Reviewed the [contribution guidelines](https://github.com/AutoFixture/AutoFixture.TUnit/blob/master/CONTRIBUTING.md) - [ ] Linked the issue(s) the PR closes - [ ] Implemented automated tests and checked coverage - [ ] Provided inline documentation comments for new public API -- [ ] Ran the full solution [build and validation](https://github.com/AutoFixture/AutoFixture#build) locally +- [ ] Ran the full solution [build and validation](https://github.com/AutoFixture/AutoFixture.TUnit/blob/master/CONTRIBUTING.md#verification) locally diff --git a/.github/workflows/continuous.yml b/.github/workflows/continuous.yml index 95c7192..84d4066 100644 --- a/.github/workflows/continuous.yml +++ b/.github/workflows/continuous.yml @@ -27,16 +27,16 @@ jobs: name: windows-latest runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: fetch-depth: 0 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v6 with: dotnet-version: | - 6.0.x 8.0.x + 10.0.x - name: Cache .nuke/temp, ~/.nuget/packages - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: | .nuke/temp diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d145954..afbaeb6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,16 +26,16 @@ jobs: name: windows-latest runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: fetch-depth: 0 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v6 with: dotnet-version: | - 6.0.x 8.0.x + 10.0.x - name: Cache .nuke/temp, ~/.nuget/packages - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: | .nuke/temp @@ -46,15 +46,15 @@ jobs: env: GitHubToken: ${{ secrets.GITHUB_TOKEN }} NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: testresults path: artifacts/testresults - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: reports path: artifacts/reports - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: packages path: artifacts/packages diff --git a/AutoFixture.TUnit.Tests.globalconfig b/AutoFixture.TUnit.Tests.globalconfig deleted file mode 100644 index 2b8356f..0000000 --- a/AutoFixture.TUnit.Tests.globalconfig +++ /dev/null @@ -1,654 +0,0 @@ -is_global = true -global_level = 200 - -# NOTE: No section headers for configuration entries - -#### .NET Coding Conventions #### - -## Naming conventions ## - -#### Diagnostic configuration #### - -## Managed code analysis ## - -dotnet_diagnostic.CA1000.severity = none -dotnet_diagnostic.CA1001.severity = none -dotnet_diagnostic.CA1002.severity = none -dotnet_diagnostic.CA1003.severity = none -dotnet_diagnostic.CA1004.severity = none -dotnet_diagnostic.CA1005.severity = none -dotnet_diagnostic.CA1006.severity = none -dotnet_diagnostic.CA1007.severity = none -dotnet_diagnostic.CA1008.severity = none -dotnet_diagnostic.CA1009.severity = none -dotnet_diagnostic.CA1010.severity = none -dotnet_diagnostic.CA1011.severity = none -dotnet_diagnostic.CA1012.severity = none -dotnet_diagnostic.CA1013.severity = none -dotnet_diagnostic.CA1014.severity = none -dotnet_diagnostic.CA1016.severity = none -dotnet_diagnostic.CA1017.severity = none -dotnet_diagnostic.CA1018.severity = none -dotnet_diagnostic.CA1019.severity = none -dotnet_diagnostic.CA1020.severity = none -dotnet_diagnostic.CA1021.severity = none -dotnet_diagnostic.CA1023.severity = none -dotnet_diagnostic.CA1024.severity = none -dotnet_diagnostic.CA1025.severity = none -dotnet_diagnostic.CA1026.severity = none -dotnet_diagnostic.CA1027.severity = none -dotnet_diagnostic.CA1028.severity = none -dotnet_diagnostic.CA1030.severity = none -dotnet_diagnostic.CA1031.severity = none -dotnet_diagnostic.CA1032.severity = none -dotnet_diagnostic.CA1033.severity = none -dotnet_diagnostic.CA1034.severity = none -dotnet_diagnostic.CA1035.severity = none -dotnet_diagnostic.CA1036.severity = none -dotnet_diagnostic.CA1038.severity = none -dotnet_diagnostic.CA1039.severity = none -dotnet_diagnostic.CA1040.severity = none -dotnet_diagnostic.CA1041.severity = none -dotnet_diagnostic.CA1043.severity = none -dotnet_diagnostic.CA1044.severity = none -dotnet_diagnostic.CA1045.severity = none -dotnet_diagnostic.CA1046.severity = none -dotnet_diagnostic.CA1047.severity = none -dotnet_diagnostic.CA1048.severity = none -dotnet_diagnostic.CA1049.severity = none -dotnet_diagnostic.CA1050.severity = none -dotnet_diagnostic.CA1051.severity = none -dotnet_diagnostic.CA1052.severity = none -dotnet_diagnostic.CA1053.severity = none -dotnet_diagnostic.CA1054.severity = none -dotnet_diagnostic.CA1055.severity = none -dotnet_diagnostic.CA1056.severity = none -dotnet_diagnostic.CA1057.severity = none -dotnet_diagnostic.CA1058.severity = none -dotnet_diagnostic.CA1059.severity = none -dotnet_diagnostic.CA1060.severity = none -dotnet_diagnostic.CA1061.severity = none -dotnet_diagnostic.CA1062.severity = none -dotnet_diagnostic.CA1063.severity = none -dotnet_diagnostic.CA1064.severity = none -dotnet_diagnostic.CA1065.severity = none -dotnet_diagnostic.CA1300.severity = none -dotnet_diagnostic.CA1301.severity = none -dotnet_diagnostic.CA1302.severity = none -dotnet_diagnostic.CA1303.severity = none -dotnet_diagnostic.CA1304.severity = none -dotnet_diagnostic.CA1305.severity = none -dotnet_diagnostic.CA1306.severity = none -dotnet_diagnostic.CA1307.severity = none -dotnet_diagnostic.CA1308.severity = none -dotnet_diagnostic.CA1309.severity = none -dotnet_diagnostic.CA1400.severity = none -dotnet_diagnostic.CA1401.severity = none -dotnet_diagnostic.CA1402.severity = none -dotnet_diagnostic.CA1403.severity = none -dotnet_diagnostic.CA1404.severity = none -dotnet_diagnostic.CA1405.severity = none -dotnet_diagnostic.CA1406.severity = none -dotnet_diagnostic.CA1407.severity = none -dotnet_diagnostic.CA1408.severity = none -dotnet_diagnostic.CA1409.severity = none -dotnet_diagnostic.CA1410.severity = none -dotnet_diagnostic.CA1411.severity = none -dotnet_diagnostic.CA1412.severity = none -dotnet_diagnostic.CA1413.severity = none -dotnet_diagnostic.CA1414.severity = none -dotnet_diagnostic.CA1415.severity = none -dotnet_diagnostic.CA1500.severity = none -dotnet_diagnostic.CA1501.severity = none -dotnet_diagnostic.CA1502.severity = none -dotnet_diagnostic.CA1504.severity = none -dotnet_diagnostic.CA1505.severity = none -dotnet_diagnostic.CA1506.severity = none -dotnet_diagnostic.CA1600.severity = none -dotnet_diagnostic.CA1601.severity = none -dotnet_diagnostic.CA1700.severity = none -dotnet_diagnostic.CA1701.severity = none -dotnet_diagnostic.CA1702.severity = none -dotnet_diagnostic.CA1703.severity = none -dotnet_diagnostic.CA1704.severity = none -dotnet_diagnostic.CA1707.severity = none -dotnet_diagnostic.CA1708.severity = none -dotnet_diagnostic.CA1709.severity = none -dotnet_diagnostic.CA1710.severity = none -dotnet_diagnostic.CA1711.severity = none -dotnet_diagnostic.CA1712.severity = none -dotnet_diagnostic.CA1713.severity = none -dotnet_diagnostic.CA1714.severity = none -dotnet_diagnostic.CA1715.severity = none -dotnet_diagnostic.CA1716.severity = none -dotnet_diagnostic.CA1717.severity = none -dotnet_diagnostic.CA1719.severity = none -dotnet_diagnostic.CA1720.severity = none -dotnet_diagnostic.CA1721.severity = none -dotnet_diagnostic.CA1722.severity = none -dotnet_diagnostic.CA1724.severity = none -dotnet_diagnostic.CA1725.severity = none -dotnet_diagnostic.CA1726.severity = none -dotnet_diagnostic.CA1800.severity = none -dotnet_diagnostic.CA1801.severity = none -dotnet_diagnostic.CA1802.severity = none -dotnet_diagnostic.CA1804.severity = none -dotnet_diagnostic.CA1806.severity = none -dotnet_diagnostic.CA1809.severity = none -dotnet_diagnostic.CA1810.severity = none -dotnet_diagnostic.CA1811.severity = none -dotnet_diagnostic.CA1812.severity = none -dotnet_diagnostic.CA1813.severity = none -dotnet_diagnostic.CA1814.severity = none -dotnet_diagnostic.CA1815.severity = none -dotnet_diagnostic.CA1816.severity = none -dotnet_diagnostic.CA1819.severity = none -dotnet_diagnostic.CA1820.severity = none -dotnet_diagnostic.CA1821.severity = none -dotnet_diagnostic.CA1822.severity = none -dotnet_diagnostic.CA1823.severity = none -dotnet_diagnostic.CA1824.severity = none -dotnet_diagnostic.CA1825.severity = none -dotnet_diagnostic.CA1900.severity = none -dotnet_diagnostic.CA1901.severity = none -dotnet_diagnostic.CA1903.severity = none -dotnet_diagnostic.CA2000.severity = none -dotnet_diagnostic.CA2001.severity = none -dotnet_diagnostic.CA2002.severity = none -dotnet_diagnostic.CA2003.severity = none -dotnet_diagnostic.CA2004.severity = none -dotnet_diagnostic.CA2006.severity = none -dotnet_diagnostic.CA2100.severity = none -dotnet_diagnostic.CA2101.severity = none -dotnet_diagnostic.CA2102.severity = none -dotnet_diagnostic.CA2103.severity = none -dotnet_diagnostic.CA2104.severity = none -dotnet_diagnostic.CA2105.severity = none -dotnet_diagnostic.CA2106.severity = none -dotnet_diagnostic.CA2107.severity = none -dotnet_diagnostic.CA2108.severity = none -dotnet_diagnostic.CA2109.severity = none -dotnet_diagnostic.CA2111.severity = none -dotnet_diagnostic.CA2112.severity = none -dotnet_diagnostic.CA2114.severity = none -dotnet_diagnostic.CA2115.severity = none -dotnet_diagnostic.CA2116.severity = none -dotnet_diagnostic.CA2117.severity = none -dotnet_diagnostic.CA2118.severity = none -dotnet_diagnostic.CA2119.severity = none -dotnet_diagnostic.CA2120.severity = none -dotnet_diagnostic.CA2121.severity = none -dotnet_diagnostic.CA2122.severity = none -dotnet_diagnostic.CA2123.severity = none -dotnet_diagnostic.CA2124.severity = none -dotnet_diagnostic.CA2126.severity = none -dotnet_diagnostic.CA2130.severity = none -dotnet_diagnostic.CA2131.severity = none -dotnet_diagnostic.CA2132.severity = none -dotnet_diagnostic.CA2133.severity = none -dotnet_diagnostic.CA2134.severity = none -dotnet_diagnostic.CA2135.severity = none -dotnet_diagnostic.CA2136.severity = none -dotnet_diagnostic.CA2137.severity = none -dotnet_diagnostic.CA2138.severity = none -dotnet_diagnostic.CA2139.severity = none -dotnet_diagnostic.CA2140.severity = none -dotnet_diagnostic.CA2141.severity = none -dotnet_diagnostic.CA2142.severity = none -dotnet_diagnostic.CA2143.severity = none -dotnet_diagnostic.CA2144.severity = none -dotnet_diagnostic.CA2145.severity = none -dotnet_diagnostic.CA2146.severity = none -dotnet_diagnostic.CA2147.severity = none -dotnet_diagnostic.CA2149.severity = none -dotnet_diagnostic.CA2151.severity = none -dotnet_diagnostic.CA2200.severity = none -dotnet_diagnostic.CA2201.severity = none -dotnet_diagnostic.CA2202.severity = none -dotnet_diagnostic.CA2204.severity = none -dotnet_diagnostic.CA2205.severity = none -dotnet_diagnostic.CA2207.severity = none -dotnet_diagnostic.CA2208.severity = none -dotnet_diagnostic.CA2210.severity = none -dotnet_diagnostic.CA2211.severity = none -dotnet_diagnostic.CA2212.severity = none -dotnet_diagnostic.CA2213.severity = none -dotnet_diagnostic.CA2214.severity = none -dotnet_diagnostic.CA2215.severity = none -dotnet_diagnostic.CA2216.severity = none -dotnet_diagnostic.CA2217.severity = none -dotnet_diagnostic.CA2218.severity = none -dotnet_diagnostic.CA2219.severity = none -dotnet_diagnostic.CA2220.severity = none -dotnet_diagnostic.CA2221.severity = none -dotnet_diagnostic.CA2222.severity = none -dotnet_diagnostic.CA2223.severity = none -dotnet_diagnostic.CA2224.severity = none -dotnet_diagnostic.CA2225.severity = none -dotnet_diagnostic.CA2226.severity = none -dotnet_diagnostic.CA2227.severity = none -dotnet_diagnostic.CA2228.severity = none -dotnet_diagnostic.CA2229.severity = none -dotnet_diagnostic.CA2230.severity = none -dotnet_diagnostic.CA2231.severity = none -dotnet_diagnostic.CA2232.severity = none -dotnet_diagnostic.CA2233.severity = none -dotnet_diagnostic.CA2234.severity = none -dotnet_diagnostic.CA2235.severity = none -dotnet_diagnostic.CA2236.severity = none -dotnet_diagnostic.CA2237.severity = none -dotnet_diagnostic.CA2238.severity = none -dotnet_diagnostic.CA2239.severity = none -dotnet_diagnostic.CA2240.severity = none -dotnet_diagnostic.CA2241.severity = none -dotnet_diagnostic.CA2242.severity = none -dotnet_diagnostic.CA2243.severity = none -dotnet_diagnostic.CA5122.severity = none - -## Security analysis ## - -dotnet_diagnostic.CA2300.severity = none - -## Native code analysis ## - -dotnet_diagnostic.C26100.severity = none -dotnet_diagnostic.C26101.severity = none -dotnet_diagnostic.C26105.severity = none -dotnet_diagnostic.C26110.severity = none -dotnet_diagnostic.C26111.severity = none -dotnet_diagnostic.C26112.severity = none -dotnet_diagnostic.C26115.severity = none -dotnet_diagnostic.C26116.severity = none -dotnet_diagnostic.C26117.severity = none -dotnet_diagnostic.C26130.severity = none -dotnet_diagnostic.C26135.severity = none -dotnet_diagnostic.C26140.severity = none -dotnet_diagnostic.C26160.severity = none -dotnet_diagnostic.C26165.severity = none -dotnet_diagnostic.C26166.severity = none -dotnet_diagnostic.C26167.severity = none -dotnet_diagnostic.C28020.severity = none -dotnet_diagnostic.C28021.severity = none -dotnet_diagnostic.C28022.severity = none -dotnet_diagnostic.C28023.severity = none -dotnet_diagnostic.C28024.severity = none -dotnet_diagnostic.C28039.severity = none -dotnet_diagnostic.C28101.severity = none -dotnet_diagnostic.C28103.severity = none -dotnet_diagnostic.C28104.severity = none -dotnet_diagnostic.C28105.severity = none -dotnet_diagnostic.C28106.severity = none -dotnet_diagnostic.C28107.severity = none -dotnet_diagnostic.C28108.severity = none -dotnet_diagnostic.C28109.severity = none -dotnet_diagnostic.C28110.severity = none -dotnet_diagnostic.C28111.severity = none -dotnet_diagnostic.C28112.severity = none -dotnet_diagnostic.C28113.severity = none -dotnet_diagnostic.C28114.severity = none -dotnet_diagnostic.C28120.severity = none -dotnet_diagnostic.C28121.severity = none -dotnet_diagnostic.C28122.severity = none -dotnet_diagnostic.C28123.severity = none -dotnet_diagnostic.C28124.severity = none -dotnet_diagnostic.C28125.severity = none -dotnet_diagnostic.C28126.severity = none -dotnet_diagnostic.C28127.severity = none -dotnet_diagnostic.C28128.severity = none -dotnet_diagnostic.C28129.severity = none -dotnet_diagnostic.C28131.severity = none -dotnet_diagnostic.C28132.severity = none -dotnet_diagnostic.C28133.severity = none -dotnet_diagnostic.C28134.severity = none -dotnet_diagnostic.C28135.severity = none -dotnet_diagnostic.C28137.severity = none -dotnet_diagnostic.C28138.severity = none -dotnet_diagnostic.C28141.severity = none -dotnet_diagnostic.C28143.severity = none -dotnet_diagnostic.C28144.severity = none -dotnet_diagnostic.C28145.severity = none -dotnet_diagnostic.C28146.severity = none -dotnet_diagnostic.C28147.severity = none -dotnet_diagnostic.C28150.severity = none -dotnet_diagnostic.C28151.severity = none -dotnet_diagnostic.C28152.severity = none -dotnet_diagnostic.C28153.severity = none -dotnet_diagnostic.C28156.severity = none -dotnet_diagnostic.C28157.severity = none -dotnet_diagnostic.C28158.severity = none -dotnet_diagnostic.C28159.severity = none -dotnet_diagnostic.C28160.severity = none -dotnet_diagnostic.C28161.severity = none -dotnet_diagnostic.C28162.severity = none -dotnet_diagnostic.C28163.severity = none -dotnet_diagnostic.C28164.severity = none -dotnet_diagnostic.C28165.severity = none -dotnet_diagnostic.C28166.severity = none -dotnet_diagnostic.C28167.severity = none -dotnet_diagnostic.C28168.severity = none -dotnet_diagnostic.C28169.severity = none -dotnet_diagnostic.C28170.severity = none -dotnet_diagnostic.C28171.severity = none -dotnet_diagnostic.C28172.severity = none -dotnet_diagnostic.C28173.severity = none -dotnet_diagnostic.C28175.severity = none -dotnet_diagnostic.C28176.severity = none -dotnet_diagnostic.C28182.severity = none -dotnet_diagnostic.C28183.severity = none -dotnet_diagnostic.C28193.severity = none -dotnet_diagnostic.C28194.severity = none -dotnet_diagnostic.C28195.severity = none -dotnet_diagnostic.C28196.severity = none -dotnet_diagnostic.C28197.severity = none -dotnet_diagnostic.C28198.severity = none -dotnet_diagnostic.C28199.severity = none -dotnet_diagnostic.C28202.severity = none -dotnet_diagnostic.C28203.severity = none -dotnet_diagnostic.C28204.severity = none -dotnet_diagnostic.C28205.severity = none -dotnet_diagnostic.C28206.severity = none -dotnet_diagnostic.C28207.severity = none -dotnet_diagnostic.C28208.severity = none -dotnet_diagnostic.C28209.severity = none -dotnet_diagnostic.C28210.severity = none -dotnet_diagnostic.C28211.severity = none -dotnet_diagnostic.C28212.severity = none -dotnet_diagnostic.C28213.severity = none -dotnet_diagnostic.C28214.severity = none -dotnet_diagnostic.C28215.severity = none -dotnet_diagnostic.C28216.severity = none -dotnet_diagnostic.C28217.severity = none -dotnet_diagnostic.C28218.severity = none -dotnet_diagnostic.C28219.severity = none -dotnet_diagnostic.C28220.severity = none -dotnet_diagnostic.C28221.severity = none -dotnet_diagnostic.C28222.severity = none -dotnet_diagnostic.C28223.severity = none -dotnet_diagnostic.C28224.severity = none -dotnet_diagnostic.C28225.severity = none -dotnet_diagnostic.C28226.severity = none -dotnet_diagnostic.C28227.severity = none -dotnet_diagnostic.C28228.severity = none -dotnet_diagnostic.C28229.severity = none -dotnet_diagnostic.C28230.severity = none -dotnet_diagnostic.C28231.severity = none -dotnet_diagnostic.C28232.severity = none -dotnet_diagnostic.C28233.severity = none -dotnet_diagnostic.C28234.severity = none -dotnet_diagnostic.C28235.severity = none -dotnet_diagnostic.C28236.severity = none -dotnet_diagnostic.C28237.severity = none -dotnet_diagnostic.C28238.severity = none -dotnet_diagnostic.C28239.severity = none -dotnet_diagnostic.C28240.severity = none -dotnet_diagnostic.C28241.severity = none -dotnet_diagnostic.C28243.severity = none -dotnet_diagnostic.C28244.severity = none -dotnet_diagnostic.C28245.severity = none -dotnet_diagnostic.C28246.severity = none -dotnet_diagnostic.C28250.severity = none -dotnet_diagnostic.C28251.severity = none -dotnet_diagnostic.C28252.severity = none -dotnet_diagnostic.C28253.severity = none -dotnet_diagnostic.C28254.severity = none -dotnet_diagnostic.C28260.severity = none -dotnet_diagnostic.C28262.severity = none -dotnet_diagnostic.C28263.severity = none -dotnet_diagnostic.C28266.severity = none -dotnet_diagnostic.C28267.severity = none -dotnet_diagnostic.C28272.severity = none -dotnet_diagnostic.C28273.severity = none -dotnet_diagnostic.C28275.severity = none -dotnet_diagnostic.C28278.severity = none -dotnet_diagnostic.C28279.severity = none -dotnet_diagnostic.C28280.severity = none -dotnet_diagnostic.C28282.severity = none -dotnet_diagnostic.C28283.severity = none -dotnet_diagnostic.C28284.severity = none -dotnet_diagnostic.C28285.severity = none -dotnet_diagnostic.C28286.severity = none -dotnet_diagnostic.C28287.severity = none -dotnet_diagnostic.C28288.severity = none -dotnet_diagnostic.C28289.severity = none -dotnet_diagnostic.C28290.severity = none -dotnet_diagnostic.C28291.severity = none -dotnet_diagnostic.C28300.severity = none -dotnet_diagnostic.C28301.severity = none -dotnet_diagnostic.C28302.severity = none -dotnet_diagnostic.C28303.severity = none -dotnet_diagnostic.C28304.severity = none -dotnet_diagnostic.C28305.severity = none -dotnet_diagnostic.C28306.severity = none -dotnet_diagnostic.C28307.severity = none -dotnet_diagnostic.C28308.severity = none -dotnet_diagnostic.C28309.severity = none -dotnet_diagnostic.C28350.severity = none -dotnet_diagnostic.C28351.severity = none -dotnet_diagnostic.C28601.severity = none -dotnet_diagnostic.C28602.severity = none -dotnet_diagnostic.C28604.severity = none -dotnet_diagnostic.C28615.severity = none -dotnet_diagnostic.C28616.severity = none -dotnet_diagnostic.C28617.severity = none -dotnet_diagnostic.C28623.severity = none -dotnet_diagnostic.C28624.severity = none -dotnet_diagnostic.C28625.severity = none -dotnet_diagnostic.C28636.severity = none -dotnet_diagnostic.C28637.severity = none -dotnet_diagnostic.C28638.severity = none -dotnet_diagnostic.C28639.severity = none -dotnet_diagnostic.C28640.severity = none -dotnet_diagnostic.C28645.severity = none -dotnet_diagnostic.C28648.severity = none -dotnet_diagnostic.C28649.severity = none -dotnet_diagnostic.C28650.severity = none -dotnet_diagnostic.C28714.severity = none -dotnet_diagnostic.C28715.severity = none -dotnet_diagnostic.C28716.severity = none -dotnet_diagnostic.C28717.severity = none -dotnet_diagnostic.C28719.severity = none -dotnet_diagnostic.C28720.severity = none -dotnet_diagnostic.C28721.severity = none -dotnet_diagnostic.C28726.severity = none -dotnet_diagnostic.C28727.severity = none -dotnet_diagnostic.C28730.severity = none -dotnet_diagnostic.C28735.severity = none -dotnet_diagnostic.C28736.severity = none -dotnet_diagnostic.C28750.severity = none -dotnet_diagnostic.C28751.severity = none -dotnet_diagnostic.C6001.severity = none -dotnet_diagnostic.C6011.severity = none -dotnet_diagnostic.C6014.severity = none -dotnet_diagnostic.C6029.severity = none -dotnet_diagnostic.C6031.severity = none -dotnet_diagnostic.C6053.severity = none -dotnet_diagnostic.C6054.severity = none -dotnet_diagnostic.C6059.severity = none -dotnet_diagnostic.C6063.severity = none -dotnet_diagnostic.C6064.severity = none -dotnet_diagnostic.C6066.severity = none -dotnet_diagnostic.C6067.severity = none -dotnet_diagnostic.C6101.severity = none -dotnet_diagnostic.C6200.severity = none -dotnet_diagnostic.C6201.severity = none -dotnet_diagnostic.C6211.severity = none -dotnet_diagnostic.C6214.severity = none -dotnet_diagnostic.C6215.severity = none -dotnet_diagnostic.C6216.severity = none -dotnet_diagnostic.C6217.severity = none -dotnet_diagnostic.C6219.severity = none -dotnet_diagnostic.C6220.severity = none -dotnet_diagnostic.C6221.severity = none -dotnet_diagnostic.C6225.severity = none -dotnet_diagnostic.C6226.severity = none -dotnet_diagnostic.C6230.severity = none -dotnet_diagnostic.C6235.severity = none -dotnet_diagnostic.C6236.severity = none -dotnet_diagnostic.C6237.severity = none -dotnet_diagnostic.C6239.severity = none -dotnet_diagnostic.C6240.severity = none -dotnet_diagnostic.C6242.severity = none -dotnet_diagnostic.C6244.severity = none -dotnet_diagnostic.C6246.severity = none -dotnet_diagnostic.C6248.severity = none -dotnet_diagnostic.C6250.severity = none -dotnet_diagnostic.C6255.severity = none -dotnet_diagnostic.C6258.severity = none -dotnet_diagnostic.C6259.severity = none -dotnet_diagnostic.C6260.severity = none -dotnet_diagnostic.C6262.severity = none -dotnet_diagnostic.C6263.severity = none -dotnet_diagnostic.C6268.severity = none -dotnet_diagnostic.C6269.severity = none -dotnet_diagnostic.C6270.severity = none -dotnet_diagnostic.C6271.severity = none -dotnet_diagnostic.C6272.severity = none -dotnet_diagnostic.C6273.severity = none -dotnet_diagnostic.C6274.severity = none -dotnet_diagnostic.C6276.severity = none -dotnet_diagnostic.C6277.severity = none -dotnet_diagnostic.C6278.severity = none -dotnet_diagnostic.C6279.severity = none -dotnet_diagnostic.C6280.severity = none -dotnet_diagnostic.C6281.severity = none -dotnet_diagnostic.C6282.severity = none -dotnet_diagnostic.C6283.severity = none -dotnet_diagnostic.C6284.severity = none -dotnet_diagnostic.C6285.severity = none -dotnet_diagnostic.C6286.severity = none -dotnet_diagnostic.C6287.severity = none -dotnet_diagnostic.C6288.severity = none -dotnet_diagnostic.C6289.severity = none -dotnet_diagnostic.C6290.severity = none -dotnet_diagnostic.C6291.severity = none -dotnet_diagnostic.C6292.severity = none -dotnet_diagnostic.C6293.severity = none -dotnet_diagnostic.C6294.severity = none -dotnet_diagnostic.C6295.severity = none -dotnet_diagnostic.C6296.severity = none -dotnet_diagnostic.C6297.severity = none -dotnet_diagnostic.C6298.severity = none -dotnet_diagnostic.C6299.severity = none -dotnet_diagnostic.C6302.severity = none -dotnet_diagnostic.C6303.severity = none -dotnet_diagnostic.C6305.severity = none -dotnet_diagnostic.C6306.severity = none -dotnet_diagnostic.C6308.severity = none -dotnet_diagnostic.C6310.severity = none -dotnet_diagnostic.C6312.severity = none -dotnet_diagnostic.C6313.severity = none -dotnet_diagnostic.C6314.severity = none -dotnet_diagnostic.C6315.severity = none -dotnet_diagnostic.C6316.severity = none -dotnet_diagnostic.C6317.severity = none -dotnet_diagnostic.C6318.severity = none -dotnet_diagnostic.C6319.severity = none -dotnet_diagnostic.C6320.severity = none -dotnet_diagnostic.C6322.severity = none -dotnet_diagnostic.C6323.severity = none -dotnet_diagnostic.C6324.severity = none -dotnet_diagnostic.C6326.severity = none -dotnet_diagnostic.C6328.severity = none -dotnet_diagnostic.C6329.severity = none -dotnet_diagnostic.C6330.severity = none -dotnet_diagnostic.C6331.severity = none -dotnet_diagnostic.C6332.severity = none -dotnet_diagnostic.C6333.severity = none -dotnet_diagnostic.C6334.severity = none -dotnet_diagnostic.C6335.severity = none -dotnet_diagnostic.C6336.severity = none -dotnet_diagnostic.C6340.severity = none -dotnet_diagnostic.C6381.severity = none -dotnet_diagnostic.C6383.severity = none -dotnet_diagnostic.C6384.severity = none -dotnet_diagnostic.C6385.severity = none -dotnet_diagnostic.C6386.severity = none -dotnet_diagnostic.C6387.severity = none -dotnet_diagnostic.C6388.severity = none -dotnet_diagnostic.C6400.severity = none -dotnet_diagnostic.C6401.severity = none -dotnet_diagnostic.C6411.severity = none -dotnet_diagnostic.C6412.severity = none -dotnet_diagnostic.C6500.severity = none -dotnet_diagnostic.C6501.severity = none -dotnet_diagnostic.C6503.severity = none -dotnet_diagnostic.C6504.severity = none -dotnet_diagnostic.C6505.severity = none -dotnet_diagnostic.C6506.severity = none -dotnet_diagnostic.C6508.severity = none -dotnet_diagnostic.C6509.severity = none -dotnet_diagnostic.C6510.severity = none -dotnet_diagnostic.C6511.severity = none -dotnet_diagnostic.C6513.severity = none -dotnet_diagnostic.C6514.severity = none -dotnet_diagnostic.C6515.severity = none -dotnet_diagnostic.C6516.severity = none -dotnet_diagnostic.C6517.severity = none -dotnet_diagnostic.C6518.severity = none -dotnet_diagnostic.C6522.severity = none -dotnet_diagnostic.C6525.severity = none -dotnet_diagnostic.C6527.severity = none -dotnet_diagnostic.C6530.severity = none -dotnet_diagnostic.C6540.severity = none -dotnet_diagnostic.C6551.severity = none -dotnet_diagnostic.C6552.severity = none -dotnet_diagnostic.C6701.severity = none -dotnet_diagnostic.C6702.severity = none -dotnet_diagnostic.C6703.severity = none -dotnet_diagnostic.C6704.severity = none -dotnet_diagnostic.C6705.severity = none -dotnet_diagnostic.C6706.severity = none -dotnet_diagnostic.C6707.severity = none -dotnet_diagnostic.C6993.severity = none -dotnet_diagnostic.C6995.severity = none -dotnet_diagnostic.C6997.severity = none - - -## Runtime analysis ## - -dotnet_diagnostic.CA1825.severity = none # CA1825: Avoid zero-length array allocations - -## Tasks analysis ## - -dotnet_diagnostic.RS0018.severity = none - -## Documentation ## - -dotnet_diagnostic.RS0010.severity = none - -## StyleCop Analyzers ## - -dotnet_diagnostic.SA0001.severity = none # SA0001: XML comment analysis is disabled due to project configuration -dotnet_diagnostic.SA1116.severity = none # SA1116: The parameters should begin on the line after the declaration, whenever the parameter span across multiple line -dotnet_diagnostic.SA1117.severity = none # SA1117: The parameters should all be placed on the same line or each parameter should be placed on its own line. -dotnet_diagnostic.SA1118.severity = none # SA1118: The parameter spans multiple lines -dotnet_diagnostic.SA1133.severity = none # SA1133: Each attribute should be placed in its own set of square brackets. -dotnet_diagnostic.SA1200.severity = none # SA1200: Using directive should appear within a namespace declaration -dotnet_diagnostic.SA1201.severity = none # SA1201: A property should not follow a method -dotnet_diagnostic.SA1202.severity = none # SA1202: 'public' members should come before 'private' members -dotnet_diagnostic.SA1203.severity = none # SA1203: Constant fields should appear before non-constant fields -dotnet_diagnostic.SA1204.severity = none # SA1204: Static members should appear before non-static members -dotnet_diagnostic.SA1214.severity = none # SA1214: Readonly fields should appear before non-readonly fields -dotnet_diagnostic.SA1401.severity = none # SA1401: Field should be private -dotnet_diagnostic.SA1402.severity = none # SA1402: File may only contain a single type -dotnet_diagnostic.SA1413.severity = none # SA1413: Use trailing comma in multi-line initializers -dotnet_diagnostic.SA1501.severity = none # SA1501: Statement should not be on a single line -dotnet_diagnostic.SA1503.severity = none # SA1503: Braces should not be omitted -dotnet_diagnostic.SA1513.severity = none # SA1513: Closing brace should be followed by blank line -dotnet_diagnostic.SA1515.severity = none # SA1515: Single-line comment should be preceded by blank line -dotnet_diagnostic.SA1516.severity = none # SA1516: Elements should be separated by blank line -dotnet_diagnostic.SA1600.severity = none # SA1600: Elements should be documented -dotnet_diagnostic.SA1604.severity = none # SA1604: Element documentation should have summary -dotnet_diagnostic.SA1610.severity = none # SA1610: Property documentation should have value text -dotnet_diagnostic.SA1611.severity = none # SA1611: The documentation for parameter 'predicate' is missing -dotnet_diagnostic.SA1612.severity = none # SA1612: The parameter documentation for 'context' should be at position 1. -dotnet_diagnostic.SA1614.severity = none # SA1614: Element parameter documentation should have text -dotnet_diagnostic.SA1615.severity = none # SA1615: Element return value should be documented -dotnet_diagnostic.SA1616.severity = none # SA1616: Element return value documentation should have text -dotnet_diagnostic.SA1618.severity = none # SA1618: The documentation for type parameter 'TProperty' is missing -dotnet_diagnostic.SA1622.severity = none # SA1622: Generic type parameter documentation should have text. -dotnet_diagnostic.SA1623.severity = none # SA1623: The property's documentation summary text should begin with: 'Gets' -dotnet_diagnostic.SA1625.severity = none # SA1625: Element documentation should not be copied and pasted -dotnet_diagnostic.SA1627.severity = none # SA1627: The documentation text within the \'exception\' tag should not be empty. -dotnet_diagnostic.SA1633.severity = none # SA1633: The file header is missing or not located at the top of the file. -dotnet_diagnostic.SA1642.severity = none # SA1642: Constructor summary documentation should begin with standard text diff --git a/AutoFixture.TUnit.globalconfig b/AutoFixture.TUnit.globalconfig index 3f911a7..66900ba 100644 --- a/AutoFixture.TUnit.globalconfig +++ b/AutoFixture.TUnit.globalconfig @@ -1,58 +1,52 @@ is_global = true global_level = 100 -# NOTE: No section headers for configuration entries - -#### .NET Coding Conventions #### - -## Naming conventions ## - #### Diagnostic configuration #### ## Managed code analysis ## -dotnet_diagnostic.CA1006.severity = none # CA1006: Do not nest generic types in member signatures -dotnet_diagnostic.CA1020.severity = none # CA1020: Avoid namespaces with few types -dotnet_diagnostic.CA1303.severity = none # CA1303: Do not pass literals as localized parameters -dotnet_diagnostic.CA2243.severity = none # CA2243: Attribute string literals should parse correctly +dotnet_diagnostic.CA1006.severity = none # Do not nest generic types in member signatures +dotnet_diagnostic.CA1020.severity = none # Avoid namespaces with few types +dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters +dotnet_diagnostic.CA2243.severity = none # Attribute string literals should parse correctly ## Runtime analysis ## -dotnet_diagnostic.CA1825.severity = none # CA1825: Avoid zero-length array allocations +dotnet_diagnostic.CA1825.severity = none # Avoid zero-length array allocations ## Security ## -dotnet_diagnostic.CA5394.severity = none # CA5394: Do not use insecure randomness +dotnet_diagnostic.CA5394.severity = none # Do not use insecure randomness ## StyleCop Analyzers ## -dotnet_diagnostic.SA1101.severity = none # SA1101: Prefix local calls with this. -dotnet_diagnostic.SA1116.severity = none # SA1116: The parameters should begin on the line after the declaration, whenever the parameter span across multiple line -dotnet_diagnostic.SA1117.severity = none # SA1117: The parameters should all be placed on the same line or each parameter should be placed on its own line. -dotnet_diagnostic.SA1118.severity = none # SA1118: The parameter spans multiple lines -dotnet_diagnostic.SA1200.severity = none # SA1200: Using directive should appear within a namespace declaration -dotnet_diagnostic.SA1201.severity = none # SA1201: A property should not follow a method -dotnet_diagnostic.SA1202.severity = none # SA1202: 'public' members should come before 'private' members -dotnet_diagnostic.SA1203.severity = none # SA1203: Constant fields should appear before non-constant fields -dotnet_diagnostic.SA1204.severity = none # SA1204: Static members should appear before non-static members -dotnet_diagnostic.SA1214.severity = none # SA1214: Readonly fields should appear before non-readonly fields -dotnet_diagnostic.SA1309.severity = none # SA1309: Field names should not begin with an underscore -dotnet_diagnostic.SA1413.severity = none # SA1413: Use trailing comma in multi-line initializers -dotnet_diagnostic.SA1501.severity = none # SA1501: Statement should not be on a single line -dotnet_diagnostic.SA1503.severity = none # SA1503: Braces should not be omitted -dotnet_diagnostic.SA1513.severity = none # SA1513: Closing brace should be followed by blank line -dotnet_diagnostic.SA1600.severity = none # SA1600: Elements should be documented -dotnet_diagnostic.SA1604.severity = none # SA1604: Element documentation should have summary -dotnet_diagnostic.SA1610.severity = none # SA1610: Property documentation should have value text -dotnet_diagnostic.SA1611.severity = none # SA1611: The documentation for parameter 'predicate' is missing -dotnet_diagnostic.SA1612.severity = none # SA1612: The parameter documentation for 'context' should be at position 1. -dotnet_diagnostic.SA1614.severity = none # SA1614: Element parameter documentation should have text -dotnet_diagnostic.SA1615.severity = none # SA1615: Element return value should be documented -dotnet_diagnostic.SA1616.severity = none # SA1616: Element return value documentation should have text -dotnet_diagnostic.SA1618.severity = none # SA1618: The documentation for type parameter 'TProperty' is missing -dotnet_diagnostic.SA1622.severity = none # SA1622: Generic type parameter documentation should have text. -dotnet_diagnostic.SA1623.severity = none # SA1623: The property's documentation summary text should begin with: 'Gets' -dotnet_diagnostic.SA1625.severity = none # SA1625: Element documentation should not be copied and pasted -dotnet_diagnostic.SA1627.severity = none # SA1627: The documentation text within the \'exception\' tag should not be empty. -dotnet_diagnostic.SA1633.severity = none # SA1633: The file header is missing or not located at the top of the file. -dotnet_diagnostic.SA1642.severity = none # SA1642: Constructor summary documentation should begin with standard text \ No newline at end of file +dotnet_diagnostic.SA1101.severity = none # Prefix local calls with this. +dotnet_diagnostic.SA1116.severity = none # Parameters should begin on the line after the declaration +dotnet_diagnostic.SA1117.severity = none # Parameters should all be on the same line or each on its own line +dotnet_diagnostic.SA1118.severity = none # Parameter spans multiple lines +dotnet_diagnostic.SA1200.severity = none # Using directive should appear within a namespace declaration +dotnet_diagnostic.SA1201.severity = none # A property should not follow a method +dotnet_diagnostic.SA1202.severity = none # 'public' members should come before 'private' members +dotnet_diagnostic.SA1203.severity = none # Constant fields should appear before non-constant fields +dotnet_diagnostic.SA1204.severity = none # Static members should appear before non-static members +dotnet_diagnostic.SA1214.severity = none # Readonly fields should appear before non-readonly fields +dotnet_diagnostic.SA1309.severity = none # Field names should not begin with an underscore +dotnet_diagnostic.SA1413.severity = none # Use trailing comma in multi-line initializers +dotnet_diagnostic.SA1501.severity = none # Statement should not be on a single line +dotnet_diagnostic.SA1503.severity = none # Braces should not be omitted +dotnet_diagnostic.SA1513.severity = none # Closing brace should be followed by blank line +dotnet_diagnostic.SA1600.severity = none # Elements should be documented +dotnet_diagnostic.SA1604.severity = none # Element documentation should have summary +dotnet_diagnostic.SA1610.severity = none # Property documentation should have value text +dotnet_diagnostic.SA1611.severity = none # Parameter documentation is missing +dotnet_diagnostic.SA1612.severity = none # Parameter documentation order +dotnet_diagnostic.SA1614.severity = none # Element parameter documentation should have text +dotnet_diagnostic.SA1615.severity = none # Element return value should be documented +dotnet_diagnostic.SA1616.severity = none # Element return value documentation should have text +dotnet_diagnostic.SA1618.severity = none # Type parameter documentation is missing +dotnet_diagnostic.SA1622.severity = none # Generic type parameter documentation should have text +dotnet_diagnostic.SA1623.severity = none # Property documentation summary text should begin with 'Gets' +dotnet_diagnostic.SA1625.severity = none # Element documentation should not be copied and pasted +dotnet_diagnostic.SA1627.severity = none # Documentation text within the 'exception' tag should not be empty +dotnet_diagnostic.SA1633.severity = none # The file header is missing or not located at the top of the file +dotnet_diagnostic.SA1642.severity = none # Constructor summary documentation should begin with standard text diff --git a/AutoFixture.TUnit.sln.DotSettings b/AutoFixture.TUnit.sln.DotSettings index dac263b..fcf6df8 100644 --- a/AutoFixture.TUnit.sln.DotSettings +++ b/AutoFixture.TUnit.sln.DotSettings @@ -12,7 +12,6 @@ True True True - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> True True @@ -26,18 +25,19 @@ True True True - xUnit fact template + TUnit test template True 0 True True Everywhere - fact + test True - [Fact] + [Test] public void $NAME$() { // Arrange$END$ // Act // Assert -} +} + diff --git a/Common.Test.props b/Common.Test.props index f0100ac..2cc1ee9 100644 --- a/Common.Test.props +++ b/Common.Test.props @@ -16,21 +16,19 @@ false + + + + $(NoWarn);CS8632;CA1707;IDE0058 + true - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + - - + + diff --git a/Common.props b/Common.props index 5cebd21..49be59a 100644 --- a/Common.props +++ b/Common.props @@ -31,7 +31,6 @@ https://github.com/AutoFixture/AutoFixture.TUnit true MIT - https://raw.githubusercontent.com/AutoFixture/AutoFixture.TUnit/master/AutoFixtureLogo200x200.png icon.png README.md $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb @@ -44,7 +43,7 @@ - + diff --git a/build/Build.cs b/build/Build.cs index e209985..a6e3de6 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Nuke.Common; @@ -45,7 +46,7 @@ class Build : NukeBuild [Solution("AutoFixture.TUnit.sln")] readonly Solution Solution; [GitRepository] readonly GitRepository GitRepository; - [GitVersion] readonly GitVersion GitVersion; + [GitVersion(NoFetch = true)] readonly GitVersion GitVersion; [CI] readonly GitHubActions GitHubActions; [Parameter("GitHub auth token", Name = "github-token"), Secret] readonly string GitHubToken; @@ -62,7 +63,8 @@ class Build : NukeBuild IEnumerable TestProjects => Solution.GetAllProjects("*Tests"); IEnumerable Libraries => Solution.Projects.Except(TestProjects).Except(Excluded); - IEnumerable CSharpLibraries => Libraries.Where(x => x.Is(ProjectType.CSharpProject)); + IEnumerable CSharpLibraries => + Libraries.Where(x => x.Path.ToString().EndsWith(".csproj", StringComparison.OrdinalIgnoreCase)); IEnumerable Packages => PackagesDirectory.GlobFiles("*.nupkg"); bool IsContinuousIntegration => IsServerBuild || CI; @@ -129,9 +131,10 @@ class Build : NukeBuild .SetResultsDirectory(TestResultsDirectory) .SetNoBuild(FinishedTargets.Contains(Compile)) .When(_ => InvokedTargets.Contains(Cover), _ => _ + // Do not pin a shared --coverage-output path: multi-TFM hosts race on one + // file and the empty net48 report can wipe populated net* coverage. .AddProcessAdditionalArguments("--") .AddProcessAdditionalArguments("--coverage") - .AddProcessAdditionalArguments("--coverage-output", TestResultsDirectory / "coverage.cobertura.xml") .AddProcessAdditionalArguments("--coverage-output-format", "cobertura"))); var testArchive = TestResultsDirectory / "TestResults.zip"; @@ -149,7 +152,7 @@ class Build : NukeBuild ReportGenerator(_ => _ .SetFramework("net8.0") .SetAssemblyFilters("-TestTypeFoundation*") - .SetReports(TestResultsDirectory / "**" / "coverage.cobertura.xml") + .SetReports(TestResultsDirectory / "**" / "*.cobertura.xml") .SetTargetDirectory(ReportsDirectory) .SetReportTypes("lcov", ReportTypes.HtmlInline)); diff --git a/build/_build.csproj b/build/_build.csproj index f422706..36fc409 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 CS0649;CS0169 .. @@ -16,8 +16,10 @@ + - + + From a509b81d88839a4c24bca29de3ee3ab127408df6 Mon Sep 17 00:00:00 2001 From: Andrei Ivascu <7030530+aivascu@users.noreply.github.com> Date: Mon, 7 Sep 2026 00:31:39 +0300 Subject: [PATCH 3/5] Reorganize tests and cover shapes, class-level, and generic Auto* scenarios. --- .../ArrayEdgeCaseScenarioTests.cs | 43 ++ .../ClassLevelScenarioTests.cs | 112 ++++ .../GenericClassLevelScenarioTests.cs | 53 ++ .../GenericUsageScenarioTests.cs | 62 ++ .../GetDataTests.cs} | 33 +- .../ScenarioTests.cs | 62 ++ .../AutoClassRowCollect.cs | 16 + .../ClassLevelScenarioTests.cs | 113 ++++ .../EmptySequenceRowTests.cs | 21 + .../GenericClassLevelScenarioTests.cs | 53 ++ .../GenericUsageScenarioTests.cs | 108 ++++ .../GetDataTests.cs} | 107 ++-- .../NullRowTests.cs | 21 + .../ResultShapeScenarioTests.cs | 79 +++ .../ScenarioTests.cs} | 14 +- .../UsageScenarioTests.cs | 128 ++++ .../ClassLevelScenarioTests.cs | 119 ++++ .../GetDataTests.cs} | 40 +- .../ScenarioTests.cs | 45 ++ .../AutoMemberRowCollect.cs | 17 + .../ClassLevelScenarioTests.cs | 130 ++++ .../ConstructionTests.cs | 67 +++ .../EmptySequenceRowTests.cs | 30 + .../GenericClassLevelScenarioTests.cs | 69 +++ .../GenericUsageScenarioTests.cs | 100 ++++ .../GetDataTests.cs} | 195 ++---- .../ResultShapeScenarioTests.cs | 138 +++++ .../ScenarioTests.cs} | 18 +- .../UsageScenarioTests.cs | 97 +++ .../ClassLevelScenarioTests.cs | 185 ++++++ .../ConstructionTests.cs} | 39 +- .../GetDataTests.cs} | 12 +- .../UsageScenarioTests.cs | 85 +++ .../CustomizeAttributeTests.cs} | 12 +- .../FavorArraysAttributeTests.cs} | 17 +- .../FavorEnumerablesAttributeTests.cs} | 17 +- .../FavorListsAttributeTests.cs} | 17 +- .../Customizations/FrozenAttributeTests.cs} | 12 +- .../Customizations/GreedyAttributeTests.cs} | 17 +- .../Customizations/ModestAttributeTests.cs} | 17 +- .../NoAutoPropertiesAttributeTests.cs} | 15 +- .../Customizations/ScenarioTests.cs | 337 +++++++++++ .../AutoFixture.TUnit.Tests.csproj | 23 +- .../DependencyConstraintsTests.cs | 10 +- .../Internal/ClassDataSourceTests.cs | 138 ----- .../DataGeneratorMetadataHelper.cs | 26 +- .../AutoDataSourceTests/CombineTests.cs} | 150 ++++- .../GetDataRowsAsyncTests.cs} | 32 +- .../ClassDataSourceTests/ConstructionTests.cs | 74 +++ .../ConstructionTests.cs} | 34 +- .../ConstructionTests.cs} | 34 +- .../ConstructionTests.cs} | 46 +- .../ConstructionTests.cs | 72 +++ .../ResultShapeLeftoverTests.cs | 33 + .../ConstructionTests.cs} | 48 +- .../Internal/MethodDataSourceTests.cs | 106 ---- tests/AutoFixture.TUnit.Tests/Scenario.cs | 563 ------------------ .../TestTypes/ChildTestTypeMethodData.cs | 4 +- .../TestTypes/ClassWithEmptyTestData.cs | 4 +- .../TestTypes/ClassWithExcessTestData.cs | 16 + .../TestTypes/ClassWithNullTestData.cs | 10 +- ...CompositeTypeWithOverloadedConstructors.cs | 4 +- .../DataSourceFixtures/ClassDataShapes.cs | 125 ++++ .../DataSourceFixtures/MemberDataShapes.cs | 84 +++ .../TestTypes/DelegatingCustomization.cs | 4 +- .../TestTypes/DelegatingCustomizeAttribute.cs | 4 +- .../TestTypes/DelegatingFixture.cs | 4 +- .../TestTypes/DelegatingMemberDataSource.cs | 4 +- .../TestTypes/DelegatingSpecimenBuilder.cs | 4 +- .../TestTypes/DelegatingTestData.cs | 4 +- .../DerivedAutoArgumentsAttribute.cs | 2 +- .../DerivedAutoClassDataSourceAttribute.cs | 4 +- .../DerivedAutoDataSourceAttribute.cs | 4 +- .../DerivedAutoMemberDataSourceAttribute.cs | 4 +- .../TestTypes/EmptyClassData.cs | 4 +- .../TestTypes/ExampleTestClass.cs | 7 +- .../TestTypes/FixedParameterBuilder.cs | 2 +- .../TestTypes/InlineAttributeTestData.cs | 2 +- .../TestTypes/InlineFrozenValuesTestData.cs | 2 +- .../InlinePrimitiveValuesTestData.cs | 2 +- .../TestTypes/MixedTypeClassData.cs | 4 +- .../TestTypes/MyClass.cs | 4 +- .../TestTypes/ParameterNameCriterion.cs | 2 +- .../TestTypes/ParameterizedClassData.cs | 4 +- .../TestTypes/SampleTestType.cs | 8 +- .../TestTypes/TestTypeWithMemberDataSource.cs | 5 +- .../TestTypes/TestTypeWithMethodData.cs | 2 +- .../TypeWithCustomizationAttributes.cs | 3 +- ...eWithIParameterCustomizationSourceUsage.cs | 4 +- .../AbstractClassWithPublicConstructor.cs | 4 +- .../TestTypeFoundation/AbstractGenericType.cs | 2 +- tests/TestTypeFoundation/AbstractType.cs | 4 +- ...peWithConstructorWithMultipleParameters.cs | 4 +- .../AbstractTypeWithNonDefaultConstructor.cs | 4 +- tests/TestTypeFoundation/ActivityScope.cs | 2 +- tests/TestTypeFoundation/CollectionHolder.cs | 4 +- tests/TestTypeFoundation/CompositeType.cs | 4 +- tests/TestTypeFoundation/ConcreteType.cs | 4 +- ...TypeWithPrivateParameterlessConstructor.cs | 4 +- tests/TestTypeFoundation/DoubleFieldHolder.cs | 4 +- .../TestTypeFoundation/DoubleParameterType.cs | 4 +- .../DoublePropertyHolder.cs | 4 +- tests/TestTypeFoundation/EmptyEnum.cs | 4 +- tests/TestTypeFoundation/EnumType.cs | 4 +- tests/TestTypeFoundation/EqualityResponder.cs | 4 +- tests/TestTypeFoundation/FieldHolder.cs | 4 +- tests/TestTypeFoundation/GenericType.cs | 2 +- .../GuardedConstructorHost.cs | 4 +- ...nstructorHostHoldingStaticReadOnlyField.cs | 4 +- ...ructorHostHoldingStaticReadOnlyProperty.cs | 4 +- tests/TestTypeFoundation/GuardedMethodHost.cs | 4 +- .../GuardedPropertyHolder.cs | 2 +- .../GuardedStaticMethodOnStaticTypeHost.cs | 2 +- tests/TestTypeFoundation/IInterface.cs | 4 +- .../IllBehavedPropertyHolder.cs | 2 +- .../IndexedPropertyHolder.cs | 4 +- .../InternalGetterPropertyHolder.cs | 4 +- tests/TestTypeFoundation/ItemContainer.cs | 4 +- tests/TestTypeFoundation/ItemHolder.cs | 4 +- .../MultiUnorderedConstructorType.cs | 4 +- tests/TestTypeFoundation/MutableValueType.cs | 4 +- .../MutableValueTypeWithoutConstructor.cs | 4 +- .../NonCompliantCollectionHolder.cs | 4 +- .../NoopInterfaceImplementer.cs | 4 +- .../Properties/AssemblyInfo.cs | 2 +- tests/TestTypeFoundation/PropertyHolder.cs | 4 +- .../QuadrupleParameterType.cs | 4 +- .../TestTypeFoundation/ReadOnlyFieldHolder.cs | 4 +- .../ReadOnlyPropertyHolder.cs | 4 +- tests/TestTypeFoundation/RecordType.cs | 2 +- .../TestTypeFoundation/SingleParameterType.cs | 4 +- tests/TestTypeFoundation/StaticFieldHolder.cs | 4 +- .../StaticPropertyHolder.cs | 4 +- .../TestTypeFoundation.csproj | 9 +- tests/TestTypeFoundation/TriState.cs | 4 +- .../TestTypeFoundation/TripleParameterType.cs | 4 +- .../TriplePropertyHolder.cs | 4 +- ...thCastOperatorsWithoutPublicConstructor.cs | 4 +- .../TypeWithConcreteParameterMethod.cs | 4 +- .../TypeWithEmptyEnumField.cs | 4 +- .../TypeWithFactoryMethod.cs | 4 +- .../TypeWithFactoryProperty.cs | 4 +- tests/TestTypeFoundation/TypeWithIndexer.cs | 4 +- .../TypeWithOverloadedMembers.cs | 4 +- .../TypeWithPseudoFactoryMethod.cs | 4 +- tests/TestTypeFoundation/TypeWithRefMethod.cs | 4 +- .../UnguardedConstructorHost.cs | 4 +- .../TestTypeFoundation/UnguardedMethodHost.cs | 4 +- .../UnguardedStaticMethodOnStaticTypeHost.cs | 4 +- ...UnguardedStaticPropertyOnStaticTypeHost.cs | 4 +- 150 files changed, 3380 insertions(+), 1454 deletions(-) create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ClassLevelScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericClassLevelScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericUsageScenarioTests.cs rename tests/AutoFixture.TUnit.Tests/{AutoArgumentsAttributeTests.cs => Attributes/AutoArgumentsAttributeTests/GetDataTests.cs} (79%) create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/AutoClassRowCollect.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/EmptySequenceRowTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs rename tests/AutoFixture.TUnit.Tests/{ClassAutoDataSourceAttributeTests.cs => Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs} (73%) create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/NullRowTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs rename tests/AutoFixture.TUnit.Tests/{ClassAutoDataSourceScenarioTests.cs => Attributes/AutoClassDataSourceAttributeTests/ScenarioTests.cs} (84%) create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ClassLevelScenarioTests.cs rename tests/AutoFixture.TUnit.Tests/{AutoDataSourceAttributeTests.cs => Attributes/AutoDataSourceAttributeTests/GetDataTests.cs} (79%) create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/AutoMemberRowCollect.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/EmptySequenceRowTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs rename tests/AutoFixture.TUnit.Tests/{MemberAutoDataSourceAttributeTest.cs => Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs} (63%) create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs rename tests/AutoFixture.TUnit.Tests/{MemberAutoDataSourceAttributeScenarioTests.cs => Attributes/AutoMemberDataSourceAttributeTests/ScenarioTests.cs} (90%) create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/UsageScenarioTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ClassLevelScenarioTests.cs rename tests/AutoFixture.TUnit.Tests/{CompositeDataSourceAttributeTest.cs => Attributes/CompositeDataSourceAttributeTests/ConstructionTests.cs} (66%) rename tests/AutoFixture.TUnit.Tests/{CompositeDataSourceAttributeSufficientDataTest.cs => Attributes/CompositeDataSourceAttributeTests/GetDataTests.cs} (94%) create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs rename tests/AutoFixture.TUnit.Tests/{CustomizeAttributeTest.cs => Attributes/Customizations/CustomizeAttributeTests.cs} (65%) rename tests/AutoFixture.TUnit.Tests/{FavorArraysAttributeTest.cs => Attributes/Customizations/FavorArraysAttributeTests.cs} (72%) rename tests/AutoFixture.TUnit.Tests/{FavorEnumerablesAttributeTest.cs => Attributes/Customizations/FavorEnumerablesAttributeTests.cs} (72%) rename tests/AutoFixture.TUnit.Tests/{FavorListsAttributeTest.cs => Attributes/Customizations/FavorListsAttributeTests.cs} (73%) rename tests/AutoFixture.TUnit.Tests/{FrozenAttributeTest.cs => Attributes/Customizations/FrozenAttributeTests.cs} (60%) rename tests/AutoFixture.TUnit.Tests/{GreedyAttributeTest.cs => Attributes/Customizations/GreedyAttributeTests.cs} (73%) rename tests/AutoFixture.TUnit.Tests/{ModestAttributeTest.cs => Attributes/Customizations/ModestAttributeTests.cs} (72%) rename tests/AutoFixture.TUnit.Tests/{NoAutoPropertiesAttributeTest.cs => Attributes/Customizations/NoAutoPropertiesAttributeTests.cs} (69%) create mode 100644 tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ScenarioTests.cs delete mode 100644 tests/AutoFixture.TUnit.Tests/Internal/ClassDataSourceTests.cs rename tests/AutoFixture.TUnit.Tests/{ => Internal/DataGeneratorMetadataSupport}/DataGeneratorMetadataHelper.cs (72%) rename tests/AutoFixture.TUnit.Tests/Internal/{AutoDataSourceTests.cs => DataSources/AutoDataSourceTests/CombineTests.cs} (57%) rename tests/AutoFixture.TUnit.Tests/Internal/{DataSourceTests.cs => DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs} (74%) create mode 100644 tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs rename tests/AutoFixture.TUnit.Tests/Internal/{FieldDataSourceTests.cs => DataSources/FieldDataSourceTests/ConstructionTests.cs} (71%) rename tests/AutoFixture.TUnit.Tests/Internal/{InlineDataSourceTests.cs => DataSources/InlineDataSourceTests/ConstructionTests.cs} (69%) rename tests/AutoFixture.TUnit.Tests/Internal/{MemberDataSourceTests.cs => DataSources/MemberDataSourceTests/ConstructionTests.cs} (62%) create mode 100644 tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs create mode 100644 tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs rename tests/AutoFixture.TUnit.Tests/Internal/{PropertyDataSourceTests.cs => DataSources/PropertyDataSourceTests/ConstructionTests.cs} (72%) delete mode 100644 tests/AutoFixture.TUnit.Tests/Internal/MethodDataSourceTests.cs delete mode 100644 tests/AutoFixture.TUnit.Tests/Scenario.cs create mode 100644 tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithExcessTestData.cs create mode 100644 tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/ClassDataShapes.cs create mode 100644 tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs new file mode 100644 index 0000000..3fd5aae --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs @@ -0,0 +1,43 @@ +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests; + +/// +/// Documents the params object?[] pitfall: a non-generic +/// [AutoArguments(new object[] { ... })] expands into separate cells, +/// while [AutoArguments<T[]>(...)] keeps the array as one argument. +/// +public class ArrayEdgeCaseScenarioTests +{ + [Test] + [AutoArguments(new object[] { 1, 2 })] + public async Task WhenNonGenericObjectArray_ExpandsIntoSeparateArguments(int a, int b) + { + await Assert.That(a).IsEqualTo(1); + await Assert.That(b).IsEqualTo(2); + } + + [Test] + [AutoArguments(new object[] { 1, 2 })] + public async Task WhenGenericObjectArray_KeepsArrayAsSingleArgument(object[] values, MyClass leftover) + { + await Assert.That(values).IsEquivalentTo(new object[] { 1, 2 }); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoArguments(new int[] { 1, 2 })] + public async Task WhenGenericIntArray_KeepsArrayAsSingleArgument(int[] values, MyClass leftover) + { + await Assert.That(values).IsEquivalentTo(new[] { 1, 2 }); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoArguments(new string[] { "a", "b" })] + public async Task WhenGenericStringArray_KeepsArrayAsSingleArgument(string[] values, MyClass leftover) + { + await Assert.That(values).IsEquivalentTo(new[] { "a", "b" }); + await Assert.That(leftover).IsNotNull(); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ClassLevelScenarioTests.cs new file mode 100644 index 0000000..2b3d16e --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ClassLevelScenarioTests.cs @@ -0,0 +1,112 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; +using ConcreteType = TestTypeFoundation.ConcreteType; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests; + +/// +/// End-to-end [AutoArguments] on the test class (TUnit ClassParameters). +/// Ordered simple → complex; mirrors AutoDataSource class-level scenarios. +/// +[AutoArguments("seed")] +public class ClassLevelPrimitiveScenarioTests(string name, int count) +{ + [Test] + public async Task WhenAppliedToClass_UsesInlineValueAndFillsRemaining() + { + await Assert.That(name).IsEqualTo("seed"); + await Assert.That(count).IsNotEqualTo(0); + } +} + +[AutoArguments("seed")] +public class ClassLevelComplexTypeScenarioTests( + string name, + PropertyHolder ph, + SingleParameterType spt, + MyClass sut) +{ + [Test] + public async Task WhenAppliedToClass_UsesInlineValueAndFillsComplexRemaining() + { + await Assert.That(name).IsEqualTo("seed"); + + await Assert.That(ph).IsNotNull(); + await Assert.That(ph.Property).IsNotNull(); + + await Assert.That(spt).IsNotNull(); + await Assert.That(spt.Parameter).IsNotNull(); + + await Assert.That(sut).IsNotNull(); + await Assert.That(sut.Echo(7)).IsEqualTo(7); + } +} + +[AutoArguments] +public class ClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second) +{ + [Test] + public async Task WhenFrozenOnConstructorParameter_SharesInstanceWithLaterParameter() + { + await Assert.That(second).IsEqualTo(first); + } +} + +[AutoArguments] +public class ClassLevelModestScenarioTests([Modest] MultiUnorderedConstructorType value) +{ + [Test] + public async Task WhenModestOnConstructorParameter_UsesModestConstructor() + { + await Assert.That(string.IsNullOrEmpty(value.Text)).IsTrue(); + await Assert.That(value.Number).IsEqualTo(0); + } +} + +[AutoArguments("from-inline")] +public class ClassLevelMultiConstructorParameterizedFirstScenarioTests +{ + private readonly string name; + + public ClassLevelMultiConstructorParameterizedFirstScenarioTests(string name) + { + this.name = name; + } + + public ClassLevelMultiConstructorParameterizedFirstScenarioTests() + { + this.name = "parameterless"; + } + + [Test] + public async Task WhenParameterizedConstructorDeclaredFirst_UsesInlineConstructorArgument() + { + await Assert.That(this.name).IsEqualTo("from-inline"); + } +} + +[AutoArguments(42)] +public class ClassLevelMultiConstructorIntFirstScenarioTests +{ + private readonly string name; + private readonly int count; + + public ClassLevelMultiConstructorIntFirstScenarioTests(int count) + { + this.name = "int-ctor"; + this.count = count; + } + + public ClassLevelMultiConstructorIntFirstScenarioTests(string name) + { + this.name = name; + this.count = -1; + } + + [Test] + public async Task WhenIntConstructorDeclaredFirst_UsesInlineIntArgument() + { + await Assert.That(this.name).IsEqualTo("int-ctor"); + await Assert.That(this.count).IsEqualTo(42); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericClassLevelScenarioTests.cs new file mode 100644 index 0000000..11df8af --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericClassLevelScenarioTests.cs @@ -0,0 +1,53 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; +using ConcreteType = TestTypeFoundation.ConcreteType; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests; + +/// +/// Class-level [AutoArguments<T>] scenarios parallel to the non-generic class-level set. +/// +[AutoArguments("seed")] +public class GenericClassLevelPrimitiveScenarioTests(string name, int count) +{ + [Test] + public async Task WhenGenericAppliedToClass_UsesInlineValueAndFillsRemaining() + { + await Assert.That(name).IsEqualTo("seed"); + await Assert.That(count).IsNotEqualTo(0); + } +} + +[AutoArguments("seed")] +public class GenericClassLevelComplexTypeScenarioTests( + string name, + PropertyHolder ph, + SingleParameterType spt, + MyClass sut) +{ + [Test] + public async Task WhenGenericAppliedToClass_UsesInlineValueAndFillsComplexRemaining() + { + await Assert.That(name).IsEqualTo("seed"); + + await Assert.That(ph).IsNotNull(); + await Assert.That(ph.Property).IsNotNull(); + + await Assert.That(spt).IsNotNull(); + await Assert.That(spt.Parameter).IsNotNull(); + + await Assert.That(sut).IsNotNull(); + await Assert.That(sut.Echo(7)).IsEqualTo(7); + } +} + +[AutoArguments("seed")] +public class GenericClassLevelFrozenScenarioTests(string name, [Frozen] Guid first, Guid second) +{ + [Test] + public async Task WhenGenericFrozenOnConstructorParameter_SharesInstanceWithLaterParameter() + { + await Assert.That(name).IsEqualTo("seed"); + await Assert.That(second).IsEqualTo(first); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericUsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericUsageScenarioTests.cs new file mode 100644 index 0000000..285400d --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericUsageScenarioTests.cs @@ -0,0 +1,62 @@ +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests; + +/// +/// End-to-end [AutoArguments<T>] usage parallel to the non-generic scenarios. +/// +public class GenericUsageScenarioTests +{ + [Test] + [AutoArguments("foo")] + public async Task WhenGenericInlineValueProvided_UsesSuppliedValueAndFillsRemaining(string s1, string s2) + { + await Assert.That(s1).IsEqualTo("foo"); + await Assert.That(s2).IsNotNull(); + } + + [Test] + [AutoArguments("foo")] + public async Task WhenGenericInlineValuePartial_SuppliesRemainingSpecimens( + string s1, string s2, MyClass myClass) + { + await Assert.That(s1).IsEqualTo("foo"); + await Assert.That(s2).IsNotNull(); + await Assert.That(myClass).IsNotNull(); + } + + [Test] + [AutoArguments("foo")] + public async Task WhenGenericInlineValuePartial_DoesNotOverwriteSuppliedValue( + string s1, string s2, string s3) + { + await Assert.That(s1).IsEqualTo("foo"); + await Assert.That(s2).IsNotNull(); + await Assert.That(s3).IsNotEqualTo("foo"); + } + + [Test] + [MyCustomAutoArguments(1337)] + public async Task WhenGenericCustomInlineAttribute_SuppliesExtraValues(int x, int y, int z) + { + await Assert.That(x).IsEqualTo(1337); + await Assert.That(y).IsNotEqualTo(0); + await Assert.That(z).IsEqualTo(42); + } + + public class MyCustomAutoArgumentsAttribute : AutoArgumentsAttribute + { + public MyCustomAutoArgumentsAttribute(T value) + : base(() => new Fixture().Customize(new TheAnswer()), value) + { + } + } + + private class TheAnswer : ICustomization + { + public void Customize(IFixture fixture) + { + fixture.Inject(42); + } + } +} diff --git a/tests/AutoFixture.TUnit.Tests/AutoArgumentsAttributeTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GetDataTests.cs similarity index 79% rename from tests/AutoFixture.TUnit.Tests/AutoArgumentsAttributeTests.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GetDataTests.cs index 9714b8d..030e829 100644 --- a/tests/AutoFixture.TUnit.Tests/AutoArgumentsAttributeTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GetDataTests.cs @@ -1,13 +1,14 @@ -using System.Reflection; +using System.Reflection; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests; public class AutoArgumentsAttributeTests { [Test] - public async Task SutIsDataAttribute() + public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute() { // Arrange & Act var sut = new AutoArgumentsAttribute(); @@ -17,7 +18,7 @@ public async Task SutIsDataAttribute() } [Test] - public async Task ValuesWillBeEmptyWhenSutIsCreatedWithDefaultConstructor() + public async Task Constructor_WhenDefault_ValuesAreEmpty() { // Arrange var sut = new AutoArgumentsAttribute(); @@ -31,7 +32,7 @@ public async Task ValuesWillBeEmptyWhenSutIsCreatedWithDefaultConstructor() } [Test] - public async Task ValuesWillNotBeEmptyWhenSutIsCreatedWithConstructorArguments() + public async Task Constructor_WhenArgumentsProvided_ValuesAreNotEmpty() { // Arrange var expectedValues = new[] { new object(), new object(), new object() }; @@ -45,7 +46,7 @@ public async Task ValuesWillNotBeEmptyWhenSutIsCreatedWithConstructorArguments() } [Test] - public async Task ValuesAreCorrectWhenConstructedWithExplicitAutoDataAttribute() + public async Task Constructor_WhenExplicitValuesProvided_ValuesMatch() { // Arrange var expectedValues = new[] { new object(), new object(), new object() }; @@ -59,7 +60,7 @@ public async Task ValuesAreCorrectWhenConstructedWithExplicitAutoDataAttribute() } [Test] - public async Task DoesntActivateFixtureImmediately() + public async Task Constructor_WhenCreated_DoesNotActivateFixtureImmediately() { // Arrange var wasInvoked = false; @@ -88,7 +89,7 @@ public async Task DoesntActivateFixtureImmediately() [Arguments("CreateWithModestAndFrozen")] [Arguments("CreateWithFrozenAndNoAutoProperties")] [Arguments("CreateWithNoAutoPropertiesAndFrozen")] - public async Task GetDataOrdersCustomizationAttributes(string methodName) + public async Task GetData_WhenCustomizationsPresent_OrdersThem(string methodName) { // Arrange var customizationLog = new List(); @@ -115,7 +116,7 @@ public async Task GetDataOrdersCustomizationAttributes(string methodName) [Test] [MethodDataSource(typeof(InlinePrimitiveValuesTestData), nameof(InlinePrimitiveValuesTestData.GetTestData))] [MethodDataSource(typeof(InlineFrozenValuesTestData), nameof(InlineFrozenValuesTestData.GetTestData))] - public async Task ReturnsSingleTestDataWithExpectedValues(BaseDataSourceAttribute attribute, MethodInfo testMethod, + public async Task GetData_WhenCalled_ReturnsSingleRowWithExpectedValues(BaseDataSourceAttribute attribute, MethodInfo testMethod, object[] expected) { // Act @@ -128,17 +129,17 @@ public async Task ReturnsSingleTestDataWithExpectedValues(BaseDataSourceAttribut [Test] [AutoArguments] - public async Task GeneratesRandomData(int a, float b, string c, decimal d) + public async Task WhenAutoArgumentsUsed_GeneratesNonDefaultValues(int a, float b, string c, decimal d) { await Assert.That(a).IsNotEqualTo(0); - await Assert.That(b).IsNotEqualTo(0); + await Assert.That(b).IsNotEqualTo(0f); await Assert.That(c).IsNotNull(); - await Assert.That(d).IsNotEqualTo(0); + await Assert.That(d).IsNotEqualTo(0m); } [Test] [AutoArguments(12, 32.1f, "hello", 71.231d)] - public async Task InlinesAllData(int a, float b, string c, decimal d) + public async Task WhenInlineValuesProvided_UsesAllSuppliedValues(int a, float b, string c, decimal d) { await Assert.That(a).IsEqualTo(12); await Assert.That(b).IsEqualTo(32.1f); @@ -157,12 +158,12 @@ public async Task InlinesAllData(int a, float b, string c, decimal d) [AutoArguments("\t\r\n")] [AutoArguments(" ")] [AutoArguments("")] - [AutoArguments([null!])] - public async Task InjectsInlineValues([Frozen] object a, + [AutoArguments([null])] + public async Task WhenMultipleInlineRows_InjectsInlineValues([Frozen] object a, [Frozen] PropertyHolder value, PropertyHolder frozen) { await Assert.That(value.Property).IsEqualTo(a); await Assert.That(value).IsSameReferenceAs(frozen); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ScenarioTests.cs new file mode 100644 index 0000000..006fe78 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ScenarioTests.cs @@ -0,0 +1,62 @@ +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests; + +public class ScenarioTests +{ + [Test] + [AutoArguments("foo")] + [AutoArguments("foo", "bar")] + public async Task WhenInlineValuesProvided_UsesSuppliedValues(string s1, string s2) + { + await Assert.That(s1).IsEqualTo("foo"); + await Assert.That(s2).IsNotNull(); + } + + [Test] + [AutoArguments("foo")] + [AutoArguments("foo", "bar")] + public async Task WhenInlineValuesPartial_SuppliesRemainingSpecimens(string s1, string s2, MyClass myClass) + { + await Assert.That(s1).IsEqualTo("foo"); + await Assert.That(s2).IsNotNull(); + await Assert.That(myClass).IsNotNull(); + } + + [Test] + [AutoArguments("foo")] + [AutoArguments("foo", "bar")] + public async Task WhenInlineValuesPartial_DoesNotOverwriteSuppliedValues(string s1, string s2, string s3) + { + await Assert.That(s1).IsEqualTo("foo"); + await Assert.That(s2).IsNotNull(); + await Assert.That(s3).IsNotEqualTo("foo"); + await Assert.That(s3).IsNotEqualTo("bar"); + } + + [Test] + [MyCustomAutoArguments(1337)] + [MyCustomAutoArguments(1337, 7)] + [MyCustomAutoArguments(1337, 7, 42)] + public async Task WhenCustomInlineAttribute_SuppliesExtraValues(int x, int y, int z) + { + await Assert.That(x).IsEqualTo(1337); + await Assert.That(z).IsEqualTo(42); + } + + public class MyCustomAutoArgumentsAttribute : AutoArgumentsAttribute + { + public MyCustomAutoArgumentsAttribute(params object[] values) + : base(() => new Fixture().Customize(new TheAnswer()), values) + { + } + } + + private class TheAnswer : ICustomization + { + public void Customize(IFixture fixture) + { + fixture.Inject(42); + } + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/AutoClassRowCollect.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/AutoClassRowCollect.cs new file mode 100644 index 0000000..28a560c --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/AutoClassRowCollect.cs @@ -0,0 +1,16 @@ +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests; + +internal static class AutoClassRowCollect +{ + public static object[][] FromType(Type sourceType, string testMethodName) + { + var sut = new AutoClassDataSourceAttribute(sourceType); + var testMethod = typeof(SampleTestType).GetMethod(testMethodName)!; + return sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) + .Select(x => x()) + .ToArray(); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs new file mode 100644 index 0000000..815e83b --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs @@ -0,0 +1,113 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; +using TestTypeFoundation; +using ConcreteType = TestTypeFoundation.ConcreteType; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests; + +/// +/// End-to-end [AutoClassDataSource] on the test class (TUnit ClassParameters). +/// Ordered simple → complex; mirrors AutoDataSource class-level scenarios. +/// +[AutoClassDataSource(typeof(StringSequenceClassData))] +public class ClassLevelPrimitiveScenarioTests(string name, int count) +{ + [Test] + public async Task WhenAppliedToClass_UsesClassValueAndFillsRemaining() + { + await Assert.That(new[] { "alpha", "beta" }).Contains(name); + await Assert.That(count).IsNotEqualTo(0); + } +} + +[AutoClassDataSource(typeof(StringSequenceClassData))] +public class ClassLevelComplexTypeScenarioTests( + string name, + PropertyHolder ph, + SingleParameterType spt, + MyClass sut) +{ + [Test] + public async Task WhenAppliedToClass_UsesClassValueAndFillsComplexRemaining() + { + await Assert.That(new[] { "alpha", "beta" }).Contains(name); + + await Assert.That(ph).IsNotNull(); + await Assert.That(ph.Property).IsNotNull(); + + await Assert.That(spt).IsNotNull(); + await Assert.That(spt.Parameter).IsNotNull(); + + await Assert.That(sut).IsNotNull(); + await Assert.That(sut.Echo(7)).IsEqualTo(7); + } +} + +[AutoClassDataSource(typeof(OneEmptyRowClassData))] +public class ClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second) +{ + [Test] + public async Task WhenFrozenOnConstructorParameter_SharesInstanceWithLaterParameter() + { + await Assert.That(second).IsEqualTo(first); + } +} + +[AutoClassDataSource(typeof(OneEmptyRowClassData))] +public class ClassLevelModestScenarioTests([Modest] MultiUnorderedConstructorType value) +{ + [Test] + public async Task WhenModestOnConstructorParameter_UsesModestConstructor() + { + await Assert.That(string.IsNullOrEmpty(value.Text)).IsTrue(); + await Assert.That(value.Number).IsEqualTo(0); + } +} + +[AutoClassDataSource(typeof(StringSequenceClassData))] +public class ClassLevelMultiConstructorParameterizedFirstScenarioTests +{ + private readonly string name; + + public ClassLevelMultiConstructorParameterizedFirstScenarioTests(string name) + { + this.name = name; + } + + public ClassLevelMultiConstructorParameterizedFirstScenarioTests() + { + this.name = "parameterless"; + } + + [Test] + public async Task WhenParameterizedConstructorDeclaredFirst_UsesClassConstructorArgument() + { + await Assert.That(new[] { "alpha", "beta" }).Contains(this.name); + } +} + +[AutoClassDataSource(typeof(IntSequenceClassData))] +public class ClassLevelMultiConstructorIntFirstScenarioTests +{ + private readonly string name; + private readonly int count; + + public ClassLevelMultiConstructorIntFirstScenarioTests(int count) + { + this.name = "int-ctor"; + this.count = count; + } + + public ClassLevelMultiConstructorIntFirstScenarioTests(string name) + { + this.name = name; + this.count = -1; + } + + [Test] + public async Task WhenIntConstructorDeclaredFirst_UsesClassIntArgument() + { + await Assert.That(this.name).IsEqualTo("int-ctor"); + await Assert.That(new[] { 11, 22 }).Contains(this.count); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/EmptySequenceRowTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/EmptySequenceRowTests.cs new file mode 100644 index 0000000..b49eefc --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/EmptySequenceRowTests.cs @@ -0,0 +1,21 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests; + +/// +/// Empty class sequences cannot be asserted via a [Test] body (no cases run), +/// so they stay as direct GetData checks. +/// +public class EmptySequenceRowTests +{ + [Test] + public async Task GetData_WhenClassYieldsEmptyAsyncSequence_YieldsNoRows() + { + var result = AutoClassRowCollect.FromType( + typeof(EmptyAsyncObjectArrayClassData), + nameof(SampleTestType.TestMethodWithTwoParameters)); + + await Assert.That(result).IsEmpty(); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs new file mode 100644 index 0000000..44d602f --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs @@ -0,0 +1,53 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; +using TestTypeFoundation; +using ConcreteType = TestTypeFoundation.ConcreteType; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests; + +/// +/// Class-level [AutoClassDataSource<T>] scenarios parallel to the non-generic class-level set. +/// +[AutoClassDataSource] +public class GenericClassLevelPrimitiveScenarioTests(string name, int count) +{ + [Test] + public async Task WhenGenericAppliedToClass_UsesClassValueAndFillsRemaining() + { + await Assert.That(new[] { "alpha", "beta" }).Contains(name); + await Assert.That(count).IsNotEqualTo(0); + } +} + +[AutoClassDataSource] +public class GenericClassLevelComplexTypeScenarioTests( + string name, + PropertyHolder ph, + SingleParameterType spt, + MyClass sut) +{ + [Test] + public async Task WhenGenericAppliedToClass_UsesClassValueAndFillsComplexRemaining() + { + await Assert.That(new[] { "alpha", "beta" }).Contains(name); + + await Assert.That(ph).IsNotNull(); + await Assert.That(ph.Property).IsNotNull(); + + await Assert.That(spt).IsNotNull(); + await Assert.That(spt.Parameter).IsNotNull(); + + await Assert.That(sut).IsNotNull(); + await Assert.That(sut.Echo(7)).IsEqualTo(7); + } +} + +[AutoClassDataSource] +public class GenericClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second) +{ + [Test] + public async Task WhenGenericFrozenOnConstructorParameter_SharesInstanceWithLaterParameter() + { + await Assert.That(second).IsEqualTo(first); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs new file mode 100644 index 0000000..5838de6 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs @@ -0,0 +1,108 @@ +using System.Collections; +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests; + +/// +/// End-to-end [AutoClassDataSource<T>] usage parallel to the non-generic scenarios. +/// +public class GenericUsageScenarioTests +{ + [Test, AutoClassDataSource] + public async Task WhenGenericClassSuppliesValues_UsesSuppliedValues(string s1, string s2, string s3) + { + await Assert.That(new[] { "foo", "dim" }).Contains(s1); + await Assert.That(s2).IsNotEmpty(); + await Assert.That(s3).IsNotEmpty(); + } + + [Test, AutoClassDataSource] + public async Task WhenGenericClassValuesPartial_SuppliesRemainingSpecimens( + string s1, string s2, string s3, MyClass myClass) + { + await Assert.That(s1).IsNotEmpty(); + await Assert.That(s2).IsNotEmpty(); + await Assert.That(s3).IsNotEmpty(); + await Assert.That(myClass).IsNotNull(); + } + + [Test, AutoClassDataSource(28, "bar", 93.102)] + public async Task WhenGenericClassDataParameterized_ReceivesExpectedData( + int p1, string p2, double p3, RecordType p4) + { + var actual = new object[] { p1, p2, p3 }; + var expected = new object[] { 28, "bar", 93.102 }; + + await Assert.That(actual).IsEquivalentTo(expected); + await Assert.That(p4).IsNotNull(); + } + + [Test, MyCustomAutoClassDataSource] + public async Task WhenGenericCustomClassAttribute_SuppliesExtraValues(int x, int y, int z) + { + await Assert.That(x).IsEqualTo(1337); + await Assert.That(y).IsNotEqualTo(0); + await Assert.That(z).IsEqualTo(42); + } + + public class StringDataClass : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return ["foo", "bar", "foobar"]; + yield return ["dim", "sum", "dimsum"]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + } + + public class ParameterizedDataClass : IEnumerable + { + private readonly int p1; + private readonly string p2; + private readonly double p3; + + public ParameterizedDataClass(int p1, string p2, double p3) + { + this.p1 = p1; + this.p2 = p2; + this.p3 = p3; + } + + public IEnumerator GetEnumerator() + { + yield return [this.p1, this.p2, this.p3]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + } + + public class IntDataClass : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return [1337]; + yield return [1337, 7]; + yield return [1337, 7, 42]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + } + + public class MyCustomAutoClassDataSourceAttribute : AutoClassDataSourceAttribute + { + public MyCustomAutoClassDataSourceAttribute(params object[] parameters) + : base(() => new Fixture().Customize(new TheAnswer()), parameters) + { + } + } + + private class TheAnswer : ICustomization + { + public void Customize(IFixture fixture) + { + fixture.Inject(42); + } + } +} diff --git a/tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceAttributeTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs similarity index 73% rename from tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceAttributeTests.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs index 9018b1a..b61fa99 100644 --- a/tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceAttributeTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs @@ -1,23 +1,23 @@ -using System.Collections; +using System.Collections; using AutoFixture.Kernel; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -using TUnit.Assertions.Extensions; using ConcreteType = TestTypeFoundation.ConcreteType; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests; public class ClassAutoDataSourceAttributeTests { [Test] - public void CanCreateInstance() + public void Constructor_WhenCreated_CanCreateInstance() { // Act & Assert _ = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData)); } [Test] - public async Task IsDataAttribute() + public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute() { // Arrange & Act var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData)); @@ -27,17 +27,17 @@ public async Task IsDataAttribute() } [Test] - public async Task ThrowsWhenSourceTypeIsNull() + public async Task Constructor_WhenSourceTypeIsNull_Throws() { // Act & Assert - await Assert.That(() => new AutoClassDataSourceAttribute(null!)).ThrowsExactly(); + await Assert.That(() => new AutoClassDataSourceAttribute(null)).ThrowsExactly(); } [Test] - public async Task TreatsNullParameterValueAsArrayWithNull() + public async Task Constructor_WhenParameterValueIsNull_TreatsAsArrayWithNull() { // Arrange & Act - var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData), null!); + var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData), null); // Assert await Assert.That(sut.Parameters).HasSingleItem() @@ -46,47 +46,52 @@ await Assert.That(sut.Parameters).HasSingleItem() } [Test] - public async Task ThrowsWhenFixtureFactoryIsNull() + public async Task Constructor_WhenFixtureFactoryIsNull_Throws() { // Act & Assert await Assert.That(() => new DerivedAutoClassDataSourceAttribute( - fixtureFactory: null!, typeof(MixedTypeClassData))).ThrowsExactly(); + fixtureFactory: null, typeof(MixedTypeClassData))).ThrowsExactly(); } [Test] - public async Task GetDataThrowsWhenSourceTypeNotEnumerable() + public async Task GetData_WhenSourceTypeIsScalar_ReturnsSingleRow() { // Arrange var sut = new AutoClassDataSourceAttribute(typeof(MyClass)); var testMethod = typeof(ExampleTestClass) .GetMethod(nameof(ExampleTestClass.TestMethod)); - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) - .Select(x => x()).ToArray()).ThrowsExactly(); + // Act + var data = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) + .Select(x => x()).ToArray(); + + // Assert — scalar class instance is one supplied argument; remaining are auto-generated + await Assert.That(data.Length).IsEqualTo(1); + await Assert.That(data[0].Length).IsEqualTo(testMethod.GetParameters().Length); + await Assert.That(data[0][0]).IsAssignableTo(); } [Test] - public async Task GetDataThrowsWhenParametersDoNotMatchConstructor() + public async Task GetData_WhenParametersDoNotMatchConstructor_Throws() { // Arrange - var sut = new AutoClassDataSourceAttribute(typeof(MyClass), "myString", 33, null!); + var sut = new AutoClassDataSourceAttribute(typeof(MyClass), "myString", 33, null); var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod)); // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) + await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) .Select(x => x()).ToArray()).ThrowsException(); } [Test] - public async Task GetDataDoesNotThrowWhenSourceYieldsNoResults() + public async Task GetData_WhenSourceYieldsNoResults_DoesNotThrow() { // Arrange var sut = new AutoClassDataSourceAttribute(typeof(EmptyClassData)); var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod)); // Act - var data = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) + var data = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) ; // Assert @@ -94,91 +99,91 @@ public async Task GetDataDoesNotThrowWhenSourceYieldsNoResults() } [Test] - public async Task GetDataThrowsWhenSourceYieldsNullResults() + public async Task GetData_WhenSourceYieldsNullResults_Throws() { // Arrange var sut = new AutoClassDataSourceAttribute(typeof(ClassWithNullTestData)); var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod)); // Act & assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) + await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) .Select(x => x()).ToArray()).ThrowsException(); } [Test] - public void GetDataDoesNotThrow() + public void GetData_WhenCalled_DoesNotThrow() { // Arrange var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData)); var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod)); // Act & Assert - sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)); + sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)); } [Test] - public async Task GetDataReturnsEnumerable() + public async Task GetData_WhenCalled_ReturnsEnumerable() { // Arrange var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData)); var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod)); // Act - var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)); + var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)); // Assert await Assert.That(actual).IsNotNull(); } [Test] - public async Task GetDataReturnsNonEmptyEnumerable() + public async Task GetData_WhenCalled_ReturnsNonEmptyEnumerable() { // Arrange var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData)); var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod)); // Act - var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)); + var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)); // Assert await Assert.That(actual).IsNotEmpty(); } [Test] - public async Task GetDataReturnsExpectedTestDataCount() + public async Task GetData_WhenCalled_ReturnsExpectedRowCount() { // Arrange var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData)); var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod)); // Act - var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)); + var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)); // Assert - await Assert.That(actual).HasCount().EqualTo(5); + await Assert.That(actual).Count().IsEqualTo(5); } [Test] - public async Task GetDataThrowsWhenDataSourceNotEnumerable() + public async Task GetData_WhenDataSourceNotEnumerable_Throws() { // Arrange var sut = new AutoClassDataSourceAttribute(typeof(GuardedConstructorHost)); var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod)); // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) + await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) .Select(x => x()).ToArray()).ThrowsException(); } [Test] - public async Task GetDataThrowsForNonMatchingConstructorTypes() + public async Task GetData_WhenConstructorTypesDoNotMatch_Throws() { // Arrange - var sut = new AutoClassDataSourceAttribute(typeof(DelegatingTestData), "myString", 33, null!); + var sut = new AutoClassDataSourceAttribute(typeof(DelegatingTestData), "myString", 33, null); var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod)); // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) + await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) .Select(x => x()).ToArray()).ThrowsException(); } @@ -195,7 +200,7 @@ await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.Crea [Arguments("CreateWithModestAndFrozen")] [Arguments("CreateWithFrozenAndNoAutoProperties")] [Arguments("CreateWithNoAutoPropertiesAndFrozen")] - public async Task GetDataOrdersCustomizationAttributes(string methodName) + public async Task GetData_WhenCustomizationsPresent_OrdersThem(string methodName) { // Arrange var method = typeof(TypeWithCustomizationAttributes) @@ -209,7 +214,7 @@ public async Task GetDataOrdersCustomizationAttributes(string methodName) var sut = new DerivedAutoClassDataSourceAttribute(() => fixture, typeof(ClassWithEmptyTestData)); // Act - _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)) + _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) .Select(x => x()) .ToArray(); @@ -223,7 +228,7 @@ public async Task GetDataOrdersCustomizationAttributes(string methodName) } [Test] - public async Task GetDataReturnsExpectedTestData() + public async Task GetData_WhenCalled_ReturnsExpectedTestData() { var builder = new CompositeSpecimenBuilder( new FixedParameterBuilder("a", 1), @@ -243,7 +248,7 @@ public async Task GetDataReturnsExpectedTestData() [-95, "test-92", EnumType.Second, new Tuple("myValue", 5)] ]; - var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) + var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) .Select(x => x()) .ToArray(); @@ -251,7 +256,7 @@ public async Task GetDataReturnsExpectedTestData() } [Test] - public async Task GetDataReturnsExpectedTestDataFromParameterizedSource() + public async Task GetData_WhenParameterizedSource_ReturnsExpectedTestData() { var builder = new CompositeSpecimenBuilder( new FixedParameterBuilder("a", 1), @@ -268,7 +273,7 @@ public async Task GetDataReturnsExpectedTestDataFromParameterizedSource() [29, "myValue", EnumType.Third, new Tuple("value", 1)] ]; - var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) + var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) .Select(x => x()) .ToArray(); @@ -276,7 +281,7 @@ public async Task GetDataReturnsExpectedTestDataFromParameterizedSource() } [Test] - public async Task TestWithNullParametersPasses() + public async Task WhenNullParameters_Passes() { // Arrange var sut = new AutoClassDataSourceAttribute(typeof(TestDataWithNullValues)); @@ -284,13 +289,13 @@ public async Task TestWithNullParametersPasses() .GetMethod(nameof(ExampleTestClass>.TestMethod)); var expected = new[] { - new object[] { null!, null!, null!, null! }, - new object[] { string.Empty, null!, null!, null! }, - new object[] { null!, " ", null!, null! }, + new object[] { null, null, null, null }, + new object[] { string.Empty, null, null, null }, + new object[] { null, " ", null, null }, }; // Act - var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) + var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) .Select(x => x()) .ToArray(); @@ -302,9 +307,9 @@ public class TestDataWithNullValues : IEnumerable { public IEnumerator GetEnumerator() { - yield return [null!, null!, null!, null!]; - yield return [string.Empty, null!, null!, null!]; - yield return [null!, " ", null!, null!]; + yield return [null, null, null, null]; + yield return [string.Empty, null, null, null]; + yield return [null, " ", null, null]; } IEnumerator IEnumerable.GetEnumerator() @@ -312,4 +317,4 @@ IEnumerator IEnumerable.GetEnumerator() return this.GetEnumerator(); } } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/NullRowTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/NullRowTests.cs new file mode 100644 index 0000000..56f822e --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/NullRowTests.cs @@ -0,0 +1,21 @@ +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests; + +public class NullRowTests +{ + [Test] + public async Task GetData_WhenClassYieldsNullRows_ThrowsInvalidOperationException() + { + var sut = new AutoClassDataSourceAttribute(typeof(ClassWithNullTestData)); + var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod); + + var act = () => sut.GenerateDataSources(metadata) + .Select(row => row()) + .ToArray(); + + await Assert.That(act).ThrowsExactly(); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs new file mode 100644 index 0000000..5848b9b --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs @@ -0,0 +1,79 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests; + +/// +/// End-to-end [AutoClassDataSource] coverage for README result shapes. +/// +public class ResultShapeScenarioTests +{ + [Test] + [AutoClassDataSource(typeof(StringSequenceClassData))] + public async Task WhenClassYieldsStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover) + { + await Assert.That(new[] { "alpha", "beta" }).Contains(value); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoClassDataSource(typeof(TupleSequenceClassData))] + public async Task WhenClassYieldsTuples_ExpandsColumnsAndFillsRemaining( + string left, int right, MyClass leftover) + { + await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoClassDataSource(typeof(ObjectArrayClassData))] + public async Task WhenClassYieldsObjectArrays_UsesSuppliedValues( + string a, int b, RecordType c) + { + await Assert.That(new[] + { + ("hello", 1, "world"), + ("foo", 2, "bar") + }).Contains((a, b, c.Value)); + } + + [Test] + [AutoClassDataSource(typeof(AsyncObjectArrayClassData))] + public async Task WhenClassYieldsAsyncObjectArrays_UsesSuppliedValues( + string a, int b, RecordType c) + { + await Assert.That(new[] + { + ("hello", 1, "world"), + ("foo", 2, "bar") + }).Contains((a, b, c.Value)); + } + + [Test] + [AutoClassDataSource(typeof(AsyncStringSequenceClassData))] + public async Task WhenClassYieldsAsyncStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover) + { + await Assert.That(new[] { "alpha", "beta" }).Contains(value); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoClassDataSource(typeof(AsyncTupleSequenceClassData))] + public async Task WhenClassYieldsAsyncTuples_ExpandsColumnsAndFillsRemaining( + string left, int right, MyClass leftover) + { + await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoClassDataSource(typeof(StringScalarClassData))] + public async Task WhenClassIsScalar_UsesInstanceAsCellAndFillsRemaining( + StringScalarClassData seed, MyClass leftover) + { + await Assert.That(seed).IsNotNull(); + await Assert.That(seed.Value).IsEqualTo("seed"); + await Assert.That(leftover).IsNotNull(); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ScenarioTests.cs similarity index 84% rename from tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceScenarioTests.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ScenarioTests.cs index 6489839..1218dad 100644 --- a/tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ScenarioTests.cs @@ -1,13 +1,13 @@ -using AutoFixture.TUnit.Tests.TestTypes; +using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests; public class ClassAutoDataSourceScenarioTests { [Test] [AutoClassDataSource(typeof(MixedTypeClassData))] - public async Task TestWithMixedTypesPasses(int? a, string b, EnumType? c, Tuple d) + public async Task WhenMixedTypes_Passes(int? a, string b, EnumType? c, Tuple d) { await Assert.That(a).IsNotNull(); await Assert.That(b).IsNotNull(); @@ -17,7 +17,7 @@ public async Task TestWithMixedTypesPasses(int? a, string b, EnumType? c, Tuple< [Test] [AutoClassDataSource(typeof(ParameterizedClassData), 42, "test-13", EnumType.Third)] - public async Task TestWithParameterizedClassDataReceivesExpectedData( + public async Task WhenParameterizedClassData_ReceivesExpectedData( int a, string b, EnumType c, PropertyHolder d) { await Assert.That(a).IsEqualTo(42); @@ -28,7 +28,7 @@ public async Task TestWithParameterizedClassDataReceivesExpectedData( [Test] [AutoClassDataSource(typeof(ParameterizedClassData), 13, "test-46", EnumType.Second)] - public async Task TestWithFrozenParametersReceivesExpectedData( + public async Task WhenFrozenParameters_ReceivesExpectedData( [Frozen] int a, [Frozen] string b, [Frozen] EnumType c, PropertyHolder a1, PropertyHolder b1, PropertyHolder c1) { @@ -43,7 +43,7 @@ public async Task TestWithFrozenParametersReceivesExpectedData( [Test] [AutoClassDataSource(typeof(ParameterizedClassData), 59, "hello-world", EnumType.Second)] - public async Task TestWithInjectedValuesRespectsOtherParameterCustomizations( + public async Task WhenInjectedValues_RespectsOtherParameterCustomizations( [Frozen] int a, [Frozen] string b, [Frozen] EnumType c, [FavorEnumerables] CompositeTypeWithOverloadedConstructors numbers, [FavorArrays] CompositeTypeWithOverloadedConstructors strings, @@ -60,4 +60,4 @@ public async Task TestWithInjectedValuesRespectsOtherParameterCustomizations( await Assert.That(enums.Items).IsAssignableTo>(); await Assert.That(enums.Items).All().Satisfy(item => item.IsEqualTo(c)); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs new file mode 100644 index 0000000..9201d36 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs @@ -0,0 +1,128 @@ +using System.Collections; +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests; + +/// +/// End-to-end [AutoClassDataSource] usage moved from the old Scenarios bucket. +/// +public class UsageScenarioTests +{ + [Test, AutoClassDataSource(typeof(StringDataClass))] + public async Task WhenClassSuppliesValues_UsesSuppliedValues(string s1, string s2, string s3) + { + await Assert.That(new[] { "foo", "dim" }).Contains(s1); + await Assert.That(s2).IsNotEmpty(); + await Assert.That(s3).IsNotEmpty(); + } + + [Test, AutoClassDataSource(typeof(StringDataClass))] + public async Task WhenClassValuesPartial_SuppliesRemainingSpecimens(string s1, string s2, string s3, MyClass myClass) + { + await Assert.That(s1).IsNotEmpty(); + await Assert.That(s2).IsNotEmpty(); + await Assert.That(s3).IsNotEmpty(); + await Assert.That(myClass).IsNotNull(); + } + + [Test, AutoClassDataSource(typeof(MixedDataClass))] + public async Task WhenMixedTypes_SuppliesExpectedData(int p1, string p2, PropertyHolder p3, MyClass myClass) + { + await Assert.That(p1).IsNotEqualTo(0); + await Assert.That(p2).IsNotEmpty(); + await Assert.That(p3).IsNotNull(); + await Assert.That(p3.Property).IsNotEmpty(); + await Assert.That(myClass).IsNotNull(); + } + + [Test, AutoClassDataSource(typeof(ParameterizedDataClass), 28, "bar", 93.102)] + public async Task WhenClassDataParameterized_ReceivesExpectedData(int p1, string p2, double p3, RecordType p4) + { + var actual = new object[] { p1, p2, p3 }; + var expected = new object[] { 28, "bar", 93.102 }; + + await Assert.That(actual).IsEquivalentTo(expected); + await Assert.That(p4).IsNotNull(); + } + + [Test, MyCustomAutoClassDataSource(typeof(IntDataClass))] + public async Task WhenCustomClassAttribute_SuppliesExtraValues(int x, int y, int z) + { + await Assert.That(x).IsEqualTo(1337); + await Assert.That(y).IsNotEqualTo(0); + await Assert.That(z).IsEqualTo(42); + } + + public class StringDataClass : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return ["foo", "bar", "foobar"]; + yield return ["dim", "sum", "dimsum"]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + } + + public class MixedDataClass : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return [1]; + yield return [4, "testValue"]; + yield return [20, "otherValue", new PropertyHolder { Property = "testValue1" }]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + } + + public class ParameterizedDataClass : IEnumerable + { + private readonly int p1; + private readonly string p2; + private readonly double p3; + + public ParameterizedDataClass(int p1, string p2, double p3) + { + this.p1 = p1; + this.p2 = p2; + this.p3 = p3; + } + + public IEnumerator GetEnumerator() + { + yield return [this.p1, this.p2, this.p3]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + } + + public class IntDataClass : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return [1337]; + yield return [1337, 7]; + yield return [1337, 7, 42]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + } + + public class MyCustomAutoClassDataSourceAttribute : AutoClassDataSourceAttribute + { + public MyCustomAutoClassDataSourceAttribute(Type sourceType, params object[] parameters) + : base(() => new Fixture().Customize(new TheAnswer()), sourceType, parameters) + { + } + } + + private class TheAnswer : ICustomization + { + public void Customize(IFixture fixture) + { + fixture.Inject(42); + } + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ClassLevelScenarioTests.cs new file mode 100644 index 0000000..8dd18a7 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ClassLevelScenarioTests.cs @@ -0,0 +1,119 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; +using ConcreteType = TestTypeFoundation.ConcreteType; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoDataSourceAttributeTests; + +/// +/// End-to-end [AutoDataSource] on the test class (TUnit ClassParameters). +/// Ordered simple → complex. +/// +[AutoDataSource] +public class ClassLevelPrimitiveScenarioTests(string name, int count) +{ + [Test] + public async Task WhenAppliedToClass_FillsPrimitiveConstructorParameters() + { + await Assert.That(name).IsNotEmpty(); + await Assert.That(count).IsNotEqualTo(0); + } +} + +[AutoDataSource] +public class ClassLevelComplexTypeScenarioTests( + PropertyHolder ph, + SingleParameterType spt, + MyClass sut) +{ + [Test] + public async Task WhenAppliedToClass_FillsComplexConstructorParameters() + { + await Assert.That(ph).IsNotNull(); + await Assert.That(ph.Property).IsNotNull(); + + await Assert.That(spt).IsNotNull(); + await Assert.That(spt.Parameter).IsNotNull(); + + await Assert.That(sut).IsNotNull(); + await Assert.That(sut.Echo(7)).IsEqualTo(7); + } +} + +[AutoDataSource] +public class ClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second) +{ + [Test] + public async Task WhenFrozenOnConstructorParameter_SharesInstanceWithLaterParameter() + { + await Assert.That(second).IsEqualTo(first); + } +} + +[AutoDataSource] +public class ClassLevelModestScenarioTests([Modest] MultiUnorderedConstructorType value) +{ + [Test] + public async Task WhenModestOnConstructorParameter_UsesModestConstructor() + { + await Assert.That(string.IsNullOrEmpty(value.Text)).IsTrue(); + await Assert.That(value.Number).IsEqualTo(0); + } +} + +/// +/// Parameterized constructor is declared first so TUnit Class.Parameters describe it. +/// A parameterless overload exists so GetConstructors().First() is not a reliable match. +/// +[AutoDataSource] +public class ClassLevelMultiConstructorParameterizedFirstScenarioTests +{ + private readonly string name; + + public ClassLevelMultiConstructorParameterizedFirstScenarioTests(string name) + { + this.name = name; + } + + public ClassLevelMultiConstructorParameterizedFirstScenarioTests() + { + this.name = "parameterless"; + } + + [Test] + public async Task WhenParameterizedConstructorDeclaredFirst_FillsMatchingConstructor() + { + await Assert.That(this.name).IsNotEqualTo("parameterless"); + await Assert.That(this.name).IsNotEmpty(); + } +} + +/// +/// Two parameterized constructors: int overload is declared first, so TUnit Class.Parameters +/// describe that constructor and AutoDataSource fills it. +/// +[AutoDataSource] +public class ClassLevelMultiConstructorIntFirstScenarioTests +{ + private readonly string name; + private readonly int count; + + public ClassLevelMultiConstructorIntFirstScenarioTests(int count) + { + this.name = "int-ctor"; + this.count = count; + } + + public ClassLevelMultiConstructorIntFirstScenarioTests(string name) + { + this.name = name; + this.count = -1; + } + + [Test] + public async Task WhenIntConstructorDeclaredFirst_FillsIntConstructor() + { + await Assert.That(this.name).IsEqualTo("int-ctor"); + await Assert.That(this.count).IsNotEqualTo(0); + await Assert.That(this.count).IsNotEqualTo(-1); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/AutoDataSourceAttributeTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/GetDataTests.cs similarity index 79% rename from tests/AutoFixture.TUnit.Tests/AutoDataSourceAttributeTests.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/GetDataTests.cs index a7da5ec..dd89c68 100644 --- a/tests/AutoFixture.TUnit.Tests/AutoDataSourceAttributeTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/GetDataTests.cs @@ -1,15 +1,15 @@ -using AutoFixture.Kernel; +using AutoFixture.Kernel; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -using TUnit.Assertions.Extensions; using ConcreteType = TestTypeFoundation.ConcreteType; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.AutoDataSourceAttributeTests; public class AutoDataSourceAttributeTests { [Test] - public async Task SutIsDataAttribute() + public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute() { // Arrange & Act var sut = new AutoDataSourceAttribute(); @@ -19,7 +19,7 @@ public async Task SutIsDataAttribute() } [Test] - public async Task InitializedWithDefaultConstructorHasCorrectFixture() + public async Task Constructor_WhenDefault_HasCorrectFixture() { // Arrange var sut = new AutoDataSourceAttribute(); @@ -32,7 +32,7 @@ public async Task InitializedWithDefaultConstructorHasCorrectFixture() } [Test] - public async Task InitializedWithFixtureFactoryConstructorHasCorrectFixture() + public async Task Constructor_WhenFixtureFactoryProvided_HasCorrectFixture() { // Arrange var fixture = new Fixture(); @@ -45,16 +45,16 @@ public async Task InitializedWithFixtureFactoryConstructorHasCorrectFixture() } [Test] - public async Task InitializeWithNullFixtureFactoryThrows() + public async Task Constructor_WhenFixtureFactoryIsNull_Throws() { // Arrange // Act & Assert await Assert.That(() => - new DerivedAutoDataSourceAttribute(null!)).ThrowsExactly(); + new DerivedAutoDataSourceAttribute(null)).ThrowsExactly(); } [Test] - public async Task DoesntActivateFixtureImmediately() + public async Task Constructor_WhenCreated_DoesNotActivateFixtureImmediately() { // Arrange var wasInvoked = false; @@ -63,7 +63,7 @@ public async Task DoesntActivateFixtureImmediately() _ = new DerivedAutoDataSourceAttribute(() => { wasInvoked = true; - return null!; + return null; }); // Assert @@ -71,26 +71,26 @@ public async Task DoesntActivateFixtureImmediately() } [Test] - public async Task GetDataWithNullMethodThrows() + public async Task GetData_WhenMethodIsNull_Throws() { // Arrange var sut = new AutoDataSourceAttribute(); // Act & assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(null!, null!))).ThrowsException(); + await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(null, null))).ThrowsException(); } [Test] - public async Task GetDataReturnsCorrectResult() + public async Task GetData_WhenCalled_ReturnsCorrectResult() { // Arrange var method = typeof(TypeWithOverloadedMembers) .GetMethod("DoSomething", [typeof(object)]); - var parameters = method!.GetParameters(); + var parameters = method.GetParameters(); var expectedResult = new object(); - object actualParameter = null!; - ISpecimenContext actualContext = null!; + object actualParameter = null; + ISpecimenContext actualContext = null; var builder = new DelegatingSpecimenBuilder { OnCreate = (r, c) => @@ -111,7 +111,7 @@ public async Task GetDataReturnsCorrectResult() // Assert await Assert.That(actualContext).IsNotNull(); await Assert.That(parameters).HasSingleItem(); - await Assert.That(actualParameter).IsEqualTo(parameters[0]); + await Assert.That(actualParameter).IsSameReferenceAs(parameters[0]); await Assert.That(result.Single()).IsEquivalentTo(new[] { expectedResult }); } @@ -128,7 +128,7 @@ public async Task GetDataReturnsCorrectResult() [Arguments("CreateWithModestAndFrozen")] [Arguments("CreateWithFrozenAndNoAutoProperties")] [Arguments("CreateWithNoAutoPropertiesAndFrozen")] - public async Task GetDataOrdersCustomizationAttributes(string methodName) + public async Task GetData_WhenCustomizationsPresent_OrdersThem(string methodName) { // Arrange var method = typeof(TypeWithCustomizationAttributes) @@ -155,7 +155,7 @@ public async Task GetDataOrdersCustomizationAttributes(string methodName) } [Test] - public async Task ShouldRecognizeAttributesImplementingIParameterCustomizationSource() + public async Task GetData_WhenParameterImplementsIParameterCustomizationSource_AppliesCustomization() { // Arrange var method = typeof(TypeWithIParameterCustomizationSourceUsage) @@ -176,4 +176,4 @@ public async Task ShouldRecognizeAttributesImplementingIParameterCustomizationSo // Assert await Assert.That(customizationLog[0]).IsAssignableTo(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ScenarioTests.cs new file mode 100644 index 0000000..47f7a1d --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ScenarioTests.cs @@ -0,0 +1,45 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; +using ConcreteType = TestTypeFoundation.ConcreteType; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoDataSourceAttributeTests; + +public class ScenarioTests +{ + [Test, AutoDataSource] + public async Task WhenIntegerParameter_ProvidesNonDefaultValue(int primitiveValue) + { + await Assert.That(primitiveValue).IsNotEqualTo(0); + } + + [Test, AutoDataSource] + public async Task WhenStringParameter_ProvidesNonDefaultValue(string text) + { + await Assert.That(text).StartsWith("text"); + } + + [Test, AutoDataSource] + public async Task WhenObjectParameter_ProvidesNonNullInstance(PropertyHolder ph) + { + await Assert.That(ph).IsNotNull(); + await Assert.That(ph.Property).IsNotNull(); + } + + [Test, AutoDataSource] + public async Task WhenMultipleParameters_ProvidesNonNullInstances(PropertyHolder ph, SingleParameterType spt) + { + await Assert.That(ph).IsNotNull(); + await Assert.That(ph.Property).IsNotNull(); + + await Assert.That(spt).IsNotNull(); + await Assert.That(spt.Parameter).IsNotNull(); + } + + [Test, AutoDataSource] + public async Task WhenExpectedNumberAndSut_AssignsExpectedNumberToSut(int expectedNumber, MyClass sut) + { + int result = sut.Echo(expectedNumber); + + await Assert.That(result).IsEqualTo(expectedNumber); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/AutoMemberRowCollect.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/AutoMemberRowCollect.cs new file mode 100644 index 0000000..7eacd23 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/AutoMemberRowCollect.cs @@ -0,0 +1,17 @@ +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; +using AutoFixture.TUnit.Tests.TestTypes; +using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests; + +internal static class AutoMemberRowCollect +{ + public static object[][] FromMember(string memberName, string testMethodName) + { + var sut = new AutoMemberDataSourceAttribute(typeof(MemberDataShapes), memberName); + var testMethod = typeof(SampleTestType).GetMethod(testMethodName)!; + return sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) + .Select(x => x()) + .ToArray(); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs new file mode 100644 index 0000000..24e10a0 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs @@ -0,0 +1,130 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; +using ConcreteType = TestTypeFoundation.ConcreteType; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests; + +/// +/// End-to-end [AutoMemberDataSource] on the test class (TUnit ClassParameters). +/// Ordered simple → complex; mirrors AutoDataSource class-level scenarios. +/// +[AutoMemberDataSource(nameof(Names))] +public class ClassLevelPrimitiveScenarioTests(string name, int count) +{ + public static IEnumerable Names => ["one", "two"]; + + [Test] + public async Task WhenAppliedToClass_UsesMemberValueAndFillsRemaining() + { + await Assert.That(new[] { "one", "two" }).Contains(name); + await Assert.That(count).IsNotEqualTo(0); + } +} + +[AutoMemberDataSource(nameof(Names))] +public class ClassLevelComplexTypeScenarioTests( + string name, + PropertyHolder ph, + SingleParameterType spt, + MyClass sut) +{ + public static IEnumerable Names => ["alpha", "beta"]; + + [Test] + public async Task WhenAppliedToClass_UsesMemberValueAndFillsComplexRemaining() + { + await Assert.That(new[] { "alpha", "beta" }).Contains(name); + + await Assert.That(ph).IsNotNull(); + await Assert.That(ph.Property).IsNotNull(); + + await Assert.That(spt).IsNotNull(); + await Assert.That(spt.Parameter).IsNotNull(); + + await Assert.That(sut).IsNotNull(); + await Assert.That(sut.Echo(7)).IsEqualTo(7); + } +} + +[AutoMemberDataSource(nameof(OneEmptyRow))] +public class ClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second) +{ + public static IEnumerable OneEmptyRow() + { + yield return []; + } + + [Test] + public async Task WhenFrozenOnConstructorParameter_SharesInstanceWithLaterParameter() + { + await Assert.That(second).IsEqualTo(first); + } +} + +[AutoMemberDataSource(nameof(OneEmptyRow))] +public class ClassLevelModestScenarioTests([Modest] MultiUnorderedConstructorType value) +{ + public static IEnumerable OneEmptyRow() + { + yield return []; + } + + [Test] + public async Task WhenModestOnConstructorParameter_UsesModestConstructor() + { + await Assert.That(string.IsNullOrEmpty(value.Text)).IsTrue(); + await Assert.That(value.Number).IsEqualTo(0); + } +} + +[AutoMemberDataSource(nameof(Names))] +public class ClassLevelMultiConstructorParameterizedFirstScenarioTests +{ + public static IEnumerable Names => ["from-member"]; + + private readonly string name; + + public ClassLevelMultiConstructorParameterizedFirstScenarioTests(string name) + { + this.name = name; + } + + public ClassLevelMultiConstructorParameterizedFirstScenarioTests() + { + this.name = "parameterless"; + } + + [Test] + public async Task WhenParameterizedConstructorDeclaredFirst_UsesMemberConstructorArgument() + { + await Assert.That(this.name).IsEqualTo("from-member"); + } +} + +[AutoMemberDataSource(nameof(Counts))] +public class ClassLevelMultiConstructorIntFirstScenarioTests +{ + public static IEnumerable Counts => [11, 22]; + + private readonly string name; + private readonly int count; + + public ClassLevelMultiConstructorIntFirstScenarioTests(int count) + { + this.name = "int-ctor"; + this.count = count; + } + + public ClassLevelMultiConstructorIntFirstScenarioTests(string name) + { + this.name = name; + this.count = -1; + } + + [Test] + public async Task WhenIntConstructorDeclaredFirst_UsesMemberIntArgument() + { + await Assert.That(this.name).IsEqualTo("int-ctor"); + await Assert.That(new[] { 11, 22 }).Contains(this.count); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs new file mode 100644 index 0000000..3356bac --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs @@ -0,0 +1,67 @@ +namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests; + +public class ConstructionTests +{ + [Test] + public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute() + { + var sut = new AutoMemberDataSourceAttribute(Guid.NewGuid().ToString()); + + await Assert.That(sut).IsAssignableTo(); + } + + [Test] + public async Task Constructor_WhenMemberNameAndParameters_SetsMembers() + { + var memberName = Guid.NewGuid().ToString(); + var parameters = new object[] { "value-one", 3, 12.2f }; + + var sut = new AutoMemberDataSourceAttribute(memberName, parameters); + + await Assert.That(sut.MemberName).IsEqualTo(memberName); + await Assert.That(sut.Parameters).IsEqualTo(parameters); + await Assert.That(sut.MemberType).IsNull(); + await Assert.That(sut.FixtureFactory).IsNotNull(); + } + + [Test] + public async Task Constructor_WhenTypeMemberNameAndParameters_SetsMembers() + { + var memberName = Guid.NewGuid().ToString(); + var parameters = new object[] { "value-one", 3, 12.2f }; + var testType = typeof(ConstructionTests); + + var sut = new AutoMemberDataSourceAttribute(testType, memberName, parameters); + + await Assert.That(sut.MemberName).IsEqualTo(memberName); + await Assert.That(sut.Parameters).IsEqualTo(parameters); + await Assert.That(sut.MemberType).IsEqualTo(testType); + await Assert.That(sut.FixtureFactory).IsNotNull(); + } + + [Test] + public async Task Constructor_WhenMemberNameIsNull_ThrowsArgumentNullException() + { + await Assert.That(() => new AutoMemberDataSourceAttribute(null)) + .ThrowsExactly(); + } + + [Test] + public async Task Constructor_WhenParametersIsNull_TreatsAsSingleNullArgument() + { + var memberName = Guid.NewGuid().ToString(); + + var actual = new AutoMemberDataSourceAttribute(memberName, null); + + var value = await Assert.That(actual.Parameters).HasSingleItem(); + await Assert.That(value).IsNull(); + } + + [Test] + public void Constructor_WhenMemberTypeIsNull_DoesNotThrow() + { + var memberName = Guid.NewGuid().ToString(); + + _ = new AutoMemberDataSourceAttribute(null, memberName); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/EmptySequenceRowTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/EmptySequenceRowTests.cs new file mode 100644 index 0000000..243ddde --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/EmptySequenceRowTests.cs @@ -0,0 +1,30 @@ +using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests; + +/// +/// Empty member sequences cannot be asserted via a [Test] body (no cases run), +/// so they stay as direct GetData checks. +/// +public class EmptySequenceRowTests +{ + [Test] + public async Task GetData_WhenMemberReturnsEmptyObjectArraySequence_YieldsNoRows() + { + var result = AutoMemberRowCollect.FromMember( + nameof(MemberDataShapes.EmptyObjectArrays), + nameof(TestTypes.SampleTestType.TestMethodWithTwoParameters)); + + await Assert.That(result).IsEmpty(); + } + + [Test] + public async Task GetData_WhenMemberReturnsEmptyAsyncSequence_YieldsNoRows() + { + var result = AutoMemberRowCollect.FromMember( + nameof(MemberDataShapes.EmptyAsyncObjectArrays), + nameof(TestTypes.SampleTestType.TestMethodWithTwoParameters)); + + await Assert.That(result).IsEmpty(); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs new file mode 100644 index 0000000..8c420c3 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs @@ -0,0 +1,69 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; +using ConcreteType = TestTypeFoundation.ConcreteType; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests; + +/// +/// Class-level [AutoMemberDataSource<T>] scenarios parallel to the non-generic class-level set. +/// +[AutoMemberDataSource(nameof(GenericMemberHost.Names))] +public class GenericClassLevelPrimitiveScenarioTests(string name, int count) +{ + [Test] + public async Task WhenGenericAppliedToClass_UsesMemberValueAndFillsRemaining() + { + await Assert.That(new[] { "one", "two" }).Contains(name); + await Assert.That(count).IsNotEqualTo(0); + } +} + +[AutoMemberDataSource(nameof(GenericMemberHost.Names))] +public class GenericClassLevelComplexTypeScenarioTests( + string name, + PropertyHolder ph, + SingleParameterType spt, + MyClass sut) +{ + [Test] + public async Task WhenGenericAppliedToClass_UsesMemberValueAndFillsComplexRemaining() + { + await Assert.That(new[] { "one", "two" }).Contains(name); + + await Assert.That(ph).IsNotNull(); + await Assert.That(ph.Property).IsNotNull(); + + await Assert.That(spt).IsNotNull(); + await Assert.That(spt.Parameter).IsNotNull(); + + await Assert.That(sut).IsNotNull(); + await Assert.That(sut.Echo(7)).IsEqualTo(7); + } +} + +[AutoMemberDataSource(nameof(OneEmptyRow))] +public class GenericClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second) +{ + public static IEnumerable OneEmptyRow() + { + yield return []; + } + + [Test] + public async Task WhenGenericFrozenOnConstructorParameter_SharesInstanceWithLaterParameter() + { + await Assert.That(second).IsEqualTo(first); + } +} + +public class GenericMemberHost +{ + public static IEnumerable Names + { + get + { + yield return "one"; + yield return "two"; + } + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs new file mode 100644 index 0000000..4ebc8a6 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs @@ -0,0 +1,100 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests; + +/// +/// End-to-end [AutoMemberDataSource<T>] usage parallel to the non-generic scenarios. +/// +public class GenericUsageScenarioTests +{ + [Test, AutoMemberDataSource(nameof(MemberHost.Strings))] + public async Task WhenGenericMemberYieldsStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover) + { + await Assert.That(new[] { "one", "two" }).Contains(value); + await Assert.That(leftover).IsNotNull(); + } + + [Test, AutoMemberDataSource(nameof(MemberHost.ObjectArrays))] + public async Task WhenGenericMemberReturnsObjectArrays_UsesSuppliedValues( + string a, int b, RecordType c) + { + await Assert.That(new[] + { + ("hello", 1, "world"), + ("foo", 2, "bar") + }).Contains((a, b, c.Value)); + } + + [Test, AutoMemberDataSource(nameof(MemberHost.StringData))] + public async Task WhenGenericMemberOnHostType_UsesSuppliedValues(string s1, string s2, MyClass leftover) + { + await Assert.That(s1).IsEqualTo("foo"); + await Assert.That(s2).IsNotNull(); + await Assert.That(leftover).IsNotNull(); + } + + [Test, MyCustomAutoMemberDataSource(nameof(MemberHost.IntData))] + public async Task WhenGenericCustomMemberAttribute_SuppliesExtraValues(int x, int y, int z) + { + await Assert.That(x).IsEqualTo(1337); + await Assert.That(y).IsNotEqualTo(0); + await Assert.That(z).IsEqualTo(42); + } + + public class MemberHost + { + public static IEnumerable Strings + { + get + { + yield return "one"; + yield return "two"; + } + } + + public static IEnumerable ObjectArrays + { + get + { + yield return ["hello", 1, new RecordType("world")]; + yield return ["foo", 2, new RecordType("bar")]; + } + } + + public static IEnumerable StringData + { + get + { + yield return ["foo"]; + yield return ["foo", "bar"]; + } + } + + public static IEnumerable IntData + { + get + { + yield return [1337]; + yield return [1337, 7]; + yield return [1337, 7, 42]; + } + } + } + + public class MyCustomAutoMemberDataSourceAttribute : AutoMemberDataSourceAttribute + { + public MyCustomAutoMemberDataSourceAttribute(string memberName, params object[] parameters) + : base(() => new Fixture().Customize(new TheAnswer()), memberName, parameters) + { + } + } + + private class TheAnswer : ICustomization + { + public void Customize(IFixture fixture) + { + fixture.Inject(42); + } + } +} diff --git a/tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs similarity index 63% rename from tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs index f49bd1a..03796fa 100644 --- a/tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs @@ -1,132 +1,53 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -using TUnit.Assertions.Extensions; using ConcreteType = TestTypeFoundation.ConcreteType; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests; [SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local", Justification = "Using parameter for precondition checks is acceptable in assertions.")] -public class MemberAutoDataSourceAttributeTest +public class GetDataTests { [Test] - public async Task SutIsDataAttribute() - { - // Arrange - var memberName = Guid.NewGuid().ToString(); - - // Act - var sut = new AutoMemberDataSourceAttribute(memberName); - - // Assert - await Assert.That(sut).IsAssignableTo(); - } - - [Test] - public async Task InitializedWithMemberNameAndParameters() - { - // Arrange - var memberName = Guid.NewGuid().ToString(); - var parameters = new object[] { "value-one", 3, 12.2f }; - - // Act - var sut = new AutoMemberDataSourceAttribute(memberName, parameters); - - // Assert - await Assert.That(sut.MemberName).IsEqualTo(memberName); - await Assert.That(sut.Parameters).IsEqualTo(parameters); - await Assert.That(sut.MemberType).IsNull(); - await Assert.That(sut.FixtureFactory).IsNotNull(); - } - - [Test] - public async Task InitializedWithTypeMemberNameAndParameters() - { - // Arrange - var memberName = Guid.NewGuid().ToString(); - var parameters = new object[] { "value-one", 3, 12.2f }; - var testType = typeof(MemberAutoDataSourceAttributeTest); - - // Act - var sut = new AutoMemberDataSourceAttribute(testType, memberName, parameters); - - // Assert - await Assert.That(sut.MemberName).IsEqualTo(memberName); - await Assert.That(sut.Parameters).IsEqualTo(parameters); - await Assert.That(sut.MemberType).IsEqualTo(testType); - await Assert.That(sut.FixtureFactory).IsNotNull(); - } - - [Test] - public async Task ThrowsWhenInitializedWithNullMemberName() - { - // Act & Assert - await Assert.That(() => new AutoMemberDataSourceAttribute(null!)) - .ThrowsExactly(); - } - - [Test] - public async Task TreatsNullParametersAsArrayWithNullValue() - { - // Arrange - var memberName = Guid.NewGuid().ToString(); - - // Act - var actual = new AutoMemberDataSourceAttribute(memberName, null!); - - // Act & Assert - var value = await Assert.That(actual.Parameters).HasSingleItem(); - await Assert.That(value).IsNull(); - } - - [Test] - public void DoesNotThrowWhenInitializedWithNullType() - { - // Arrange - var memberName = Guid.NewGuid().ToString(); - - // Act & Assert - _ = new AutoMemberDataSourceAttribute(null!, memberName); - } - - [Test] - public void ThrowsWhenTestMethodNull() + public void GetData_WhenTestMethodNull_Throws() { // Arrange var sut = new AutoMemberDataSourceAttribute("memberName"); // Act & Assert Assert.Throws( - () => _ = sut.GenerateDataSources(null!).Select(x => x()).ToArray()); + () => _ = sut.GenerateDataSources(null).Select(x => x()).ToArray()); } [Test] - public async Task ThrowsWhenMemberNotEnumerable() + public async Task GetData_WhenMemberReturnsScalar_ReturnsData() { // Arrange const string memberName = nameof(TestTypeWithMethodData.NonEnumerableMethod); var sut = new AutoMemberDataSourceAttribute(memberName); var method = TestTypeWithMethodData.GetMultipleValueTestMethodInfo(); var dataGeneratorMetadata = DataGeneratorMetadataHelper - .CreateDataGeneratorMetadata(method!); + .CreateDataGeneratorMetadata(method); - // Act & Assert - var ex = Assert.Throws( - () => sut.GenerateDataSources(dataGeneratorMetadata).ToArray()); + // Act + var result = sut.GenerateDataSources(dataGeneratorMetadata).Select(x => x()).ToArray(); - await Assert.That(ex.Message).Contains(memberName); + // Assert — scalar becomes one row; remaining parameters are auto-generated + await Assert.That(result.Length).IsEqualTo(1); + await Assert.That(result[0].Length).IsEqualTo(method.GetParameters().Length); } [Test] - public async Task ThrowsWhenMemberNotStatic() + public async Task GetData_WhenMemberNotStatic_Throws() { // Arrange const string memberName = nameof(TestTypeWithMethodData.NonStaticSource); var sut = new AutoMemberDataSourceAttribute(memberName); var method = TestTypeWithMethodData.GetMultipleValueTestMethodInfo(); var dataGeneratorMetadata = DataGeneratorMetadataHelper - .CreateDataGeneratorMetadata(method!); + .CreateDataGeneratorMetadata(method); // Act & Assert var ex = Assert.Throws( @@ -136,14 +57,14 @@ public async Task ThrowsWhenMemberNotStatic() } [Test] - public async Task ThrowsWhenMemberDoesNotExist() + public async Task GetData_WhenMemberDoesNotExist_Throws() { // Arrange var memberName = Guid.NewGuid().ToString(); var sut = new AutoMemberDataSourceAttribute(typeof(TestTypeWithMethodData), memberName); var method = TestTypeWithMethodData.GetMultipleValueTestMethodInfo(); var dataGeneratorMetadata = DataGeneratorMetadataHelper - .CreateDataGeneratorMetadata(method!); + .CreateDataGeneratorMetadata(method); // Act & Assert var ex = Assert.Throws( @@ -152,7 +73,7 @@ public async Task ThrowsWhenMemberDoesNotExist() } [Test] - public async Task DoesntActivateFixtureImmediately() + public async Task Constructor_WhenCreated_DoesNotActivateFixtureImmediately() { // Arrange var memberName = Guid.NewGuid().ToString(); @@ -182,18 +103,18 @@ public async Task DoesntActivateFixtureImmediately() [Arguments("CreateWithModestAndFrozen")] [Arguments("CreateWithFrozenAndNoAutoProperties")] [Arguments("CreateWithNoAutoPropertiesAndFrozen")] - public async Task GetDataOrdersCustomizationAttributes(string methodName) + public async Task GetData_WhenCustomizationsPresent_OrdersThem(string methodName) { // Arrange var method = typeof(TypeWithCustomizationAttributes) - .GetMethod(methodName, [typeof(ConcreteType)])!; + .GetMethod(methodName, [typeof(ConcreteType)]); var customizationLog = new List(); var fixture = new DelegatingFixture { OnCustomize = c => customizationLog.Add(c) }; var dataGeneratorMetadata = DataGeneratorMetadataHelper - .CreateDataGeneratorMetadata(method!); + .CreateDataGeneratorMetadata(method); var sut = new DerivedAutoMemberDataSourceAttribute( () => fixture, typeof(TestTypeWithMethodData), @@ -211,14 +132,14 @@ public async Task GetDataOrdersCustomizationAttributes(string methodName) } [Test] - public async Task GeneratesTestsFromParameterlessMethod() + public async Task GetData_WhenParameterlessMethod_GeneratesTests() { // Arrange const string memberName = nameof(TestTypeWithMethodData.GetSingleStringValueTestData); var sut = new AutoMemberDataSourceAttribute(memberName); var testMethod = TestTypeWithMethodData.GetSingleStringValueTestMethodInfo(); var dataGeneratorMetadata = DataGeneratorMetadataHelper - .CreateDataGeneratorMetadata(testMethod!); + .CreateDataGeneratorMetadata(testMethod); var expected = new[] { new object[] { "value-one" }, @@ -236,14 +157,14 @@ public async Task GeneratesTestsFromParameterlessMethod() } [Test] - public async Task GeneratesTestsFromMethodWithParameter() + public async Task GetData_WhenMethodWithParameter_GeneratesTests() { // Arrange const string memberName = nameof(TestTypeWithMethodData.GetStringTestsFromArgument); var sut = new AutoMemberDataSourceAttribute(memberName, "value"); var testMethod = TestTypeWithMethodData.GetStringTestsFromArgumentMethodInfo(); var dataGeneratorMetadata = DataGeneratorMetadataHelper - .CreateDataGeneratorMetadata(testMethod!); + .CreateDataGeneratorMetadata(testMethod); var expected = new[] { new object[] { "value-one" }, @@ -259,14 +180,14 @@ public async Task GeneratesTestsFromMethodWithParameter() } [Test] - public async Task GeneratesTestDataForTestsWithMultipleParameters() + public async Task GetData_WhenMultipleParameters_GeneratesTestData() { // Arrange const string memberName = nameof(TestTypeWithMethodData.GetMultipleValueTestData); var sut = new AutoMemberDataSourceAttribute(memberName); var testMethod = TestTypeWithMethodData.GetMultipleValueTestMethodInfo(); var dataGeneratorMetadata = DataGeneratorMetadataHelper - .CreateDataGeneratorMetadata(testMethod!); + .CreateDataGeneratorMetadata(testMethod); var expected = new[] { new object[] { "value-one", 12, 23.3m }, @@ -283,14 +204,14 @@ public async Task GeneratesTestDataForTestsWithMultipleParameters() } [Test] - public async Task GeneratesMissingDataForTestsWithMultipleParameters() + public async Task GetData_WhenMultipleParametersPartial_GeneratesMissingData() { // Arrange const string memberName = nameof(TestTypeWithMethodData.GetSingleStringValueTestData); var sut = new AutoMemberDataSourceAttribute(memberName); var testMethod = TestTypeWithMethodData.GetMultipleValueTestMethodInfo(); var dataGeneratorMetadata = DataGeneratorMetadataHelper - .CreateDataGeneratorMetadata(testMethod!); + .CreateDataGeneratorMetadata(testMethod); // Act var testData = sut.GenerateDataSources(dataGeneratorMetadata) @@ -302,30 +223,30 @@ public async Task GeneratesMissingDataForTestsWithMultipleParameters() // Assert await Assert.That(arguments1.Length).IsEqualTo(3); - await Assert.That(arguments1[0]).IsEqualTo("value-one"); - await Assert.That(arguments1[1]).IsNotEqualTo(0); - await Assert.That(arguments1[2]).IsNotEqualTo(0); + await Assert.That((string)arguments1[0]).IsEqualTo("value-one"); + await Assert.That((int)arguments1[1]).IsNotEqualTo(0); + await Assert.That((decimal)arguments1[2]).IsNotEqualTo(0m); await Assert.That(arguments2.Length).IsEqualTo(3); - await Assert.That(arguments2[0]).IsEqualTo("value-two"); - await Assert.That(arguments2[1]).IsNotEqualTo(0); - await Assert.That(arguments2[2]).IsNotEqualTo(0); + await Assert.That((string)arguments2[0]).IsEqualTo("value-two"); + await Assert.That((int)arguments2[1]).IsNotEqualTo(0); + await Assert.That((decimal)arguments2[2]).IsNotEqualTo(0m); await Assert.That(arguments3.Length).IsEqualTo(3); - await Assert.That(arguments3[0]).IsEqualTo("value-three"); - await Assert.That(arguments3[1]).IsNotEqualTo(0); - await Assert.That(arguments3[2]).IsNotEqualTo(0); + await Assert.That((string)arguments3[0]).IsEqualTo("value-three"); + await Assert.That((int)arguments3[1]).IsNotEqualTo(0); + await Assert.That((decimal)arguments3[2]).IsNotEqualTo(0m); } [Test] - public async Task GeneratesTestDataWithInjectedParameters() + public async Task GetData_WhenInjectedParameters_GeneratesTestData() { // Arrange const string memberName = nameof(TestTypeWithMethodData.GetDataForTestWithFrozenParameter); var sut = new AutoMemberDataSourceAttribute(memberName); var testMethod = TestTypeWithMethodData.GetTestWithFrozenParameter(); var dataGeneratorMetadata = DataGeneratorMetadataHelper - .CreateDataGeneratorMetadata(testMethod!); + .CreateDataGeneratorMetadata(testMethod); var expected = new[] { new object[] { "value-one", "value-two", "value-two" }, @@ -342,13 +263,13 @@ public async Task GeneratesTestDataWithInjectedParameters() } [Test] - public async Task AutoGeneratesValuesForFrozenParameters() + public async Task GetData_WhenFrozenParameters_AutoGeneratesValues() { // Arrange const string memberName = nameof(TestTypeWithMethodData.GetSingleStringValueTestData); var sut = new AutoMemberDataSourceAttribute(memberName); var testMethod = TestTypeWithMethodData.GetTestWithFrozenParameter(); - var dataGeneratorMetadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!); + var dataGeneratorMetadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod); // Act var testData = sut.GenerateDataSources(dataGeneratorMetadata) @@ -360,23 +281,23 @@ public async Task AutoGeneratesValuesForFrozenParameters() // Assert await Assert.That(arguments1.Length).IsEqualTo(3); - await Assert.That(arguments1[0]).IsEqualTo("value-one"); - await Assert.That(arguments1[1].ToString()!).IsNotEmpty(); - await Assert.That(arguments1[2]).IsEqualTo(arguments1[1]); + await Assert.That((string)arguments1[0]).IsEqualTo("value-one"); + await Assert.That(arguments1[1].ToString()).IsNotEmpty(); + await Assert.That(arguments1[2]).IsSameReferenceAs(arguments1[1]); await Assert.That(arguments2.Length).IsEqualTo(3); - await Assert.That(arguments2[0]).IsEqualTo("value-two"); - await Assert.That(arguments2[1].ToString()!).IsNotEmpty(); - await Assert.That(arguments2[2]).IsEqualTo(arguments2[1]); + await Assert.That((string)arguments2[0]).IsEqualTo("value-two"); + await Assert.That(arguments2[1].ToString()).IsNotEmpty(); + await Assert.That(arguments2[2]).IsSameReferenceAs(arguments2[1]); await Assert.That(arguments3.Length).IsEqualTo(3); - await Assert.That(arguments3[0]).IsEqualTo("value-three"); - await Assert.That(arguments3[1].ToString()!).IsNotEmpty(); - await Assert.That(arguments3[2]).IsEqualTo(arguments3[1]); + await Assert.That((string)arguments3[0]).IsEqualTo("value-three"); + await Assert.That(arguments3[1].ToString()).IsNotEmpty(); + await Assert.That(arguments3[2]).IsSameReferenceAs(arguments3[1]); } [Test] - public async Task SupportsInheritedTestDataMembers() + public async Task GetData_WhenMemberInherited_SupportsMember() { // Arrange const string memberName = nameof(TestTypeWithMethodData.GetMultipleValueTestData); @@ -388,7 +309,7 @@ public async Task SupportsInheritedTestDataMembers() new object[] { "value-two", 38, 12.7m }, new object[] { "value-three", 94, 52.21m } }; - var dataGeneratorMetadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!); + var dataGeneratorMetadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod); // Act var testData = sut.GenerateDataSources(dataGeneratorMetadata) @@ -402,18 +323,18 @@ public static IEnumerable TestDataWithNullValues { get { - yield return [null!, null!]; - yield return [string.Empty, null!]; - yield return [" ", null!]; + yield return [null, null]; + yield return [string.Empty, null]; + yield return [" ", null]; } } [Test] [AutoMemberDataSource(nameof(TestDataWithNullValues))] - public async Task NullTestDataReturned(string a, string b, PropertyHolder c) + public async Task WhenMemberReturnsNullRows_ReceivesNullValues(string a, string b, PropertyHolder c) { await Assert.That(string.IsNullOrWhiteSpace(a)).IsTrue(); await Assert.That(b).IsNull(); await Assert.That(c).IsNotNull(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs new file mode 100644 index 0000000..a78400a --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs @@ -0,0 +1,138 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests; + +/// +/// End-to-end [AutoMemberDataSource] coverage for README result shapes. +/// +public class ResultShapeScenarioTests +{ + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.ObjectArrays))] + public async Task WhenMemberReturnsObjectArrays_UsesSuppliedValues( + string a, int b, RecordType c) + { + await Assert.That(new[] + { + ("hello", 1, "world"), + ("foo", 2, "bar") + }).Contains((a, b, c.Value)); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.Strings))] + public async Task WhenMemberYieldsStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover) + { + await Assert.That(new[] { "one", "two" }).Contains(value); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.StringScalar))] + public async Task WhenMemberReturnsStringScalar_ReceivesValueAndFillsRemaining(string value, MyClass leftover) + { + await Assert.That(value).IsEqualTo("hello"); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.ObjectScalar))] + public async Task WhenMemberReturnsObjectScalar_ReceivesValueAndFillsRemaining(object value, MyClass leftover) + { + await Assert.That(value).IsNotNull(); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.Tuples))] + public async Task WhenMemberYieldsTuples_ExpandsColumnsAndFillsRemaining( + string left, int right, MyClass leftover) + { + await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.SingleTuple))] + public async Task WhenMemberReturnsSingleTuple_ExpandsColumnsAndFillsRemaining( + string left, int right, MyClass leftover) + { + await Assert.That(left).IsEqualTo("a"); + await Assert.That(right).IsEqualTo(1); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.NullValue))] + public async Task WhenMemberReturnsNull_ReceivesNullCellAndFillsRemaining(string value, MyClass leftover) + { + await Assert.That(value).IsNull(); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.TaskOfObjectArrays))] + public async Task WhenMemberReturnsTaskOfObjectArrays_UsesSuppliedValues( + string a, int b, RecordType c) + { + await Assert.That(new[] + { + ("hello", 1, "world"), + ("foo", 2, "bar") + }).Contains((a, b, c.Value)); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.TaskOfTuples))] + public async Task WhenMemberReturnsTaskOfTuples_ExpandsColumnsAndFillsRemaining( + string left, int right, MyClass leftover) + { + await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.AsyncObjectArrays))] + public async Task WhenMemberReturnsAsyncObjectArrays_UsesSuppliedValues( + string a, int b, RecordType c) + { + await Assert.That(new[] + { + ("hello", 1, "world"), + ("foo", 2, "bar") + }).Contains((a, b, c.Value)); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.AsyncStrings))] + public async Task WhenMemberReturnsAsyncStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover) + { + await Assert.That(new[] { "one", "two" }).Contains(value); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.AsyncTuples))] + public async Task WhenMemberReturnsAsyncTuples_ExpandsColumnsAndFillsRemaining( + string left, int right, MyClass leftover) + { + await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That(leftover).IsNotNull(); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.TupleField))] + public async Task WhenMemberIsTupleField_ExpandsColumns(string left, int right) + { + await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + } + + [Test] + [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.TupleProperty))] + public async Task WhenMemberIsTupleProperty_ExpandsColumns(string left, int right) + { + await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ScenarioTests.cs similarity index 90% rename from tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeScenarioTests.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ScenarioTests.cs index 3ad18dd..2551e82 100644 --- a/tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ScenarioTests.cs @@ -1,7 +1,7 @@ using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests; public class MemberAutoDataSourceAttributeScenarioTests { @@ -17,7 +17,7 @@ public class MemberAutoDataSourceAttributeScenarioTests memberType: typeof(TestTypeWithMethodData), memberName: nameof(TestTypeWithMethodData.GetStringTestsFromArgument), parameters: "argument")] - public async Task SingleStringValueTest(string value) + public async Task WhenSingleStringMember_ReceivesStringValue(string value) { await Assert.That(value).IsNotNull(); await Assert.That(value).IsNotEmpty(); @@ -29,7 +29,7 @@ public async Task SingleStringValueTest(string value) [AutoMemberDataSource( memberType: typeof(TestTypeWithMethodData), memberName: nameof(TestTypeWithMethodData.GetMultipleValueTestData))] - public async Task MultipleValueTest(string a, int b, decimal c) + public async Task WhenMultipleValueMember_ReceivesExpectedValues(string a, int b, decimal c) { await Assert.That(a).IsNotNull(); await Assert.That(a).IsNotEmpty(); @@ -44,7 +44,7 @@ public async Task MultipleValueTest(string a, int b, decimal c) [AutoMemberDataSource( memberType: typeof(TestTypeWithMethodData), memberName: nameof(TestTypeWithMethodData.GetSingleStringValueTestData))] - public async Task FreezesUninjectedValues( + public async Task WhenUninjectedValuesFrozen_SubsequentMatch( string a, [Frozen] string b, string c, PropertyHolder d) { @@ -64,7 +64,7 @@ public async Task FreezesUninjectedValues( [Test] [AutoMemberDataSource(nameof(GetMultipleValueTestData))] - public async Task InjectsValues([Frozen] string a, + public async Task WhenMemberValuesProvided_InjectsValues([Frozen] string a, [Frozen] int b, [Frozen] decimal c, PropertyHolder a1, @@ -93,7 +93,7 @@ public async Task InjectsValues([Frozen] string a, [AutoMemberDataSource( memberType: typeof(TestTypeWithMethodData), memberName: nameof(TestTypeWithMethodData.GetStringValuesTestData))] - public async Task DoesNotAlterTestDataValuesWhenFrozen( + public async Task WhenFrozen_DoesNotAlterMemberDataValues( [Frozen] string a, string b, string c) { var aSuffix = a.Split('-').Last(); @@ -110,7 +110,7 @@ public async Task DoesNotAlterTestDataValuesWhenFrozen( [AutoMemberDataSource( memberType: typeof(TestTypeWithMethodData), memberName: nameof(TestTypeWithMethodData.GetStringValuesTestData))] - public async Task LastInjectedValueIsFrozen( + public async Task WhenLastInjectedValueFrozen_SubsequentMatch( [Frozen] string a, [Frozen] string b, string c) { var aSuffix = a.Split('-').Last(); @@ -126,7 +126,7 @@ public async Task LastInjectedValueIsFrozen( [AutoMemberDataSource( memberType: typeof(TestTypeWithMethodData), memberName: nameof(TestTypeWithMethodData.GetTestWithComplexTypesData))] - public async Task InjectsComplexTypes( + public async Task WhenComplexTypes_InjectsExpectedValues( [Frozen] PropertyHolder a, PropertyHolder b, PropertyHolder c) @@ -158,4 +158,4 @@ public static IEnumerable GetStringValuesTestData() yield return ["test-two", "test-dos"]; yield return ["test-three", "test-tres"]; } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/UsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/UsageScenarioTests.cs new file mode 100644 index 0000000..4cf4aa9 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/UsageScenarioTests.cs @@ -0,0 +1,97 @@ +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests; + +/// +/// End-to-end [AutoMemberDataSource] usage moved from the old Scenarios bucket. +/// +public class UsageScenarioTests +{ + [Test, AutoMemberDataSource(nameof(StringData))] + public async Task WhenMemberSuppliesValues_UsesSuppliedValues(string s1, string s2) + { + await Assert.That(s1).IsEqualTo("foo"); + await Assert.That(s2).IsNotNull(); + } + + [Test, AutoMemberDataSource(nameof(StringData))] + public async Task WhenMemberValuesPartial_SuppliesRemainingSpecimens(string s1, string s2, MyClass myClass) + { + await Assert.That(s1).IsEqualTo("foo"); + await Assert.That(s2).IsNotNull(); + await Assert.That(myClass).IsNotNull(); + } + + [Test, AutoMemberDataSource(nameof(StringData))] + public async Task WhenMemberValuesPartial_DoesNotOverwriteSuppliedValues(string s1, string s2, string s3) + { + await Assert.That(s1).IsEqualTo("foo"); + await Assert.That(s2).IsNotNull(); + await Assert.That(s3).IsNotEqualTo("foo"); + await Assert.That(s3).IsNotEqualTo("bar"); + } + + [Test, AutoMemberDataSource(nameof(GetParametrizedData), 21, 38, 43)] + public async Task WhenMemberDataParameterized_ReceivesExpectedData(int x, int y, int z) + { + await Assert.That(x).IsEqualTo(21); + await Assert.That(y).IsEqualTo(38); + await Assert.That(z).IsEqualTo(43); + } + + [Test, MyCustomAutoMemberDataSource(nameof(IntData))] + public async Task WhenCustomMemberAttribute_SuppliesExtraValues(int x, int y, int z) + { + await Assert.That(x).IsEqualTo(1337); + await Assert.That(y).IsNotEqualTo(0); + await Assert.That(z).IsEqualTo(42); + } + + [Test, MyCustomAutoMemberDataSource(nameof(GetParametrizedData), 21, 38, 43)] + public async Task WhenCustomMemberAttributeParameterized_ReceivesExpectedData(int x, int y, int z) + { + await Assert.That(x).IsEqualTo(21); + await Assert.That(y).IsEqualTo(38); + await Assert.That(z).IsEqualTo(43); + } + + public static IEnumerable StringData + { + get + { + yield return ["foo"]; + yield return ["foo", "bar"]; + } + } + + public static IEnumerable IntData + { + get + { + yield return [1337]; + yield return [1337, 7]; + yield return [1337, 7, 42]; + } + } + + public static IEnumerable GetParametrizedData(int x, int y, int z) + { + yield return [x, y, z]; + } + + public class MyCustomAutoMemberDataSourceAttribute : AutoMemberDataSourceAttribute + { + public MyCustomAutoMemberDataSourceAttribute(string memberName, params object[] parameters) + : base(() => new Fixture().Customize(new TheAnswer()), memberName, parameters) + { + } + } + + private class TheAnswer : ICustomization + { + public void Customize(IFixture fixture) + { + fixture.Inject(42); + } + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ClassLevelScenarioTests.cs new file mode 100644 index 0000000..225a65c --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ClassLevelScenarioTests.cs @@ -0,0 +1,185 @@ +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; +using ConcreteType = TestTypeFoundation.ConcreteType; + +namespace AutoFixture.TUnit.Tests.Attributes.CompositeDataSourceAttributeTests; + +/// +/// End-to-end [CompositeDataSource] on the test class (TUnit ClassParameters). +/// Ordered simple → complex; mirrors AutoDataSource class-level scenarios. +/// +[ClassLevelPrimitiveComposite] +public class ClassLevelPrimitiveScenarioTests(string name, int count) +{ + [Test] + public async Task WhenAppliedToClass_UsesCompositeValues() + { + await Assert.That(name).IsEqualTo("seed"); + await Assert.That(count).IsEqualTo(7); + } +} + +[ClassLevelComplexComposite] +public class ClassLevelComplexTypeScenarioTests( + string name, + PropertyHolder ph, + SingleParameterType spt, + MyClass sut) +{ + [Test] + public async Task WhenAppliedToClass_UsesInlineValueAndFillsComplexRemaining() + { + await Assert.That(name).IsEqualTo("seed"); + + await Assert.That(ph).IsNotNull(); + await Assert.That(ph.Property).IsNotNull(); + + await Assert.That(spt).IsNotNull(); + await Assert.That(spt.Parameter).IsNotNull(); + + await Assert.That(sut).IsNotNull(); + await Assert.That(sut.Echo(7)).IsEqualTo(7); + } +} + +[ClassLevelAutoDataComposite] +public class ClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second) +{ + [Test] + public async Task WhenFrozenOnConstructorParameter_SharesInstanceWithLaterParameter() + { + await Assert.That(second).IsEqualTo(first); + } +} + +[ClassLevelAutoDataComposite] +public class ClassLevelModestScenarioTests([Modest] MultiUnorderedConstructorType value) +{ + [Test] + public async Task WhenModestOnConstructorParameter_UsesModestConstructor() + { + await Assert.That(string.IsNullOrEmpty(value.Text)).IsTrue(); + await Assert.That(value.Number).IsEqualTo(0); + } +} + +[ClassLevelInlineNameComposite] +public class ClassLevelMultiConstructorParameterizedFirstScenarioTests +{ + private readonly string name; + + public ClassLevelMultiConstructorParameterizedFirstScenarioTests(string name) + { + this.name = name; + } + + public ClassLevelMultiConstructorParameterizedFirstScenarioTests() + { + this.name = "parameterless"; + } + + [Test] + public async Task WhenParameterizedConstructorDeclaredFirst_UsesCompositeConstructorArgument() + { + await Assert.That(this.name).IsEqualTo("from-composite"); + } +} + +[ClassLevelInlineIntComposite] +public class ClassLevelMultiConstructorIntFirstScenarioTests +{ + private readonly string name; + private readonly int count; + + public ClassLevelMultiConstructorIntFirstScenarioTests(int count) + { + this.name = "int-ctor"; + this.count = count; + } + + public ClassLevelMultiConstructorIntFirstScenarioTests(string name) + { + this.name = name; + this.count = -1; + } + + [Test] + public async Task WhenIntConstructorDeclaredFirst_UsesCompositeIntArgument() + { + await Assert.That(this.name).IsEqualTo("int-ctor"); + await Assert.That(this.count).IsEqualTo(42); + } +} + +public sealed class ClassLevelPrimitiveCompositeAttribute : CompositeDataSourceAttribute +{ + public ClassLevelPrimitiveCompositeAttribute() + : base( + new FixedRowsAttribute(["seed"]), + new FixedRowsAttribute([null!, 7])) + { + } +} + +public sealed class ClassLevelComplexCompositeAttribute : CompositeDataSourceAttribute +{ + public ClassLevelComplexCompositeAttribute() + : base( + new AutoArgumentsAttribute("seed"), + new AutoDataSourceAttribute()) + { + } +} + +public sealed class ClassLevelAutoDataCompositeAttribute : CompositeDataSourceAttribute +{ + public ClassLevelAutoDataCompositeAttribute() + : base(new AutoDataSourceAttribute()) + { + } +} + +public sealed class ClassLevelInlineNameCompositeAttribute : CompositeDataSourceAttribute +{ + public ClassLevelInlineNameCompositeAttribute() + : base( + new AutoArgumentsAttribute("from-composite"), + new FixedRowsAttribute(["ignored"])) + { + } +} + +public sealed class ClassLevelInlineIntCompositeAttribute : CompositeDataSourceAttribute +{ + public ClassLevelInlineIntCompositeAttribute() + : base( + new AutoArgumentsAttribute(42), + new FixedRowsAttribute([0])) + { + } +} + +/// +/// Yields fixed rows without AutoFixture fill — same public extension model as UsageScenarioTests. +/// +public sealed class FixedRowsAttribute : BaseDataSourceAttribute +{ + private readonly object?[][] rows; + + public FixedRowsAttribute(params object?[][] rows) + { + this.rows = rows; + } + +#pragma warning disable CS1998 + public override async IAsyncEnumerable>> GetData( + DataGeneratorMetadata dataGeneratorMetadata) + { + foreach (var row in this.rows) + { + var captured = row; + yield return () => Task.FromResult(captured); + } + } +#pragma warning restore CS1998 +} diff --git a/tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ConstructionTests.cs similarity index 66% rename from tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ConstructionTests.cs index 08bcb11..b796d96 100644 --- a/tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ConstructionTests.cs @@ -1,13 +1,13 @@ -using System.Reflection; +using System.Reflection; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.CompositeDataSourceAttributeTests; public class CompositeDataSourceAttributeTest { [Test] - public async Task SutIsDataAttribute() + public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute() { // Arrange & Act var sut = new CompositeDataSourceAttribute(); @@ -17,16 +17,16 @@ public async Task SutIsDataAttribute() } [Test] - public async Task InitializeWithNullArrayThrows() + public async Task Constructor_WhenArrayIsNull_Throws() { // Arrange // Act & assert - await Assert.That(() => new CompositeDataSourceAttribute(null!)) + await Assert.That(() => new CompositeDataSourceAttribute(null)) .ThrowsExactly(); } [Test] - public async Task AttributesIsCorrectWhenInitializedWithArray() + public async Task Attributes_WhenInitializedWithArray_ReturnsSameAttributes() { // Arrange var a = () => { }; @@ -47,21 +47,22 @@ public async Task AttributesIsCorrectWhenInitializedWithArray() } [Test] - public void InitializeWithNullEnumerableThrows() + public void Constructor_WhenEnumerableIsNull_Throws() { // Act & assert Assert.Throws( - () => _ = new CompositeDataSourceAttribute(((IEnumerable)null)!)); + () => _ = new CompositeDataSourceAttribute(((IEnumerable)null))); } [Test] - public async Task AttributesIsCorrectWhenInitializedWithEnumerable() + public async Task Attributes_WhenInitializedWithEnumerable_ReturnsSameAttributes() { // Arrange var a = () => { }; var method = a.GetMethodInfo(); - var attributes = new BaseDataSourceAttribute[] + // Use a List so the IEnumerable ctor cannot cast to array and must call ToArray(). + IEnumerable attributes = new List { new FakeDataAttribute(method, []), new FakeDataAttribute(method, []), @@ -76,18 +77,22 @@ public async Task AttributesIsCorrectWhenInitializedWithEnumerable() } [Test] - public async Task GetDataWithNullGeneratorMetadataThrows() + public async Task GetData_WhenGeneratorMetadataIsNull_Throws() { // Arrange var sut = new CompositeDataSourceAttribute(); - // Act & assert - await Assert.That(() => sut.GenerateDataSources(null!) - .Select(x => x()).ToArray()).ThrowsException(); + // Act & assert - call GetData directly so the attribute's own null guard is hit + await Assert.That(async () => + { + await foreach (var _ in sut.GetData(null)) + { + } + }).ThrowsExactly(); } [Test] - public async Task GetDataOnMethodWithNoParametersReturnsNoTheory() + public async Task GetData_WhenMethodHasNoParameters_ReturnsNoRows() { // Arrange var a = () => { }; @@ -106,4 +111,4 @@ public async Task GetDataOnMethodWithNoParametersReturnsNoTheory() // Assert await Assert.That(result).All().Satisfy(row => row.IsEmpty()); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeSufficientDataTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/GetDataTests.cs similarity index 94% rename from tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeSufficientDataTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/GetDataTests.cs index 36e3d05..131ee11 100644 --- a/tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeSufficientDataTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/GetDataTests.cs @@ -1,10 +1,10 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.CompositeDataSourceAttributeTests; [SuppressMessage("Usage", "TUnit0014:Method should have a `Test` attribute or be made `private` or `protected`")] [SuppressMessage("Usage", "TUnit0046:Return a `Func` rather than a ``")] @@ -16,7 +16,7 @@ public class CompositeDataSourceAttributeSufficientDataTest [Test] [MethodDataSource(typeof(CompositeDataSourceAttributeSufficientDataTest), nameof(GetEnumerator))] - public async Task GetDataReturnsCorrectResult( + public async Task GetData_WhenCalled_ReturnsCorrectResult( IEnumerable attributes, IEnumerable expectedResult) { @@ -145,7 +145,7 @@ await Assert.That(result) ]); // Test incorrect number of parameters - should just return what it's given - // and let xUnit deal with counting parameters + // and let the test runner deal with counting parameters yield return CreateTestData( data: [ @@ -200,4 +200,4 @@ private static ( { return (data, expected); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs new file mode 100644 index 0000000..019c21e --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs @@ -0,0 +1,85 @@ +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Attributes.CompositeDataSourceAttributeTests; + +/// +/// End-to-end [CompositeDataSource] usage via the public attribute API. +/// Partial child sources are expressed as BaseDataSourceAttribute derivatives — +/// the supported extension point for custom data sources. +/// +public class UsageScenarioTests +{ + [Test, LeadingAndTrailingComposite] + public async Task WhenCompositeZipsPartialRows_MergesByCollapse(string a, int b, string c) + { + await Assert.That(new[] + { + ("alpha", 1, "tail-a"), + ("beta", 2, "tail-b") + }).Contains((a, b, c)); + } + + [Test, ArgumentsThenMemberComposite] + public async Task WhenCompositeCombinesAutoSources_RunsWithFirstSourceValues( + int id, string name, MyClass leftover) + { + await Assert.That(id).IsEqualTo(100); + await Assert.That(name).IsEqualTo("fixed-name"); + await Assert.That(leftover).IsNotNull(); + } + + public class LeadingAndTrailingCompositeAttribute : CompositeDataSourceAttribute + { + public LeadingAndTrailingCompositeAttribute() + : base( + new FixedRowsAttribute(["alpha", 1], ["beta", 2]), + new FixedRowsAttribute(["x", 0, "tail-a"], ["y", 0, "tail-b"])) + { + } + } + + public class ArgumentsThenMemberCompositeAttribute : CompositeDataSourceAttribute + { + public ArgumentsThenMemberCompositeAttribute() + : base( + new AutoArgumentsAttribute(100, "fixed-name"), + new AutoMemberDataSourceAttribute(nameof(SecondaryRows))) + { + } + } + + public static IEnumerable SecondaryRows + { + get + { + yield return ["ignored-when-first-source-fills-all"]; + yield return ["also-ignored"]; + } + } + + /// + /// Yields fixed rows without AutoFixture fill — same public extension model users get + /// by deriving . + /// + public class FixedRowsAttribute : BaseDataSourceAttribute + { + private readonly object?[][] rows; + + public FixedRowsAttribute(params object?[][] rows) + { + this.rows = rows; + } + +#pragma warning disable CS1998 + public override async IAsyncEnumerable>> GetData( + DataGeneratorMetadata dataGeneratorMetadata) + { + foreach (var row in this.rows) + { + var captured = row; + yield return () => Task.FromResult(captured); + } + } +#pragma warning restore CS1998 + } +} diff --git a/tests/AutoFixture.TUnit.Tests/CustomizeAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/CustomizeAttributeTests.cs similarity index 65% rename from tests/AutoFixture.TUnit.Tests/CustomizeAttributeTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/CustomizeAttributeTests.cs index 8b7be44..f3b5ad9 100644 --- a/tests/AutoFixture.TUnit.Tests/CustomizeAttributeTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/CustomizeAttributeTests.cs @@ -1,11 +1,11 @@ -using AutoFixture.TUnit.Tests.TestTypes; +using AutoFixture.TUnit.Tests.TestTypes; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.Customizations; public class CustomizeAttributeTest { [Test] - public async Task TestableSutIsSut() + public async Task Constructor_WhenCreated_IsCustomizeAttribute() { // Arrange && Act var sut = new DelegatingCustomizeAttribute(); @@ -15,7 +15,7 @@ public async Task TestableSutIsSut() } [Test] - public async Task SutIsAttribute() + public async Task Constructor_WhenCreated_IsAttribute() { // Arrange && Act var sut = new DelegatingCustomizeAttribute(); @@ -25,7 +25,7 @@ public async Task SutIsAttribute() } [Test] - public async Task SutImplementsIParameterCustomizationSource() + public async Task Constructor_WhenCreated_ImplementsIParameterCustomizationSource() { // Arrange && Act var sut = new DelegatingCustomizeAttribute(); @@ -33,4 +33,4 @@ public async Task SutImplementsIParameterCustomizationSource() // Assert await Assert.That(sut).IsAssignableTo(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/FavorArraysAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorArraysAttributeTests.cs similarity index 72% rename from tests/AutoFixture.TUnit.Tests/FavorArraysAttributeTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorArraysAttributeTests.cs index 40ac0f7..ab3caf4 100644 --- a/tests/AutoFixture.TUnit.Tests/FavorArraysAttributeTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorArraysAttributeTests.cs @@ -1,13 +1,12 @@ -using AutoFixture.Kernel; +using AutoFixture.Kernel; using TestTypeFoundation; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.Customizations; public class FavorArraysAttributeTest { [Test] - public async Task SutIsAttribute() + public async Task Constructor_WhenCreated_IsAttribute() { // Arrange // Act @@ -17,22 +16,22 @@ public async Task SutIsAttribute() } [Test] - public async Task GetCustomizationFromNullParameterThrows() + public async Task GetCustomization_WhenParameterIsNull_Throws() { // Arrange var sut = new FavorArraysAttribute(); // Act & assert await Assert.That(() => - sut.GetCustomization(null!)).ThrowsExactly(); + sut.GetCustomization(null)).ThrowsExactly(); } [Test] - public async Task GetCustomizationReturnsCorrectResult() + public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult() { // Arrange var sut = new FavorArraysAttribute(); var parameter = typeof(TypeWithOverloadedMembers) - .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])! + .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)]) .GetParameters().Single(); // Act var result = sut.GetCustomization(parameter); @@ -42,4 +41,4 @@ public async Task GetCustomizationReturnsCorrectResult() await Assert.That(invoker.TargetType).IsEqualTo(parameter.ParameterType); await Assert.That(invoker.Query).IsAssignableTo(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/FavorEnumerablesAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorEnumerablesAttributeTests.cs similarity index 72% rename from tests/AutoFixture.TUnit.Tests/FavorEnumerablesAttributeTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorEnumerablesAttributeTests.cs index 7c93ac7..55c7b58 100644 --- a/tests/AutoFixture.TUnit.Tests/FavorEnumerablesAttributeTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorEnumerablesAttributeTests.cs @@ -1,13 +1,12 @@ -using AutoFixture.Kernel; +using AutoFixture.Kernel; using TestTypeFoundation; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.Customizations; public class FavorEnumerablesAttributeTest { [Test] - public async Task SutIsAttribute() + public async Task Constructor_WhenCreated_IsAttribute() { // Arrange // Act @@ -17,22 +16,22 @@ public async Task SutIsAttribute() } [Test] - public async Task GetCustomizationFromNullParameterThrows() + public async Task GetCustomization_WhenParameterIsNull_Throws() { // Arrange var sut = new FavorEnumerablesAttribute(); // Act & assert await Assert.That(() => - sut.GetCustomization(null!)).ThrowsExactly(); + sut.GetCustomization(null)).ThrowsExactly(); } [Test] - public async Task GetCustomizationReturnsCorrectResult() + public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult() { // Arrange var sut = new FavorEnumerablesAttribute(); var parameter = typeof(TypeWithOverloadedMembers) - .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])! + .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)]) .GetParameters().Single(); // Act var result = sut.GetCustomization(parameter); @@ -42,4 +41,4 @@ public async Task GetCustomizationReturnsCorrectResult() await Assert.That(invoker.TargetType).IsEqualTo(parameter.ParameterType); await Assert.That(invoker.Query).IsAssignableTo(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/FavorListsAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorListsAttributeTests.cs similarity index 73% rename from tests/AutoFixture.TUnit.Tests/FavorListsAttributeTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorListsAttributeTests.cs index a8a5632..20bddd8 100644 --- a/tests/AutoFixture.TUnit.Tests/FavorListsAttributeTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorListsAttributeTests.cs @@ -1,13 +1,12 @@ -using AutoFixture.Kernel; +using AutoFixture.Kernel; using TestTypeFoundation; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.Customizations; public class FavorListsAttributeTest { [Test] - public async Task SutIsAttribute() + public async Task Constructor_WhenCreated_IsAttribute() { // Arrange // Act @@ -17,22 +16,22 @@ public async Task SutIsAttribute() } [Test] - public async Task GetCustomizationFromNullParameterThrows() + public async Task GetCustomization_WhenParameterIsNull_Throws() { // Arrange var sut = new FavorListsAttribute(); // Act & assert - await Assert.That(() => sut.GetCustomization(null!)) + await Assert.That(() => sut.GetCustomization(null)) .ThrowsExactly(); } [Test] - public async Task GetCustomizationReturnsCorrectResult() + public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult() { // Arrange var sut = new FavorListsAttribute(); var parameter = typeof(TypeWithOverloadedMembers) - .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])! + .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)]) .GetParameters().Single(); // Act var result = sut.GetCustomization(parameter); @@ -42,4 +41,4 @@ public async Task GetCustomizationReturnsCorrectResult() await Assert.That(invoker.TargetType).IsEqualTo(parameter.ParameterType); await Assert.That(invoker.Query).IsAssignableTo(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/FrozenAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FrozenAttributeTests.cs similarity index 60% rename from tests/AutoFixture.TUnit.Tests/FrozenAttributeTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FrozenAttributeTests.cs index ec37c16..48981e0 100644 --- a/tests/AutoFixture.TUnit.Tests/FrozenAttributeTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FrozenAttributeTests.cs @@ -1,11 +1,9 @@ -using TUnit.Assertions.Extensions; - -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.Customizations; public class FrozenAttributeTest { [Test] - public async Task SutIsAttribute() + public async Task Constructor_WhenCreated_IsAttribute() { // Arrange // Act @@ -15,12 +13,12 @@ public async Task SutIsAttribute() } [Test] - public async Task GetCustomizationFromNullParameterThrows() + public async Task GetCustomization_WhenParameterIsNull_Throws() { // Arrange var sut = new FrozenAttribute(); // Act & assert - await Assert.That(() => sut.GetCustomization(null!)) + await Assert.That(() => sut.GetCustomization(null)) .ThrowsExactly(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/GreedyAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/GreedyAttributeTests.cs similarity index 73% rename from tests/AutoFixture.TUnit.Tests/GreedyAttributeTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/GreedyAttributeTests.cs index 8afe8b7..6f456d2 100644 --- a/tests/AutoFixture.TUnit.Tests/GreedyAttributeTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/GreedyAttributeTests.cs @@ -1,16 +1,15 @@ -using AutoFixture.Kernel; +using AutoFixture.Kernel; using TestTypeFoundation; -using TUnit.Assertions.Extensions; #if NETCOREAPP1_1 using System.Reflection; #endif -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.Customizations; public class GreedyAttributeTest { [Test] - public async Task SutIsAttribute() + public async Task Constructor_WhenCreated_IsAttribute() { // Arrange // Act @@ -20,22 +19,22 @@ public async Task SutIsAttribute() } [Test] - public async Task GetCustomizationFromNullParameterThrows() + public async Task GetCustomization_WhenParameterIsNull_Throws() { // Arrange var sut = new GreedyAttribute(); // Act & assert - await Assert.That(() => sut.GetCustomization(null!)) + await Assert.That(() => sut.GetCustomization(null)) .ThrowsExactly(); } [Test] - public async Task GetCustomizationReturnsCorrectResult() + public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult() { // Arrange var sut = new GreedyAttribute(); var parameter = typeof(TypeWithOverloadedMembers) - .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])! + .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)]) .GetParameters().Single(); // Act var result = sut.GetCustomization(parameter); @@ -45,4 +44,4 @@ public async Task GetCustomizationReturnsCorrectResult() await Assert.That(invoker.TargetType).IsEqualTo(parameter.ParameterType); await Assert.That(invoker.Query).IsAssignableTo(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/ModestAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ModestAttributeTests.cs similarity index 72% rename from tests/AutoFixture.TUnit.Tests/ModestAttributeTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ModestAttributeTests.cs index 796c6a4..ee8d8d8 100644 --- a/tests/AutoFixture.TUnit.Tests/ModestAttributeTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ModestAttributeTests.cs @@ -1,13 +1,12 @@ -using AutoFixture.Kernel; +using AutoFixture.Kernel; using TestTypeFoundation; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.Customizations; public class ModestAttributeTest { [Test] - public async Task SutIsAttribute() + public async Task Constructor_WhenCreated_IsAttribute() { // Arrange & Act var sut = new ModestAttribute(); @@ -16,22 +15,22 @@ public async Task SutIsAttribute() } [Test] - public async Task GetCustomizationFromNullParameterThrows() + public async Task GetCustomization_WhenParameterIsNull_Throws() { // Arrange var sut = new ModestAttribute(); // Act & assert - await Assert.That(() => sut.GetCustomization(null!)) + await Assert.That(() => sut.GetCustomization(null)) .ThrowsExactly(); } [Test] - public async Task GetCustomizationReturnsCorrectResult() + public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult() { // Arrange var sut = new ModestAttribute(); var parameter = typeof(TypeWithOverloadedMembers) - .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])! + .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)]) .GetParameters().Single(); // Act @@ -43,4 +42,4 @@ public async Task GetCustomizationReturnsCorrectResult() await Assert.That(invoker.TargetType).IsEqualTo(parameter.ParameterType); await Assert.That(invoker.Query).IsAssignableTo(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/NoAutoPropertiesAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/NoAutoPropertiesAttributeTests.cs similarity index 69% rename from tests/AutoFixture.TUnit.Tests/NoAutoPropertiesAttributeTest.cs rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/NoAutoPropertiesAttributeTests.cs index 024159d..f9b4ba5 100644 --- a/tests/AutoFixture.TUnit.Tests/NoAutoPropertiesAttributeTest.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/NoAutoPropertiesAttributeTests.cs @@ -1,12 +1,11 @@ -using TestTypeFoundation; -using TUnit.Assertions.Extensions; +using TestTypeFoundation; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Attributes.Customizations; public class NoAutoPropertiesAttributeTest { [Test] - public async Task SutIsAttribute() + public async Task Constructor_WhenCreated_IsAttribute() { // Arrange // Act @@ -16,17 +15,17 @@ public async Task SutIsAttribute() } [Test] - public async Task GetCustomizationFromNullParameterThrows() + public async Task GetCustomization_WhenParameterIsNull_Throws() { // Arrange var sut = new NoAutoPropertiesAttribute(); // Act & assert - await Assert.That(() => sut.GetCustomization(null!)) + await Assert.That(() => sut.GetCustomization(null)) .ThrowsExactly(); } [Test] - public async Task GetCustomizationReturnsTheCorrectResult() + public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult() { // Arrange var sut = new NoAutoPropertiesAttribute(); @@ -38,4 +37,4 @@ public async Task GetCustomizationReturnsTheCorrectResult() // Assert await Assert.That(result).IsAssignableTo(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ScenarioTests.cs new file mode 100644 index 0000000..36600ea --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ScenarioTests.cs @@ -0,0 +1,337 @@ +using System.ComponentModel.DataAnnotations; +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; +using ConcreteType = TestTypeFoundation.ConcreteType; + +namespace AutoFixture.TUnit.Tests.Attributes.Customizations; + +/// +/// End-to-end customization usage with [AutoDataSource], moved from the old Scenarios bucket. +/// +public class ScenarioTests +{ + [Test, AutoDataSource] + public async Task WhenFirstParameterFrozen_SecondMatchesFirst([Frozen] Guid g1, Guid g2) + { + await Assert.That(g2).IsEqualTo(g1); + } + + [Test, AutoDataSource] + public async Task WhenSecondParameterFrozen_OnlySubsequentMatch(Guid g1, [Frozen] Guid g2, Guid g3) + { + await Assert.That(g2).IsNotEqualTo(g1); + await Assert.That(g3).IsNotEqualTo(g1); + + await Assert.That(g3).IsEqualTo(g2); + } + + [Test, AutoDataSource] + public async Task WhenModestApplied_UsesModestConstructor([Modest] MultiUnorderedConstructorType p) + { + await Assert.That(string.IsNullOrEmpty(p.Text)).IsTrue(); + await Assert.That(p.Number).IsEqualTo(0); + } + + [Test, AutoDataSource] + public async Task WhenGreedyApplied_UsesGreedyConstructor([Greedy] MultiUnorderedConstructorType p) + { + await Assert.That(string.IsNullOrEmpty(p.Text)).IsFalse(); + await Assert.That(p.Number).IsNotEqualTo(0); + } + + [Test, AutoDataSource] + public async Task WhenFrozenAndGreedyOnSameParameter_BothApply( + [Frozen][Greedy] MultiUnorderedConstructorType p1, MultiUnorderedConstructorType p2) + { + await Assert.That(p1).IsNotNull(); + await Assert.That(string.IsNullOrEmpty(p2.Text)).IsFalse(); + await Assert.That(p2.Number).IsNotEqualTo(0); + } + + [Test, AutoDataSource] + public async Task WhenGreedyAndFrozenOnSameParameter_BothApply( + [Greedy][Frozen] MultiUnorderedConstructorType p1, MultiUnorderedConstructorType p2) + { + await Assert.That(p1).IsNotNull(); + await Assert.That(string.IsNullOrEmpty(p2.Text)).IsFalse(); + await Assert.That(p2.Number).IsNotEqualTo(0); + await Assert.That(p2).IsSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenNoAutoPropertiesApplied_LeavesPropertiesUnset( + [NoAutoProperties] PropertyHolder ph1, + [NoAutoProperties] PropertyHolder ph2, + [NoAutoProperties] PropertyHolder ph3) + { + await Assert.That(ph1.Property).IsEqualTo(default(object)); + await Assert.That(ph2.Property).IsEqualTo(default(string)); + await Assert.That(ph3.Property).IsEqualTo(default(int)); + } + + [Test, AutoDataSource] + public async Task WhenFavorArraysAndFrozen_InjectsArrayConstructorWithFrozenItems([Frozen] int[] numbers, + [FavorArrays] ItemContainer container) + { + await Assert.That(numbers.SequenceEqual(container.Items)).IsTrue(); + } + + [Test, AutoDataSource] + public async Task WhenFavorEnumerablesApplied_UsesEnumerableConstructor( + [FavorEnumerables] CompositeTypeWithOverloadedConstructors numbers) + { + await Assert.That(numbers.Items).IsAssignableTo>(); + await Assert.That(numbers.Items).IsNotTypeOf>(); + await Assert.That(numbers.Items).IsNotTypeOf(); + } + + [Test, AutoDataSource] + public async Task WhenFavorListsApplied_UsesListConstructor( + [FavorLists] CompositeTypeWithOverloadedConstructors strings) + { + await Assert.That(strings.Items).IsAssignableTo>(); + } + + [Test, AutoDataSource] + public async Task WhenFirstParameterFrozen_AssignsSameInstanceToSecond([Frozen] string p1, + string p2) + { + await Assert.That(p2).IsEqualTo(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByExactType_AssignsSameInstanceToSecond( + [Frozen(Matching.ExactType)] ConcreteType p1, + ConcreteType p2) + { + await Assert.That(p2).IsEqualTo(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByExactType_DoesNotAssignToDifferentType( + [Frozen(Matching.ExactType)] ConcreteType p1, + object p2) + { + await Assert.That(p2).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByDirectBaseType_AssignsSameInstanceToSecond( + [Frozen(Matching.DirectBaseType)] ConcreteType p1, + AbstractType p2) + { + await Assert.That(p2).IsSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByDirectBaseType_DoesNotAssignToIndirectBaseType( + [Frozen(Matching.DirectBaseType)] ConcreteType p1, + object p2) + { + await Assert.That(p2).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByDirectBaseType_DoesNotAssignToSameType( + [Frozen(Matching.DirectBaseType)] ConcreteType p1, + ConcreteType p2) + { + await Assert.That(p2).IsNotEqualTo(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByExactOrDirectBaseType_AssignsSameInstanceToSameType( + [Frozen(Matching.ExactType | Matching.DirectBaseType)] + ConcreteType p1, + ConcreteType p2) + { + await Assert.That(p2).IsEqualTo(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByInterface_AssignsSameInstanceToSecond( + [Frozen(Matching.ImplementedInterfaces)] + NoopInterfaceImplementer p1, + IInterface p2) + { + await Assert.That(p2).IsSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByInterface_DoesNotAssignToNonInterfaceType( + [Frozen(Matching.ImplementedInterfaces)] + NoopInterfaceImplementer p1, + object p2) + { + await Assert.That(p2).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByInterface_DoesNotAssignToSameType( + [Frozen(Matching.ImplementedInterfaces)] + NoopInterfaceImplementer p1, + NoopInterfaceImplementer p2) + { + await Assert.That(p2).IsNotEqualTo(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByDirectOrInterface_AssignsSameInstanceToSameType( + [Frozen(Matching.ExactType | Matching.ImplementedInterfaces)] + NoopInterfaceImplementer p1, + NoopInterfaceImplementer p2) + { + await Assert.That(p2).IsEqualTo(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByParameterSameName_AssignsSameInstanceToSecond( + [Frozen(Matching.ParameterName)] string parameter, + SingleParameterType p2) + { + await Assert.That(p2.Parameter).IsSameReferenceAs(parameter); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByParameterDifferentName_DoesNotAssignToSecond( + [Frozen(Matching.ParameterName)] string p1, + SingleParameterType p2) + { + await Assert.That(p2.Parameter).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByParameterDifferentName_DoesNotAssignToSameType( + [Frozen(Matching.ParameterName)] string p1, + SingleParameterType p2) + { + await Assert.That(p2.Parameter).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByPropertySameName_AssignsSameInstanceToSecond( + [Frozen(Matching.PropertyName)] string property, + PropertyHolder p2) + { + await Assert.That(p2.Property).IsSameReferenceAs(property); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByPropertyDifferentName_DoesNotAssignToSecond( + [Frozen(Matching.PropertyName)] string p1, + PropertyHolder p2) + { + await Assert.That(p2.Property).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByPropertyDifferentName_DoesNotAssignToSameType( + [Frozen(Matching.PropertyName)] string p1, + PropertyHolder p2) + { + await Assert.That(p2.Property).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByFieldSameName_AssignsSameInstanceToSecond( + [Frozen(Matching.FieldName)] string field, + FieldHolder p2) + { + await Assert.That(p2.Field).IsSameReferenceAs(field); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByFieldDifferentName_DoesNotAssignToSecond( + [Frozen(Matching.FieldName)] string p1, + FieldHolder p2) + { + await Assert.That(p2.Field).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByFieldDifferentName_DoesNotAssignToSameType( + [Frozen(Matching.FieldName)] string p1, + FieldHolder p2) + { + await Assert.That(p2.Field).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByMemberSameName_AssignsSameInstanceToMatchingParameter( + [Frozen(Matching.MemberName)] string parameter, + SingleParameterType p2) + { + await Assert.That(p2.Parameter).IsSameReferenceAs(parameter); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToParameter( + [Frozen(Matching.MemberName)] string p1, + SingleParameterType p2) + { + await Assert.That(p2.Parameter).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToParameterOfSameType( + [Frozen(Matching.MemberName)] string p1, + SingleParameterType p2) + { + await Assert.That(p2.Parameter).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByMemberSameName_AssignsSameInstanceToMatchingProperty( + [Frozen(Matching.MemberName)] string property, + PropertyHolder p2) + { + await Assert.That(p2.Property).IsSameReferenceAs(property); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToProperty( + [Frozen(Matching.MemberName)] string p1, + PropertyHolder p2) + { + await Assert.That(p2.Property).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToPropertyOfSameType( + [Frozen(Matching.MemberName)] string p1, + PropertyHolder p2) + { + await Assert.That(p2.Property).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByMemberSameName_AssignsSameInstanceToMatchingField( + [Frozen(Matching.MemberName)] string field, + FieldHolder p2) + { + await Assert.That(p2.Field).IsSameReferenceAs(field); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToField( + [Frozen(Matching.MemberName)] string p1, + FieldHolder p2) + { + await Assert.That(p2.Field).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToFieldOfSameType( + [Frozen(Matching.MemberName)] string p1, + FieldHolder p2) + { + await Assert.That(p2.Field).IsNotSameReferenceAs(p1); + } + + [Test, AutoDataSource] + public async Task WhenFrozenWithStringLengthConstraint_CreatesConstrainedSpecimen( + [Frozen, StringLength(3)] string p) + { + await Assert.That(p.Length == 3).IsTrue(); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/AutoFixture.TUnit.Tests.csproj b/tests/AutoFixture.TUnit.Tests/AutoFixture.TUnit.Tests.csproj index a9bc845..7579098 100644 --- a/tests/AutoFixture.TUnit.Tests/AutoFixture.TUnit.Tests.csproj +++ b/tests/AutoFixture.TUnit.Tests/AutoFixture.TUnit.Tests.csproj @@ -8,22 +8,17 @@ disable - - - - win7-x86 - - - - - - - - - + + + AnyCPU + - + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/tests/AutoFixture.TUnit.Tests/DependencyConstraintsTests.cs b/tests/AutoFixture.TUnit.Tests/DependencyConstraintsTests.cs index df67e71..6f00142 100644 --- a/tests/AutoFixture.TUnit.Tests/DependencyConstraintsTests.cs +++ b/tests/AutoFixture.TUnit.Tests/DependencyConstraintsTests.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace AutoFixture.TUnit.Tests; @@ -15,7 +15,9 @@ public class DependencyConstraintsTests [Arguments("Unquote")] [Arguments("xunit")] [Arguments("xunit.extensions")] - public async Task AssemblyDoesNotReference(string assemblyName) + [Arguments("TUnit.Engine")] + [Arguments("TUnit.Assertions")] + public async Task WhenPackageNameGiven_DoesNotReferenceAssembly(string assemblyName) { // Arrange && Act var typeInfo = typeof(AutoDataSourceAttribute).GetTypeInfo(); @@ -36,7 +38,7 @@ await Assert.That(referencedAssemblies) [Arguments("Unquote")] [Arguments("xunit")] [Arguments("xunit.extensions")] - public async Task UnitTestsAssemblyDoesNotReference(string assemblyName) + public async Task WhenPackageNameGiven_UnitTestsAssemblyDoesNotReference(string assemblyName) { // Arrange && Act var typeInfo = this.GetType().GetTypeInfo(); @@ -46,4 +48,4 @@ public async Task UnitTestsAssemblyDoesNotReference(string assemblyName) await Assert.That(referencedAssemblies) .DoesNotContain(an => an.Name == assemblyName); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/ClassDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/ClassDataSourceTests.cs deleted file mode 100644 index b184f47..0000000 --- a/tests/AutoFixture.TUnit.Tests/Internal/ClassDataSourceTests.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System.Collections; -using AutoFixture.TUnit.Internal; -using AutoFixture.TUnit.Tests.TestTypes; -using TestTypeFoundation; -using TUnit.Assertions.Extensions; - -namespace AutoFixture.TUnit.Tests.Internal; - -public class ClassDataSourceTests -{ - [Test] - public async Task SutIsTestDataSource() - { - // Arrange & Act - var sut = new ClassDataSource(typeof(object)); - - // Assert - await Assert.That(sut).IsAssignableTo(); - } - - [Test] - public async Task ConstructorWithNullTypeThrows() - { - // Act & Assert - await Assert.That(() => _ = new ClassDataSource(null!)).ThrowsExactly(); - } - - [Test] - public async Task ConstructorWithNullParametersThrows() - { - // Act & Assert - await Assert.That(() => _ = new ClassDataSource(typeof(object), null!)).ThrowsExactly(); - } - - [Test] - public async Task TypeIsCorrect() - { - // Arrange - var expected = typeof(object); - var sut = new ClassDataSource(expected); - - // Act - var result = sut.Type; - - // Assert - await Assert.That(result).IsEqualTo(expected); - } - - [Test] - public async Task ParametersIsCorrect() - { - // Arrange - var expected = new[] { new object() }; - var sut = new ClassDataSource(typeof(object), expected); - - // Act - var result = sut.Parameters; - - // Assert - await Assert.That(result).IsEquivalentTo(expected); - } - - [Test] - public async Task ThrowsWhenSourceIsNotEnumerable() - { - // Arrange - var sut = new ClassDataSource(typeof(object)); - var method = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray()).ThrowsExactly(); - } - - [Test] - public async Task GeneratesTestDatWithPrimitiveValues() - { - // Arrange - var expected = new[] - { - new object[] { "hello", 1, new RecordType("world") }, - new object[] { "foo", 2, new RecordType("bar") }, - new object[] { "Han", 3, new RecordType("Solo") } - }; - var sut = new ClassDataSource(typeof(TestSourceWithMixedValues)); - var method = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - - // Act - var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) - .Select(x => x()) - .ToArray(); - - // Assert - await Assert.That(actual).IsEquivalentTo(expected); - } - - private class TestSourceWithMixedValues : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return ["hello", 1, new RecordType("world")]; - yield return ["foo", 2, new RecordType("bar")]; - yield return ["Han", 3, new RecordType("Solo")]; - } - - IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); - } - - [Test] - public async Task ThrowsWhenConstructorParametersDontMatch() - { - // Arrange - var parameters = new object[] { "a", 1 }; - var sut = new ClassDataSource(typeof(TestSourceWithMixedValues), parameters); - var method = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray()).ThrowsException(); - } - - [Test] - public async Task AppliesExpectedConstructorParameters() - { - // Arrange - object[] parameters = [new object[] { "y", 25 }]; - var sut = new ClassDataSource(typeof(DelegatingTestData), parameters); - var method = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - - // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); - - // Assert - await Assert.That(result.Single()).IsEquivalentTo(new object[] { "y", 25 }); - } -} \ No newline at end of file diff --git a/tests/AutoFixture.TUnit.Tests/DataGeneratorMetadataHelper.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataGeneratorMetadataSupport/DataGeneratorMetadataHelper.cs similarity index 72% rename from tests/AutoFixture.TUnit.Tests/DataGeneratorMetadataHelper.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataGeneratorMetadataSupport/DataGeneratorMetadataHelper.cs index 1483b35..6a145da 100644 --- a/tests/AutoFixture.TUnit.Tests/DataGeneratorMetadataHelper.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataGeneratorMetadataSupport/DataGeneratorMetadataHelper.cs @@ -1,7 +1,7 @@ using System.Reflection; using TUnit.Core.Enums; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; public static class DataGeneratorMetadataHelper { @@ -13,7 +13,7 @@ public static DataGeneratorMetadata CreateDataGeneratorMetadata(Type type, strin public static DataGeneratorMetadata CreateDataGeneratorMetadata(MethodInfo methodInfo) { var parameters = methodInfo.GetParameters(); - var type = methodInfo.ReflectedType ?? methodInfo.DeclaringType!; + var type = methodInfo.ReflectedType ?? methodInfo.DeclaringType; var methodName = methodInfo.Name; var parameterMetadatas = parameters @@ -22,32 +22,32 @@ public static DataGeneratorMetadata CreateDataGeneratorMetadata(MethodInfo metho return new DataGeneratorMetadata { Type = DataGeneratorType.TestParameters, - TestBuilderContext = null!, - TestSessionId = null!, + TestBuilderContext = null, + TestSessionId = null, MembersToGenerate = parameterMetadatas .Cast().ToArray(), TestInformation = new MethodMetadata { Type = type, - TypeInfo = new global::TUnit.Core.ConcreteType(type), + TypeInfo = new ConcreteType(type), Name = methodName, GenericTypeCount = 0, - ReturnTypeInfo = new global::TUnit.Core.ConcreteType(typeof(void)), + ReturnTypeInfo = new ConcreteType(typeof(void)), Class = new ClassMetadata { Type = type, - TypeInfo = new global::TUnit.Core.ConcreteType(type), - Assembly = null!, + TypeInfo = new ConcreteType(type), + Assembly = null, Name = type.Name, - Namespace = null!, + Namespace = null, Parameters = [], Properties = [], - Parent = null! + Parent = null }, Parameters = parameterMetadatas, ReturnType = typeof(void), }, - TestClassInstance = null!, + TestClassInstance = null, ClassInstanceArguments = [] }; } @@ -56,8 +56,8 @@ private static ParameterMetadata CreateParameter(ParameterInfo parameterInfo) { return new ParameterMetadata(parameterInfo.ParameterType) { - Name = parameterInfo.Name!, - TypeInfo = new global::TUnit.Core.ConcreteType(parameterInfo.ParameterType), + Name = parameterInfo.Name, + TypeInfo = new ConcreteType(parameterInfo.ParameterType), ReflectionInfo = parameterInfo }; } diff --git a/tests/AutoFixture.TUnit.Tests/Internal/AutoDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/AutoDataSourceTests/CombineTests.cs similarity index 57% rename from tests/AutoFixture.TUnit.Tests/Internal/AutoDataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/AutoDataSourceTests/CombineTests.cs index c120b30..68c58be 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/AutoDataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/AutoDataSourceTests/CombineTests.cs @@ -1,14 +1,14 @@ -using AutoFixture.Kernel; +using AutoFixture.Kernel; using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.AutoDataSourceTests; public class AutoDataSourceTests { [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange & Act var sut = new AutoDataSource(() => new DelegatingFixture()); @@ -18,7 +18,7 @@ public async Task SutIsTestDataSource() } [Test] - public async Task SetsPropertiesToExpectedValues() + public async Task Constructor_WhenCreated_SetsPropertiesToExpectedValues() { // Arrange var fixtureFactory = () => new DelegatingFixture(); @@ -33,7 +33,7 @@ public async Task SetsPropertiesToExpectedValues() } [Test] - public async Task GeneratesTestDataUsingFixture() + public async Task GetData_WhenCalled_GeneratesTestDataUsingFixture() { // Arrange var builder = new CompositeSpecimenBuilder( @@ -48,7 +48,7 @@ public async Task GeneratesTestDataUsingFixture() var method = typeof(SampleTestType).GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).Select(x => x()).ToArray(); + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).Select(x => x()).ToArray(); // Assert await Assert.That(result).IsNotNull(); @@ -56,14 +56,14 @@ public async Task GeneratesTestDataUsingFixture() var item = result.Single(); await Assert.That(item).IsNotNull(); - await Assert.That(item!.Length).IsEqualTo(3); - await Assert.That(item[0]).IsEqualTo("value"); - await Assert.That(item[1]).IsEqualTo(1); - await Assert.That(item[2]).IsEqualTo(12.2); + await Assert.That(item.Length).IsEqualTo(3); + await Assert.That((string)item[0]).IsEqualTo("value"); + await Assert.That((int)item[1]).IsEqualTo(1); + await Assert.That((double)item[2]).IsEqualTo(12.2); } [Test] - public async Task CombinesTestDataFromSourceWithAutoGeneratedValues() + public async Task GetData_WhenSourcePartial_CombinesWithAutoGeneratedValues() { // Arrange var source = new DelegatingDataSource @@ -85,7 +85,7 @@ public async Task CombinesTestDataFromSourceWithAutoGeneratedValues() .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).ToArray(); + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); // Assert await Assert.That(result).IsNotNull(); @@ -96,7 +96,7 @@ public async Task CombinesTestDataFromSourceWithAutoGeneratedValues() } [Test] - public async Task DoesNotGenerateValuesWhenAllValuesProvidedBySource() + public async Task GetData_WhenSourceProvidesAllValues_DoesNotGenerateValues() { // Arrange var source = new DelegatingDataSource @@ -117,7 +117,7 @@ public async Task DoesNotGenerateValuesWhenAllValuesProvidedBySource() .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).ToArray(); + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); // Assert await Assert.That(result).IsNotNull(); @@ -128,7 +128,67 @@ public async Task DoesNotGenerateValuesWhenAllValuesProvidedBySource() } [Test] - public async Task ReturnsNoTestDataWhenSourceReturnsNoTestData() + public async Task GetData_WhenSourceProvidesMoreValuesThanParameters_Throws() + { + // Arrange + var source = new DelegatingDataSource + { + TestData = [["a", 1, 2.0, "extra"]], + }; + var sut = new AutoDataSource(() => new DelegatingFixture(), source); + var method = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method); + + // Act & Assert + await Assert.That(() => sut.GenerateDataSources(metadata).Select(x => x()).ToArray()) + .ThrowsExactly(); + } + + [Test] + public async Task GetData_WhenClassDataSourceProvidesMoreValuesThanParameters_Throws() + { + // Arrange + var source = new ClassDataSource(typeof(ClassWithExcessTestData)); + var sut = new AutoDataSource(() => new Fixture(), source); + var testMethod = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithSingleParameter)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod); + + // Act & Assert + await Assert.That(async () => + { + await foreach (var rowFunc in sut.GetData(metadata)) + { + _ = await rowFunc(); + } + }).ThrowsExactly(); + } + + [Test] + public async Task GetData_WhenMemberDataSourceProvidesMoreValuesThanParameters_Throws() + { + // Arrange + var source = new MemberDataSource( + typeof(AutoDataSourceTests), + nameof(ExcessMemberData)); + var sut = new AutoDataSource(() => new Fixture(), source); + var testMethod = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithSingleParameter)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod); + + // Act & Assert + await Assert.That(async () => + { + await foreach (var rowFunc in sut.GetData(metadata)) + { + _ = await rowFunc(); + } + }).ThrowsExactly(); + } + + [Test] + public async Task GetData_WhenSourceReturnsNoTestData_ReturnsNoRows() { // Arrange var source = new DelegatingDataSource @@ -141,30 +201,30 @@ public async Task ReturnsNoTestDataWhenSourceReturnsNoTestData() .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).ToArray(); + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); // Assert await Assert.That(result).IsEmpty(); } [Test] - public async Task ThrowsWhenSourceReturnsNull() + public async Task GetData_WhenSourceReturnsNull_Throws() { // Arrange - var source = new DelegatingDataSource { TestData = null! }; + var source = new DelegatingDataSource { TestData = null }; var fixture = new DelegatingFixture(); var sut = new AutoDataSource(() => fixture, source); var method = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)) + await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) .ToArray()) .ThrowsException(); } [Test] - public async Task DoesNotCustomizeFixtureWhenParametersNotCustomized() + public async Task GetData_WhenParametersNotCustomized_DoesNotCustomizeFixture() { // Arrange var customizations = new List(); @@ -177,14 +237,14 @@ public async Task DoesNotCustomizeFixtureWhenParametersNotCustomized() .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act - _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).ToArray(); + _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); // Assert await Assert.That(customizations.Count).IsEqualTo(0); } [Test] - public async Task CustomizesFixtureUsingParameterCustomizations() + public async Task GetData_WhenParametersCustomized_CustomizesFixture() { // Arrange var customizations = new List(); @@ -197,14 +257,14 @@ public async Task CustomizesFixtureUsingParameterCustomizations() .GetMethod(nameof(SampleTestType.TestMethodWithCustomizedParameter)); // Act - _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).Select(x => x()).ToArray(); + _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).Select(x => x()).ToArray(); // Assert await Assert.That(customizations.Count).IsGreaterThan(0); } [Test] - public async Task CustomizationsAreAppliedInExpectedOrder() + public async Task GetData_WhenMultipleCustomizations_AppliesInExpectedOrder() { // Arrange var customizations = new List(); @@ -217,7 +277,7 @@ public async Task CustomizationsAreAppliedInExpectedOrder() .GetMethod(nameof(SampleTestType.TestMethodWithMultipleCustomizations)); // Act - _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).Select(x => x()).ToArray(); + _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).Select(x => x()).ToArray(); // Assert using var scope = Assert.Multiple(); @@ -232,4 +292,40 @@ public async Task CustomizationsAreAppliedInExpectedOrder() await Assert.That(compositeCustomizations[0]).IsAssignableTo(); await Assert.That(compositeCustomizations[1]).IsAssignableTo(); } -} \ No newline at end of file + + [Test] + public async Task GetData_WhenSourceYieldsNullRowFactory_Throws() + { + // Arrange + var source = new NullRowFactoryDataSource(); + var sut = new AutoDataSource(() => new DelegatingFixture(), source); + var method = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method); + + // Act & Assert + await Assert.That(async () => + { + await foreach (var rowFunc in sut.GetData(metadata)) + { + _ = await rowFunc(); + } + }).ThrowsExactly(); + } + + public static IEnumerable ExcessMemberData() + { + yield return ["one", "two", "three"]; + } + + private sealed class NullRowFactoryDataSource : BaseDataSourceAttribute + { +#pragma warning disable CS1998 + public override async IAsyncEnumerable>> GetData( + DataGeneratorMetadata dataGeneratorMetadata) + { + yield return null!; + } +#pragma warning restore CS1998 + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs similarity index 74% rename from tests/AutoFixture.TUnit.Tests/Internal/DataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs index 67fb61e..5a9e905 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs @@ -1,13 +1,13 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.BaseDataSourceAttributeTests; public class DataSourceTests { [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange var sut = new DelegatingDataSource(); @@ -17,7 +17,7 @@ public async Task SutIsTestDataSource() } [Test] - public async Task ReturnSingleEmptyArrayWhenMethodHasNoParameters() + public async Task GetDataRowsAsync_WhenMethodHasNoParameters_ReturnsSingleEmptyArray() { // Arrange var sut = new DelegatingDataSource(); @@ -35,10 +35,10 @@ public async Task ReturnSingleEmptyArrayWhenMethodHasNoParameters() } [Test] - public async Task ThrowsWhenNoDataFoundForMethod() + public async Task GetDataRowsAsync_WhenNoDataFound_Throws() { // Arrange - var sut = new DelegatingDataSource { TestData = null! }; + var sut = new DelegatingDataSource { TestData = null }; var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithSingleParameter)); @@ -47,7 +47,7 @@ public async Task ThrowsWhenNoDataFoundForMethod() } [Test] - public async Task ReturnSingleArrayWithSingleItemWhenMethodHasSingleParameter() + public async Task GetDataRowsAsync_WhenMethodHasSingleParameter_ReturnsSingleItemArray() { // Arrange var sut = new DelegatingDataSource @@ -63,20 +63,20 @@ public async Task ReturnSingleArrayWithSingleItemWhenMethodHasSingleParameter() // Assert await Assert.That(result.Length).IsEqualTo(1); var testData = result.Single()(); - await Assert.That(testData!.Length).IsEqualTo(1); - await Assert.That(testData[0]).IsEqualTo("hello"); + await Assert.That(testData.Length).IsEqualTo(1); + await Assert.That((string)testData[0]).IsEqualTo("hello"); } [Test] - public async Task ReturnsArgumentsFittingTestParameters() + public async Task GetDataRowsAsync_WhenCalled_ReturnsArgumentsFittingParameters() { // Arrange var testData = new[] { new object[] { "hello", 16, 32.86d }, - new object[] { null!, -1, -20.22 }, + new object[] { null, -1, -20.22 }, new object[] { "one", 2 }, - new object[] { null! }, + new object[] { null }, new object[] { }, }; var sut = new DelegatingDataSource { TestData = testData }; @@ -93,12 +93,12 @@ public async Task ReturnsArgumentsFittingTestParameters() foreach (var a in actual) { - await Assert.That(a!.Length).IsBetween(0, 3); + await Assert.That(a.Length).IsBetween(0, 3); } } [Test] - public async Task ThrowsWhenTestDataContainsMoreArgumentsThanParameters() + public async Task GetDataRowsAsync_WhenMoreArgumentsThanParameters_Throws() { // Arrange var testData = new[] { new object[] { "hello", 16, 32.86d, "extra" } }; @@ -109,4 +109,4 @@ public async Task ThrowsWhenTestDataContainsMoreArgumentsThanParameters() // Act & Assert await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)).ToArray()).ThrowsExactly(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs new file mode 100644 index 0000000..20a039b --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs @@ -0,0 +1,74 @@ +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Internal.DataSources.ClassDataSourceTests; + +/// +/// Internal ClassDataSource construction leftovers. Row shapes via AutoClassDataSourceAttribute. +/// +public class ConstructionTests +{ + [Test] + public async Task Constructor_WhenCreated_IsDataSource() + { + var sut = new ClassDataSource(typeof(object)); + + await Assert.That(sut).IsAssignableTo(); + } + + [Test] + public async Task Constructor_WhenTypeIsNull_ThrowsArgumentNullException() + { + await Assert.That(() => _ = new ClassDataSource(null)).ThrowsExactly(); + } + + [Test] + public async Task Constructor_WhenParametersIsNull_ThrowsArgumentNullException() + { + await Assert.That(() => _ = new ClassDataSource(typeof(object), null)).ThrowsExactly(); + } + + [Test] + public async Task Type_WhenRead_ReturnsConstructorArgument() + { + var expected = typeof(object); + var sut = new ClassDataSource(expected); + + await Assert.That(sut.Type).IsEqualTo(expected); + } + + [Test] + public async Task Parameters_WhenRead_ReturnsConstructorArguments() + { + var expected = new[] { new object() }; + var sut = new ClassDataSource(typeof(object), expected); + + await Assert.That(sut.Parameters).IsEquivalentTo(expected); + } + + [Test] + public async Task GetData_WhenConstructorParametersDontMatch_Throws() + { + var parameters = new object[] { "a", 1 }; + var sut = new ClassDataSource(typeof(object), parameters); + var method = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); + + await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray()) + .ThrowsException(); + } + + [Test] + public async Task GetData_WhenConstructorParametersMatch_AppliesThem() + { + object[] parameters = [new object[] { "y", 25 }]; + var sut = new ClassDataSource(typeof(DelegatingTestData), parameters); + var method = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); + + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); + + await Assert.That(result.Single()).IsEquivalentTo(new object[] { "y", 25 }); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/FieldDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/FieldDataSourceTests/ConstructionTests.cs similarity index 71% rename from tests/AutoFixture.TUnit.Tests/Internal/FieldDataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/FieldDataSourceTests/ConstructionTests.cs index 4f0d802..3567590 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/FieldDataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/FieldDataSourceTests/ConstructionTests.cs @@ -1,9 +1,9 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.FieldDataSourceTests; public class FieldDataSourceTests { @@ -17,7 +17,7 @@ public class FieldDataSourceTests public static object NonEnumerableField = new object(); [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange var sourceField = typeof(FieldDataSourceTests) @@ -29,14 +29,14 @@ public async Task SutIsTestDataSource() } [Test] - public async Task ThrowsWhenConstructedWithNullField() + public async Task Constructor_WhenFieldIsNull_Throws() { // Act & Assert - await Assert.That(() => new FieldDataSource(null!)).ThrowsExactly(); + await Assert.That(() => new FieldDataSource(null)).ThrowsExactly(); } [Test] - public async Task FieldIsCorrect() + public async Task Field_WhenRead_ReturnsConstructorArgument() { // Arrange var expected = typeof(FieldDataSourceTests) @@ -51,7 +51,7 @@ public async Task FieldIsCorrect() } [Test] - public async Task ThrowsWhenInvokedWithNullTestMethod() + public async Task GetData_WhenTestMethodIsNull_Throws() { // Arrange var sourceField = typeof(FieldDataSourceTests) @@ -59,11 +59,11 @@ public async Task ThrowsWhenInvokedWithNullTestMethod() var sut = new FieldDataSource(sourceField); // Act & Assert - await Assert.That(() => sut.GenerateDataSources(null!).ToArray()).ThrowsExactly(); + await Assert.That(() => sut.GenerateDataSources(null).ToArray()).ThrowsExactly(); } [Test] - public async Task ThrowsWhenSourceIsNotEnumerable() + public async Task GetData_WhenSourceIsScalar_ReturnsSingleRow() { // Arrange var sourceField = typeof(FieldDataSourceTests) @@ -72,12 +72,18 @@ public async Task ThrowsWhenSourceIsNotEnumerable() var method = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray()).ThrowsExactly(); + // Act + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) + .Select(x => x()) + .ToArray(); + + // Assert + await Assert.That(result.Length).IsEqualTo(1); + await Assert.That(result[0]).IsEquivalentTo(new object[] { NonEnumerableField }); } [Test] - public async Task GeneratesTestDataMatchingTestParameters() + public async Task GetData_WhenCalled_ReturnsDataMatchingParameters() { // Arrange var expected = new[] @@ -107,4 +113,4 @@ public async Task GeneratesTestDataMatchingTestParameters() ["foo", 2, new RecordType("bar")], ["Han", 3, new RecordType("Solo")] ]; -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/InlineDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/InlineDataSourceTests/ConstructionTests.cs similarity index 69% rename from tests/AutoFixture.TUnit.Tests/Internal/InlineDataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/InlineDataSourceTests/ConstructionTests.cs index 85847b9..2616e78 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/InlineDataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/InlineDataSourceTests/ConstructionTests.cs @@ -1,13 +1,13 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.InlineDataSourceTests; public class InlineDataSourceTests { [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange // Act @@ -18,16 +18,16 @@ public async Task SutIsTestDataSource() } [Test] - public async Task InitializeWithNullValuesThrows() + public async Task Constructor_WhenValuesIsNull_Throws() { // Arrange // Act & Assert await Assert.That(() => - new InlineDataSource(null!)).ThrowsExactly(); + new InlineDataSource(null)).ThrowsExactly(); } [Test] - public async Task ValuesIsCorrect() + public async Task Values_WhenRead_ReturnsConstructorArguments() { // Arrange var expectedValues = Array.Empty(); @@ -39,18 +39,22 @@ public async Task ValuesIsCorrect() } [Test] - public async Task GetTestDataWithNullMethodThrows() + public async Task GetData_WhenMethodIsNull_Throws() { // Arrange var sut = new InlineDataSource([ ]); - // Act & Assert - await Assert.That(() => - sut.GenerateDataSources(null!).ToArray()).ThrowsExactly(); + // Act & Assert - call GetData directly so InlineDataSource's null guard is hit + await Assert.That(async () => + { + await foreach (var _ in sut.GetData(null)) + { + } + }).ThrowsExactly(); } [Test] - public async Task SourceThrowsWhenArgumentCountExceedParameterCount() + public async Task GetData_WhenArgumentCountExceedsParameterCount_Throws() { // Arrange var values = new object[] { "aloha", 42, 12.3d, "extra" }; @@ -66,7 +70,7 @@ await Assert.That(() => } [Test] - public async Task ReturnsTestDataWhenArgumentCountMatchesParameterCount() + public async Task GetData_WhenArgumentCountMatchesParameterCount_ReturnsTestData() { // Arrange var values = new object[] { "aloha", 42, 12.3d }; @@ -83,7 +87,7 @@ public async Task ReturnsTestDataWhenArgumentCountMatchesParameterCount() } [Test] - public async Task ReturnsAllArgumentsWhenArgumentCountLessThanParameterCount() + public async Task GetData_WhenArgumentCountLessThanParameterCount_ReturnsAllArguments() { // Arrange var values = new object[] { "aloha", 42 }; @@ -98,4 +102,4 @@ public async Task ReturnsAllArgumentsWhenArgumentCountLessThanParameterCount() var testData = await Assert.That(result).HasSingleItem(); await Assert.That(testData).IsEqualTo(values); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/MemberDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MemberDataSourceTests/ConstructionTests.cs similarity index 62% rename from tests/AutoFixture.TUnit.Tests/Internal/MemberDataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/MemberDataSourceTests/ConstructionTests.cs index 8b30299..6488939 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/MemberDataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MemberDataSourceTests/ConstructionTests.cs @@ -1,9 +1,9 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; -using TUnit.Assertions.Extensions; using PropertyDataSource = AutoFixture.TUnit.Internal.PropertyDataSource; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.MemberDataSourceTests; public class MemberDataSourceTests { @@ -15,7 +15,7 @@ public class MemberDataSourceTests public static IEnumerable GetEmptyTestData() => Array.Empty(); [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange & Act var sut = new MemberDataSource( @@ -27,38 +27,38 @@ public async Task SutIsTestDataSource() } [Test] - public async Task ThrowsWhenTypeIsNull() + public async Task Constructor_WhenTypeIsNull_Throws() { // Arrange var method = nameof(GetEmptyTestData); // Act & Assert - await Assert.That(() => new MemberDataSource(null!, method)).ThrowsExactly(); + await Assert.That(() => new MemberDataSource(null, method)).ThrowsExactly(); } [Test] - public async Task ThrowsWhenNameIsNull() + public async Task Constructor_WhenNameIsNull_Throws() { // Arrange var type = typeof(MemberDataSourceTests); // Act & Assert - await Assert.That(() => new MemberDataSource(type, null!)).ThrowsExactly(); + await Assert.That(() => new MemberDataSource(type, null)).ThrowsExactly(); } [Test] - public async Task ThrowsWhenArgumentsIsNull() + public async Task Constructor_WhenArgumentsIsNull_Throws() { // Arrange var type = typeof(MemberDataSourceTests); var method = nameof(GetEmptyTestData); // Act & Assert - await Assert.That(() => new MemberDataSource(type, method, null!)).ThrowsExactly(); + await Assert.That(() => new MemberDataSource(type, method, null)).ThrowsExactly(); } [Test] - public async Task InitializesTypeProperty() + public async Task Type_WhenRead_ReturnsConstructorArgument() { // Arrange var type = typeof(MemberDataSourceTests); @@ -77,7 +77,7 @@ public async Task InitializesTypeProperty() [Arguments(nameof(EmptyTestDataField), typeof(FieldDataSource))] [Arguments(nameof(EmptyTestData), typeof(PropertyDataSource))] [Arguments(nameof(GetEmptyTestData), typeof(MethodDataSource))] - public async Task InitializesSourceProperty(string memberName, Type expectedInnerSourceType) + public async Task Source_WhenRead_ReturnsResolvedMember(string memberName, Type expectedInnerSourceType) { // Arrange var type = typeof(MemberDataSourceTests); @@ -90,7 +90,7 @@ public async Task InitializesSourceProperty(string memberName, Type expectedInne } [Test] - public async Task ThrowsWhenSourceDoesNotExist() + public async Task GetData_WhenSourceDoesNotExist_Throws() { // Arrange var type = typeof(MemberDataSourceTests); @@ -103,12 +103,24 @@ public async Task ThrowsWhenSourceDoesNotExist() [Arguments(nameof(NonTestDataField))] [Arguments(nameof(NonTestDataProperty))] [Arguments(nameof(NonTestDataMethod))] - public async Task ThrowsWhenSourceDoesNotReturnTestData(string memberName) + public async Task GetData_WhenSourceReturnsScalar_ReturnsSingleRow(string memberName) { // Arrange var type = typeof(MemberDataSourceTests); + var sut = new MemberDataSource(type, memberName); + var testMethod = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!); - // Act & Assert - await Assert.That(() => _ = new DelegatingMemberDataSource(type, memberName)).ThrowsExactly(); + // Act + var result = new List(); + await foreach (var rowFunc in sut.GetData(metadata)) + { + result.Add(await rowFunc()); + } + + // Assert + await Assert.That(result.Count).IsEqualTo(1); + await Assert.That(result[0]!.Length).IsEqualTo(1); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs new file mode 100644 index 0000000..f0ba263 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs @@ -0,0 +1,72 @@ +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.Internal.DataSources.MethodDataSourceTests; + +/// +/// Internal MethodDataSource construction and wiring leftovers. +/// Row shapes are covered via AutoMemberDataSourceAttribute. +/// +public class ConstructionTests +{ + public static IEnumerable ObjectArrayRows() + { + yield return ["hello", 1, new RecordType("world")]; + yield return ["foo", 2, new RecordType("bar")]; + } + + [Test] + public async Task Constructor_WhenCreated_IsDataSource() + { + var methodInfo = typeof(ConstructionTests).GetMethod(nameof(this.Constructor_WhenCreated_IsDataSource)); + var sut = new MethodDataSource(methodInfo); + + await Assert.That(sut).IsAssignableTo(); + } + + [Test] + public async Task Constructor_WhenMethodInfoIsNull_ThrowsArgumentNullException() + { + await Assert.That(() => new MethodDataSource(null)).ThrowsExactly(); + } + + [Test] + public async Task Constructor_WhenArgumentsIsNull_ThrowsArgumentNullException() + { + var methodInfo = typeof(ConstructionTests).GetMethod(nameof(this.Constructor_WhenCreated_IsDataSource)); + + await Assert.That(() => new MethodDataSource(methodInfo, null)).ThrowsExactly(); + } + + [Test] + public async Task Constructor_WhenArgumentsProvided_SetsMembers() + { + var methodInfo = typeof(ConstructionTests).GetMethod(nameof(this.Constructor_WhenCreated_IsDataSource)); + var arguments = new[] { new object() }; + + var sut = new MethodDataSource(methodInfo, arguments); + + await Assert.That(sut.MethodInfo).IsEqualTo(methodInfo); + await Assert.That(sut.Arguments).IsEquivalentTo(arguments); + } + + [Test] + public async Task GetData_WhenInvoked_CallsSourceMethod() + { + var expected = new[] + { + new object[] { "hello", 1, new RecordType("world") }, + new object[] { "foo", 2, new RecordType("bar") } + }; + var sourceMethod = typeof(ConstructionTests).GetMethod(nameof(ObjectArrayRows)); + var testMethod = typeof(SampleTestType).GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); + var sut = new MethodDataSource(sourceMethod); + + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) + .Select(x => x()); + + await Assert.That(result).IsEquivalentTo(expected); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs new file mode 100644 index 0000000..ae53e3f --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs @@ -0,0 +1,33 @@ +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Internal.DataSources.MethodDataSourceTests; + +/// +/// Leftover Internal coverage for branches awkward to express via public attributes +/// (nested Task unwrap). Prefer AutoMemberDataSourceAttribute shape tests for normal cases. +/// +public class ResultShapeLeftoverTests +{ + [Test] + public async Task GetData_WhenNestedTaskOfTupleSequence_UnwrapsAllTasksAndExpandsTuples() + { + var sourceMethod = typeof(ResultShapeLeftoverTests).GetMethod(nameof(NestedTaskOfTupleSequence)); + var testMethod = typeof(SampleTestType).GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); + var sut = new MethodDataSource(sourceMethod!); + + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) + .Select(x => x()) + .ToArray(); + + await Assert.That(result).IsEquivalentTo(new object[][] + { + ["a", 1], + ["b", 2] + }); + } + + public static Task>> NestedTaskOfTupleSequence() => + Task.FromResult(Task.FromResult>([("a", 1), ("b", 2)])); +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/PropertyDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/PropertyDataSourceTests/ConstructionTests.cs similarity index 72% rename from tests/AutoFixture.TUnit.Tests/Internal/PropertyDataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/PropertyDataSourceTests/ConstructionTests.cs index 588ad52..2f5a4ba 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/PropertyDataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/PropertyDataSourceTests/ConstructionTests.cs @@ -1,15 +1,15 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -using TUnit.Assertions.Extensions; using PropertyDataSource = AutoFixture.TUnit.Internal.PropertyDataSource; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.PropertyDataSourceTests; public class PropertyDataSourceTests { [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange var sourceProperty = typeof(PropertyDataSourceTests) @@ -30,14 +30,14 @@ public async Task SutIsTestDataSource() public static object NonEnumerableProperty => new object(); [Test] - public async Task ThrowsWhenConstructedWithNullProperty() + public async Task Constructor_WhenPropertyIsNull_Throws() { // Act & Assert - await Assert.That(() => new PropertyDataSource(null!)).ThrowsExactly(); + await Assert.That(() => new PropertyDataSource(null)).ThrowsExactly(); } [Test] - public async Task PropertyIsCorrect() + public async Task Property_WhenRead_ReturnsConstructorArgument() { // Arrange var expected = typeof(PropertyDataSourceTests) @@ -52,7 +52,7 @@ public async Task PropertyIsCorrect() } [Test] - public async Task ThrowsWhenInvokedWithNullTestMethod() + public async Task GetData_WhenTestMethodIsNull_Throws() { // Arrange var sourceProperty = typeof(PropertyDataSourceTests) @@ -60,11 +60,11 @@ public async Task ThrowsWhenInvokedWithNullTestMethod() var sut = new PropertyDataSource(sourceProperty); // Act & Assert - await Assert.That(() => sut.GenerateDataSources(null!).ToArray()).ThrowsExactly(); + await Assert.That(() => sut.GenerateDataSources(null).ToArray()).ThrowsExactly(); } [Test] - public async Task ThrowsWhenSourceIsNotEnumerable() + public async Task GetData_WhenSourceIsScalar_ReturnsSingleRow() { // Arrange var sourceProperty = typeof(PropertyDataSourceTests) @@ -73,14 +73,18 @@ public async Task ThrowsWhenSourceIsNotEnumerable() var method = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) + // Act + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) + .Select(x => x()) + .ToArray(); - .ToArray()).ThrowsExactly(); + // Assert + await Assert.That(result.Length).IsEqualTo(1); + await Assert.That(result[0].Length).IsEqualTo(1); } [Test] - public async Task GeneratesTestDataMatchingTestParameters() + public async Task GetData_WhenCalled_ReturnsDataMatchingParameters() { // Arrange var expected = new[] @@ -112,14 +116,14 @@ public async Task GeneratesTestDataMatchingTestParameters() ]; [Test] - public async Task ReturnsNullArguments() + public async Task GetData_WhenSourceReturnsNull_ReturnsNullArguments() { // Arrange var expected = new[] { - new object[] { null!, 1, null! }, - new object[] { null!, 2, null! }, - new object[] { null!, 3, null! } + new object[] { null, 1, null }, + new object[] { null, 2, null }, + new object[] { null, 3, null } }; var sourceProperty = typeof(PropertyDataSourceTests) .GetProperty(nameof(TestDataPropertyWithNullValues)); @@ -138,8 +142,8 @@ public async Task ReturnsNullArguments() public static IEnumerable TestDataPropertyWithNullValues => [ - [null!, 1, null!], - [null!, 2, null!], - [null!, 3, null!] + [null, 1, null], + [null, 2, null], + [null, 3, null] ]; -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/MethodDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/MethodDataSourceTests.cs deleted file mode 100644 index edbddd8..0000000 --- a/tests/AutoFixture.TUnit.Tests/Internal/MethodDataSourceTests.cs +++ /dev/null @@ -1,106 +0,0 @@ -using AutoFixture.TUnit.Internal; -using AutoFixture.TUnit.Tests.TestTypes; -using TestTypeFoundation; -using TUnit.Assertions.Extensions; - -namespace AutoFixture.TUnit.Tests.Internal; - -public class MethodDataSourceTests -{ - public static IEnumerable GetTestDataFieldWithMixedValues() - { - yield return ["hello", 1, new RecordType("world")]; - yield return ["foo", 2, new RecordType("bar")]; - yield return ["Han", 3, new RecordType("Solo")]; - } - - [Test] - public async Task SutIsTestDataSource() - { - // Arrange - var methodInfo = typeof(MethodDataSourceTests) - .GetMethod(nameof(this.SutIsTestDataSource)); - - // Act - var sut = new MethodDataSource(methodInfo); - - // Assert - await Assert.That(sut).IsAssignableTo(); - } - - [Test] - public async Task ThrowsWhenMethodInfoIsNull() - { - // Act & Assert - await Assert.That(() => - new MethodDataSource(null!)).ThrowsExactly(); - } - - [Test] - public async Task ThrowsWhenArgumentsIsNull() - { - // Arrange - var methodInfo = typeof(MethodDataSourceTests) - .GetMethod(nameof(this.SutIsTestDataSource)); - - // Act & Assert - await Assert.That(() => - new MethodDataSource(methodInfo, null!)).ThrowsExactly(); - } - - [Test] - public async Task ConstructorSetsProperties() - { - // Arrange - var methodInfo = typeof(MethodDataSourceTests) - .GetMethod(nameof(this.SutIsTestDataSource)); - var arguments = new[] { new object() }; - - // Act - var sut = new MethodDataSource(methodInfo, arguments); - - // Assert - await Assert.That(sut.MethodInfo).IsEqualTo(methodInfo); - await Assert.That(sut.Arguments).IsEquivalentTo(arguments); - } - - [Test] - public async Task GetTestDataInvokesMethodInfo() - { - // Arrange - var expected = new[] - { - new object[] { "hello", 1, new RecordType("world") }, - new object[] { "foo", 2, new RecordType("bar") }, - new object[] { "Han", 3, new RecordType("Solo") } - }; - var testDataSource = typeof(MethodDataSourceTests) - .GetMethod(nameof(GetTestDataFieldWithMixedValues)); - var testData = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - var sut = new MethodDataSource(testDataSource); - - // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testData)) - .Select(x => x()); - - // Assert - await Assert.That(result).IsEquivalentTo(expected); - } - - [Test] - public async Task ThrowsWhenMemberDoesNotReturnAnEnumerableValue() - { - // Arrange - var dataSource = typeof(MethodDataSourceTests) - .GetMethod(nameof(NonEnumerableTestData)); - var testData = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - var sut = new MethodDataSource(dataSource); - - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testData)).ToArray()).ThrowsExactly(); - } - - public static object NonEnumerableTestData() => new(); -} \ No newline at end of file diff --git a/tests/AutoFixture.TUnit.Tests/Scenario.cs b/tests/AutoFixture.TUnit.Tests/Scenario.cs deleted file mode 100644 index 2f273df..0000000 --- a/tests/AutoFixture.TUnit.Tests/Scenario.cs +++ /dev/null @@ -1,563 +0,0 @@ -using System.Collections; -using System.ComponentModel.DataAnnotations; -using AutoFixture.TUnit.Tests.TestTypes; -using TestTypeFoundation; -using ConcreteType = TestTypeFoundation.ConcreteType; - -namespace AutoFixture.TUnit.Tests; - -public class Scenario -{ - [Test, AutoDataSource] - public async Task AutoDataProvidesCorrectInteger(int primitiveValue) - { - await Assert.That(primitiveValue).IsNotEqualTo(0); - } - - [Test, AutoDataSource] - public async Task AutoDataProvidesCorrectString(string text) - { - await Assert.That(text).StartsWith("text"); - } - - [Test, AutoDataSource] - public async Task AutoDataProvidesCorrectObject(PropertyHolder ph) - { - await Assert.That(ph).IsNotNull(); - await Assert.That(ph.Property).IsNotNull(); - } - - [Test, AutoDataSource] - public async Task AutoDataProvidesMultipleObjects(PropertyHolder ph, SingleParameterType spt) - { - await Assert.That(ph).IsNotNull(); - await Assert.That(ph.Property).IsNotNull(); - - await Assert.That(spt).IsNotNull(); - await Assert.That(spt.Parameter).IsNotNull(); - } - - [Test] - [AutoArguments("foo")] - [AutoArguments("foo", "bar")] - public async Task InlineAutoDataUsesSuppliedDataValues(string s1, string s2) - { - await Assert.That(s1).IsEqualTo("foo"); - await Assert.That(s2).IsNotNull(); - } - - [Test] - [AutoArguments("foo")] - [AutoArguments("foo", "bar")] - public async Task InlineAutoDataSuppliesDataSpecimens(string s1, string s2, MyClass myClass) - { - await Assert.That(s1).IsEqualTo("foo"); - await Assert.That(s2).IsNotNull(); - await Assert.That(myClass).IsNotNull(); - } - - [Test] - [AutoArguments("foo")] - [AutoArguments("foo", "bar")] - public async Task InlineAutoDataSuppliesDataSpecimensOnlyForNonProvidedValues(string s1, string s2, string s3) - { - await Assert.That(s1).IsEqualTo("foo"); - await Assert.That(s2).IsNotNull(); - await Assert.That(s3).IsNotEqualTo("foo"); - await Assert.That(s3).IsNotEqualTo("bar"); - } - - // This test and its associated types is used to document one of the - // InlineAutoDataAttribute constructor overloads. - [Test] - [MyCustomAutoArguments(1337)] - [MyCustomAutoArguments(1337, 7)] - [MyCustomAutoArguments(1337, 7, 42)] -#pragma warning disable xUnit1026 // Test methods should use all of their parameters - it's required by the test logic. - public async Task CustomInlineDataSuppliesExtraValues(int x, int y, int z) -#pragma warning restore xUnit1026 // Test methods should use all of their parameters - { - await Assert.That(x).IsEqualTo(1337); - - // y can vary, so we can't express any meaningful assertion for it. - await Assert.That(z).IsEqualTo(42); - } - - public class MyCustomAutoArgumentsAttribute - : AutoArgumentsAttribute - { - public MyCustomAutoArgumentsAttribute(params object[] values) - : base(() => new Fixture().Customize(new TheAnswer()), values) - { - } - } - - [Test, AutoMemberDataSource(nameof(StringData))] - public async Task MemberAutoDataUsesSuppliedDataValues(string s1, string s2) - { - await Assert.That(s1).IsEqualTo("foo"); - await Assert.That(s2).IsNotNull(); - } - - [Test, AutoMemberDataSource(nameof(StringData))] - public async Task MemberAutoDataSuppliesDataSpecimens(string s1, string s2, MyClass myClass) - { - await Assert.That(s1).IsEqualTo("foo"); - await Assert.That(s2).IsNotNull(); - await Assert.That(myClass).IsNotNull(); - } - - [Test, AutoMemberDataSource(nameof(StringData))] - public async Task MemberAutoDataSuppliesDataSpecimensOnlyForNonProvidedValues(string s1, string s2, string s3) - { - await Assert.That(s1).IsEqualTo("foo"); - await Assert.That(s2).IsNotNull(); - await Assert.That(s3).IsNotEqualTo("foo"); - await Assert.That(s3).IsNotEqualTo("bar"); - } - - [Test, AutoMemberDataSource(nameof(GetParametrizedData), 21, 38, 43)] - public async Task MemberAutoDataCanBeParametrized(int x, int y, int z) - { - await Assert.That(x).IsEqualTo(21); - await Assert.That(y).IsEqualTo(38); - await Assert.That(z).IsEqualTo(43); - } - - [Test, MyCustomAutoMemberDataSource(nameof(IntData))] - public async Task CustomMemberAutoDataSuppliesExtraValues(int x, int y, int z) - { - await Assert.That(x).IsEqualTo(1337); - await Assert.That(y).IsNotEqualTo(0); - await Assert.That(z).IsEqualTo(42); - } - - [Test, MyCustomAutoMemberDataSource(nameof(GetParametrizedData), 21, 38, 43)] - public async Task CustomMemberAutoDataCanBeParametrized(int x, int y, int z) - { - await Assert.That(x).IsEqualTo(21); - await Assert.That(y).IsEqualTo(38); - await Assert.That(z).IsEqualTo(43); - } - - public static IEnumerable StringData - { - get - { - yield return ["foo"]; - yield return ["foo", "bar"]; - } - } - - public static IEnumerable IntData - { - get - { - yield return [1337]; - yield return [1337, 7]; - yield return [1337, 7, 42]; - } - } - - public static IEnumerable GetParametrizedData(int x, int y, int z) - { - yield return [x, y, z]; - } - - public class MyCustomAutoMemberDataSourceAttribute - : AutoMemberDataSourceAttribute - { - public MyCustomAutoMemberDataSourceAttribute(string memberName, params object[] parameters) - : base(() => new Fixture().Customize(new TheAnswer()), memberName, parameters) - { - } - } - - private class TheAnswer : ICustomization - { - public void Customize(IFixture fixture) - { - fixture.Inject(42); - } - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameter([Frozen] Guid g1, Guid g2) - { - await Assert.That(g2).IsEqualTo(g1); - } - - [Test, AutoDataSource] - public async Task FreezeSecondParameterOnlyFreezesSubsequentParameters(Guid g1, [Frozen] Guid g2, Guid g3) - { - await Assert.That(g2).IsNotEqualTo(g1); - await Assert.That(g3).IsNotEqualTo(g1); - - await Assert.That(g3).IsEqualTo(g2); - } - - [Test, AutoDataSource] - public async Task IntroductoryTest(int expectedNumber, MyClass sut) - { - // Arrange - // Act - int result = sut.Echo(expectedNumber); - - // Assert - await Assert.That(result).IsEqualTo(expectedNumber); - } - - [Test, AutoDataSource] - public async Task ModestCreatesParameterWithModestConstructor([Modest] MultiUnorderedConstructorType p) - { - await Assert.That(string.IsNullOrEmpty(p.Text)).IsTrue(); - await Assert.That(p.Number).IsEqualTo(0); - } - - [Test, AutoDataSource] - public async Task GreedyCreatesParameterWithGreedyConstructor([Greedy] MultiUnorderedConstructorType p) - { - await Assert.That(string.IsNullOrEmpty(p.Text)).IsFalse(); - await Assert.That(p.Number).IsNotEqualTo(0); - } - - [Test, AutoDataSource] - public async Task BothFrozenAndGreedyAttributesCanBeAppliedToSameParameter( - [Frozen][Greedy] MultiUnorderedConstructorType p1, MultiUnorderedConstructorType p2) - { - await Assert.That(p1).IsNotNull(); - await Assert.That(string.IsNullOrEmpty(p2.Text)).IsFalse(); - await Assert.That(p2.Number).IsNotEqualTo(0); - } - - [Test, AutoDataSource] - public async Task FavorArraysCausesArrayConstructorToBeInjectedWithFrozenItems([Frozen] int[] numbers, - [FavorArrays] ItemContainer container) - { - await Assert.That(numbers.SequenceEqual(container.Items)).IsTrue(); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterShouldAssignSameInstanceToSecondParameter([Frozen] string p1, - string p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByExactTypeShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.ExactType)] ConcreteType p1, - ConcreteType p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByExactTypeShouldNotAssignSameInstanceToSecondParameterOfDifferentType( - [Frozen(Matching.ExactType)] ConcreteType p1, - object p2) - { - await Assert.That(p2).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByDirectBaseTypeShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.DirectBaseType)] ConcreteType p1, - AbstractType p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByDirectBaseTypeShouldNotAssignSameInstanceToSecondParameterOfIndirectBaseType( - [Frozen(Matching.DirectBaseType)] ConcreteType p1, - object p2) - { - await Assert.That(p2).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByDirectBaseTypeShouldNotAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.DirectBaseType)] ConcreteType p1, - ConcreteType p2) - { - await Assert.That(p2).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByExactOrDirectBaseTypeShouldAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.ExactType | Matching.DirectBaseType)] - ConcreteType p1, - ConcreteType p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByInterfaceShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.ImplementedInterfaces)] - NoopInterfaceImplementer p1, - IInterface p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByInterfaceShouldNotAssignSameInstanceToSecondParameterOfNonInterfaceType( - [Frozen(Matching.ImplementedInterfaces)] - NoopInterfaceImplementer p1, - object p2) - { - await Assert.That(p2).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByInterfaceShouldNotAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.ImplementedInterfaces)] - NoopInterfaceImplementer p1, - NoopInterfaceImplementer p2) - { - await Assert.That(p2).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByDirectOrInterfaceShouldAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.ExactType | Matching.ImplementedInterfaces)] - NoopInterfaceImplementer p1, - NoopInterfaceImplementer p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByParameterWithSameNameShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.ParameterName)] string parameter, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsEqualTo(parameter); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByParameterWithDifferentNameShouldNotAssignSameInstanceToSecondParameter( - [Frozen(Matching.ParameterName)] string p1, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByParameterWithDifferentNameShouldNotAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.ParameterName)] string p1, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByPropertyWithSameNameShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.PropertyName)] string property, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsEqualTo(property); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByPropertyWithDifferentNameShouldNotAssignSameInstanceToSecondParameter( - [Frozen(Matching.PropertyName)] string p1, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByPropertyWithDifferentNameShouldNotAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.PropertyName)] string p1, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByFieldWithSameNameShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.FieldName)] string field, - FieldHolder p2) - { - await Assert.That(p2.Field).IsEqualTo(field); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByFieldWithDifferentNameShouldNotAssignSameInstanceToSecondParameter( - [Frozen(Matching.FieldName)] string p1, - FieldHolder p2) - { - await Assert.That(p2.Field).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByFieldWithDifferentNameShouldNotAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.FieldName)] string p1, - FieldHolder p2) - { - await Assert.That(p2.Field).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithSameNameShouldAssignSameInstanceToMatchingParameter( - [Frozen(Matching.MemberName)] string parameter, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsEqualTo(parameter); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToParameter( - [Frozen(Matching.MemberName)] string p1, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToParameterOfSameType( - [Frozen(Matching.MemberName)] string p1, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithSameNameShouldAssignSameInstanceToMatchingProperty( - [Frozen(Matching.MemberName)] string property, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsEqualTo(property); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToProperty( - [Frozen(Matching.MemberName)] string p1, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToPropertyOfSameType( - [Frozen(Matching.MemberName)] string p1, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithSameNameShouldAssignSameInstanceToMatchingField( - [Frozen(Matching.MemberName)] string field, - FieldHolder p2) - { - await Assert.That(p2.Field).IsEqualTo(field); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToField( - [Frozen(Matching.MemberName)] string p1, - FieldHolder p2) - { - await Assert.That(p2.Field).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToFieldOfSameType( - [Frozen(Matching.MemberName)] string p1, - FieldHolder p2) - { - await Assert.That(p2.Field).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeParameterWithStringLengthConstraintShouldCreateConstrainedSpecimen( - [Frozen, StringLength(3)] string p) - { - await Assert.That(p.Length == 3).IsTrue(); - } - - [Test, AutoClassDataSource(typeof(StringDataClass))] - public async Task ClassAutoDataUsesValuesSuppliedByClass(string s1, string s2, string s3) - { - await Assert.That(new[] { "foo", "dim" }).Contains(s1); - await Assert.That(s2).IsNotEmpty(); - await Assert.That(s3).IsNotEmpty(); - } - - [Test, AutoClassDataSource(typeof(StringDataClass))] - public async Task ClassAutoDataSuppliesDataSpecimens(string s1, string s2, string s3, MyClass myClass) - { - await Assert.That(s1).IsNotEmpty(); - await Assert.That(s2).IsNotEmpty(); - await Assert.That(s3).IsNotEmpty(); - await Assert.That(myClass).IsNotNull(); - } - - [Test, AutoClassDataSource(typeof(MixedDataClass))] - public async Task ClassAutoDataSuppliesDataOfMixedTypes(int p1, string p2, PropertyHolder p3, MyClass myClass) - { - await Assert.That(p1).IsNotEqualTo(0); - await Assert.That(p2).IsNotEmpty(); - await Assert.That(p3).IsNotNull(); - await Assert.That(p3.Property).IsNotEmpty(); - await Assert.That(myClass).IsNotNull(); - } - - [Test, AutoClassDataSource(typeof(ParameterizedDataClass), 28, "bar", 93.102)] - public async Task ClassAutoDataCanBeParameterized(int p1, string p2, double p3, RecordType p4) - { - var actual = new object[] { p1, p2, p3 }; - var expected = new object[] { 28, "bar", 93.102 }; - - await Assert.That(actual).IsEquivalentTo(expected); - await Assert.That(p4).IsNotNull(); - } - - public class StringDataClass : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return ["foo", "bar", "foobar"]; - yield return ["dim", "sum", "dimsum"]; - } - - IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); - } - - public class MixedDataClass : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return [1]; - yield return [4, "testValue"]; - yield return [20, "otherValue", new PropertyHolder { Property = "testValue1" }]; - } - - IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); - } - - public class ParameterizedDataClass : IEnumerable - { - private readonly int p1; - private readonly string p2; - private readonly double p3; - - public ParameterizedDataClass(int p1, string p2, double p3) - { - this.p1 = p1; - this.p2 = p2; - this.p3 = p3; - } - - public IEnumerator GetEnumerator() - { - yield return [this.p1, this.p2, this.p3]; - } - - IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); - } -} \ No newline at end of file diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ChildTestTypeMethodData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ChildTestTypeMethodData.cs index 79a6ed5..8373033 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ChildTestTypeMethodData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ChildTestTypeMethodData.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -22,4 +22,4 @@ public class ChildTestTypeMethodData : TestTypeWithMethodData return typeof(ChildTestTypeMethodData) .GetMethod(nameof(MultipleValueTest)); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithEmptyTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithEmptyTestData.cs index 276aca2..617aac2 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithEmptyTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithEmptyTestData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -12,4 +12,4 @@ public IEnumerator GetEnumerator() } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithExcessTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithExcessTestData.cs new file mode 100644 index 0000000..352c672 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithExcessTestData.cs @@ -0,0 +1,16 @@ +using System.Collections; + +namespace AutoFixture.TUnit.Tests.TestTypes; + +/// +/// Yields rows with more values than a typical one-parameter test method needs. +/// +public class ClassWithExcessTestData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return ["one", "two", "three"]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithNullTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithNullTestData.cs index e95410f..5cee59c 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithNullTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithNullTestData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -6,10 +6,10 @@ public class ClassWithNullTestData : IEnumerable { public IEnumerator GetEnumerator() { - yield return null!; - yield return null!; - yield return null!; + yield return null; + yield return null; + yield return null; } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/CompositeTypeWithOverloadedConstructors.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/CompositeTypeWithOverloadedConstructors.cs index b7c8744..f836d09 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/CompositeTypeWithOverloadedConstructors.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/CompositeTypeWithOverloadedConstructors.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; public class CompositeTypeWithOverloadedConstructors { @@ -18,4 +18,4 @@ public CompositeTypeWithOverloadedConstructors(IEnumerable items) } public IEnumerable Items { get; } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/ClassDataShapes.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/ClassDataShapes.cs new file mode 100644 index 0000000..deed7fa --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/ClassDataShapes.cs @@ -0,0 +1,125 @@ +using System.Collections; +using System.Runtime.CompilerServices; +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; + +public class ObjectArrayClassData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return ["hello", 1, new RecordType("world")]; + yield return ["foo", 2, new RecordType("bar")]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} + +public class StringSequenceClassData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return "alpha"; + yield return "beta"; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} + +public class TupleSequenceClassData : IEnumerable<(string, int)> +{ + public IEnumerator<(string, int)> GetEnumerator() + { + yield return ("a", 1); + yield return ("b", 2); + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} + +public class AsyncObjectArrayClassData : IAsyncEnumerable +{ + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => + EnumerateAsync(cancellationToken).GetAsyncEnumerator(cancellationToken); + + private static async IAsyncEnumerable EnumerateAsync( + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + yield return ["hello", 1, new RecordType("world")]; + yield return ["foo", 2, new RecordType("bar")]; + await Task.CompletedTask; + } +} + +public class AsyncStringSequenceClassData : IAsyncEnumerable +{ + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => + EnumerateAsync(cancellationToken).GetAsyncEnumerator(cancellationToken); + + private static async IAsyncEnumerable EnumerateAsync( + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + yield return "alpha"; + yield return "beta"; + await Task.CompletedTask; + } +} + +public class AsyncTupleSequenceClassData : IAsyncEnumerable<(string, int)> +{ + public IAsyncEnumerator<(string, int)> GetAsyncEnumerator(CancellationToken cancellationToken = default) => + EnumerateAsync(cancellationToken).GetAsyncEnumerator(cancellationToken); + + private static async IAsyncEnumerable<(string, int)> EnumerateAsync( + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + yield return ("a", 1); + yield return ("b", 2); + await Task.CompletedTask; + } +} + +public class EmptyAsyncObjectArrayClassData : IAsyncEnumerable +{ + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => + EnumerateAsync(cancellationToken).GetAsyncEnumerator(cancellationToken); + + private static async IAsyncEnumerable EnumerateAsync( + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + await Task.CompletedTask; + yield break; + } +} + +/// +/// Non-enumerable source type: the constructed instance becomes a single-cell row. +/// +public class StringScalarClassData +{ + public string Value { get; } = "seed"; +} + +/// +/// One row with no columns so AutoClassDataSource fills every constructor parameter. +/// +public class OneEmptyRowClassData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return []; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} + +public class IntSequenceClassData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return 11; + yield return 22; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs new file mode 100644 index 0000000..76a890d --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs @@ -0,0 +1,84 @@ +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; + +/// +/// Shared member data shapes for public AutoMemberDataSourceAttribute coverage. +/// +public static class MemberDataShapes +{ + public static object? NullValue() => null; + + public static string StringScalar() => "hello"; + + public static object ObjectScalar() => new object(); + + public static (string, int) SingleTuple() => ("a", 1); + + public static IEnumerable EmptyObjectArrays() => Array.Empty(); + + public static IEnumerable ObjectArrays() + { + yield return ["hello", 1, new RecordType("world")]; + yield return ["foo", 2, new RecordType("bar")]; + } + + public static IEnumerable Strings() + { + yield return "one"; + yield return "two"; + } + + public static IEnumerable<(string, int)> Tuples() + { + yield return ("a", 1); + yield return ("b", 2); + } + + public static Task> TaskOfObjectArrays() => + Task.FromResult(ObjectArrays()); + + public static Task> TaskOfTuples() => + Task.FromResult(Tuples()); + + public static async IAsyncEnumerable AsyncObjectArrays() + { + foreach (var row in ObjectArrays()) + { + yield return row; + } + + await Task.CompletedTask; + } + + public static async IAsyncEnumerable AsyncStrings() + { + foreach (var value in Strings()) + { + yield return value; + } + + await Task.CompletedTask; + } + + public static async IAsyncEnumerable<(string, int)> AsyncTuples() + { + foreach (var value in Tuples()) + { + yield return value; + } + + await Task.CompletedTask; + } + + public static async IAsyncEnumerable EmptyAsyncObjectArrays() + { + await Task.CompletedTask; + yield break; + } + + // Field / property mirrors for resolve-member coverage + public static readonly IEnumerable<(string, int)> TupleField = [("a", 1), ("b", 2)]; + + public static IEnumerable<(string, int)> TupleProperty => [("a", 1), ("b", 2)]; +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomization.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomization.cs index d297a7c..e881bb4 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomization.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomization.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; internal class DelegatingCustomization : ICustomization { @@ -13,4 +13,4 @@ public void Customize(IFixture fixture) } internal Action OnCustomize { get; set; } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomizeAttribute.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomizeAttribute.cs index b04bd83..ce33ac8 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomizeAttribute.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomizeAttribute.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -10,4 +10,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter) } public Func OnGetCustomization { get; set; } = p => new DelegatingCustomization(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingFixture.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingFixture.cs index 1615294..b8da0bd 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingFixture.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingFixture.cs @@ -1,4 +1,4 @@ -using AutoFixture.Dsl; +using AutoFixture.Dsl; using AutoFixture.Kernel; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -91,4 +91,4 @@ public object Create(object request, ISpecimenContext context) internal Func OnCreate { get; set; } = (_, _) => new object(); internal Action OnCustomize { get; set; } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingMemberDataSource.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingMemberDataSource.cs index 7f198ba..2744020 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingMemberDataSource.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingMemberDataSource.cs @@ -1,4 +1,4 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -11,4 +11,4 @@ public DelegatingMemberDataSource(Type type, string name, params object[] argume } public DataSource GetSource() => this.Source; -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingSpecimenBuilder.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingSpecimenBuilder.cs index c5d6e79..5fa763f 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingSpecimenBuilder.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingSpecimenBuilder.cs @@ -1,4 +1,4 @@ -using AutoFixture.Kernel; +using AutoFixture.Kernel; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -10,4 +10,4 @@ public object Create(object request, ISpecimenContext context) } internal Func OnCreate { get; set; } = (_, _) => new object(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingTestData.cs index b8d688b..734a3dc 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingTestData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -19,4 +19,4 @@ public DelegatingTestData(IEnumerable data) public IEnumerator GetEnumerator() => this.data.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoArgumentsAttribute.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoArgumentsAttribute.cs index 701064d..47d80d1 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoArgumentsAttribute.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoArgumentsAttribute.cs @@ -7,4 +7,4 @@ public DerivedAutoArgumentsAttribute(Func fixtureFactory, params objec : base(fixtureFactory, values) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoClassDataSourceAttribute.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoClassDataSourceAttribute.cs index 92fe044..46d7adc 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoClassDataSourceAttribute.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoClassDataSourceAttribute.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; public class DerivedAutoClassDataSourceAttribute : AutoClassDataSourceAttribute { @@ -11,4 +11,4 @@ public DerivedAutoClassDataSourceAttribute(Func fixtureFactory, Type s : base(fixtureFactory, sourceType, parameters) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoDataSourceAttribute.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoDataSourceAttribute.cs index e8f3dee..ce56eb3 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoDataSourceAttribute.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoDataSourceAttribute.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; public class DerivedAutoDataSourceAttribute : AutoDataSourceAttribute { @@ -6,4 +6,4 @@ public DerivedAutoDataSourceAttribute(Func fixtureFactory) : base(fixtureFactory) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoMemberDataSourceAttribute.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoMemberDataSourceAttribute.cs index 0daf5ec..aa4f170 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoMemberDataSourceAttribute.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoMemberDataSourceAttribute.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; public class DerivedAutoMemberDataSourceAttribute : AutoMemberDataSourceAttribute { @@ -11,4 +11,4 @@ public DerivedAutoMemberDataSourceAttribute(Func fixtureFactory, Type : base(fixtureFactory, memberType, memberName, parameters) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/EmptyClassData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/EmptyClassData.cs index b9a8f61..1aa8629 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/EmptyClassData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/EmptyClassData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -10,4 +10,4 @@ public IEnumerator GetEnumerator() } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ExampleTestClass.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ExampleTestClass.cs index 8f3b637..e05622e 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ExampleTestClass.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ExampleTestClass.cs @@ -1,12 +1,9 @@ -using System.Diagnostics.CodeAnalysis; using TestTypeFoundation; namespace AutoFixture.TUnit.Tests.TestTypes; public class ExampleTestClass { - [SuppressMessage("Usage", "xUnit1013:Public method should be marked as test", - Justification = "This test method is used through reflection.")] public void TestMethod(int a, string b, EnumType c, Tuple d) { } @@ -14,9 +11,7 @@ public void TestMethod(int a, string b, EnumType c, Tuple d) public class ExampleTestClass { - [SuppressMessage("Usage", "xUnit1013:Public method should be marked as test", - Justification = "This test method is used through reflection.")] public void TestMethod(T1 a, T2 b, T3 c, T4 d) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/FixedParameterBuilder.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/FixedParameterBuilder.cs index 9ef50fc..d066e48 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/FixedParameterBuilder.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/FixedParameterBuilder.cs @@ -9,4 +9,4 @@ public FixedParameterBuilder(string name, T value) : base(new FixedBuilder(value), new ParameterSpecification(typeof(T), name)) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/InlineAttributeTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/InlineAttributeTestData.cs index 3a2533d..fcaf5b2 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/InlineAttributeTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/InlineAttributeTestData.cs @@ -52,4 +52,4 @@ ICustomization CreateCustomization() } public abstract IEnumerable GetData(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/InlineFrozenValuesTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/InlineFrozenValuesTestData.cs index 328be8d..a0e642f 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/InlineFrozenValuesTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/InlineFrozenValuesTestData.cs @@ -32,4 +32,4 @@ internal class InlineFrozenValuesTestData : InlineAttributeTestData<(BaseDataSou TestTypeWithMemberDataSource.GetTestWithFrozenParameter(), ["string_a2", "string_b2", "string_b2"]); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/InlinePrimitiveValuesTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/InlinePrimitiveValuesTestData.cs index e77d8ea..1514473 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/InlinePrimitiveValuesTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/InlinePrimitiveValuesTestData.cs @@ -35,4 +35,4 @@ internal class InlinePrimitiveValuesTestData : InlineAttributeTestData<(BaseData ["parameter_a3", 13, 332.009m] ); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/MixedTypeClassData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/MixedTypeClassData.cs index e6b2243..26d64a5 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/MixedTypeClassData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/MixedTypeClassData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using TestTypeFoundation; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -15,4 +15,4 @@ public IEnumerator GetEnumerator() } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/MyClass.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/MyClass.cs index c955db3..84695ee 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/MyClass.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/MyClass.cs @@ -1,6 +1,6 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; public class MyClass { public T Echo(T item) => item; -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterNameCriterion.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterNameCriterion.cs index 274c65d..fa6b17e 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterNameCriterion.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterNameCriterion.cs @@ -24,4 +24,4 @@ public bool Equals(ParameterInfo other) { return this.NameCriterion.Equals(other.Name); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterizedClassData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterizedClassData.cs index 59d2452..3eba681 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterizedClassData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterizedClassData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using TestTypeFoundation; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -23,4 +23,4 @@ public IEnumerator GetEnumerator() } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/SampleTestType.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/SampleTestType.cs index 7e5ec85..3bd63ca 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/SampleTestType.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/SampleTestType.cs @@ -1,4 +1,4 @@ -using TestTypeFoundation; +using TestTypeFoundation; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -16,6 +16,10 @@ public void TestMethodWithMultipleParameters(string a, int b, double c) { } + public void TestMethodWithTwoParameters(string a, int b) + { + } + public void TestMethodWithReferenceTypeParameter(string a, int b, PropertyHolder c) { } @@ -35,4 +39,4 @@ public void TestMethodWithCustomizedParameter([Frozen] string a, int b, Property public void TestMethodWithMultipleCustomizations([Frozen] string a, [Frozen] int b, [Greedy][Frozen] PropertyHolder c) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMemberDataSource.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMemberDataSource.cs index 0a145e6..dd66f94 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMemberDataSource.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMemberDataSource.cs @@ -1,12 +1,9 @@ -using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace AutoFixture.TUnit.Tests.TestTypes; internal class TestTypeWithMemberDataSource { - [SuppressMessage("Usage", "xUnit1013:Public method should be marked as test", - Justification = "Test is invoked through reflection.")] public async Task MultipleValueTest(string a, int b, decimal c) { await Assert.That(a).IsNotNull(); @@ -34,4 +31,4 @@ public static MethodInfo GetMultipleValueTestMethodInfo() => public static MethodInfo GetTestWithFrozenParameter() => typeof(TestTypeWithMemberDataSource) .GetMethod(nameof(TestWithFrozenParameter)); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMethodData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMethodData.cs index 751998b..c7a2e43 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMethodData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMethodData.cs @@ -156,4 +156,4 @@ public static IEnumerable GetStringValuesTestData() } public static IEnumerable GetEmptyTestData() => []; -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithCustomizationAttributes.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithCustomizationAttributes.cs index e27c00e..b839c7b 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithCustomizationAttributes.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithCustomizationAttributes.cs @@ -1,4 +1,3 @@ -using TestTypeFoundation; using ConcreteType = TestTypeFoundation.ConcreteType; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -52,4 +51,4 @@ public void CreateWithFrozenAndNoAutoProperties([Frozen, NoAutoProperties] Concr public void CreateWithNoAutoPropertiesAndFrozen([NoAutoProperties, Frozen] ConcreteType sut) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithIParameterCustomizationSourceUsage.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithIParameterCustomizationSourceUsage.cs index 8099949..224523d 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithIParameterCustomizationSourceUsage.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithIParameterCustomizationSourceUsage.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -23,4 +23,4 @@ public void Customize(IFixture fixture) { } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/AbstractClassWithPublicConstructor.cs b/tests/TestTypeFoundation/AbstractClassWithPublicConstructor.cs index 1e038eb..47c8cf2 100644 --- a/tests/TestTypeFoundation/AbstractClassWithPublicConstructor.cs +++ b/tests/TestTypeFoundation/AbstractClassWithPublicConstructor.cs @@ -1,5 +1,5 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public abstract class AbstractClassWithPublicConstructor { -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/AbstractGenericType.cs b/tests/TestTypeFoundation/AbstractGenericType.cs index 376b3a1..a3ce742 100644 --- a/tests/TestTypeFoundation/AbstractGenericType.cs +++ b/tests/TestTypeFoundation/AbstractGenericType.cs @@ -8,4 +8,4 @@ protected AbstractGenericType(T value) } public T Value { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/AbstractType.cs b/tests/TestTypeFoundation/AbstractType.cs index ab273cd..7a3016f 100644 --- a/tests/TestTypeFoundation/AbstractType.cs +++ b/tests/TestTypeFoundation/AbstractType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public abstract class AbstractType { @@ -11,4 +11,4 @@ public abstract class AbstractType public virtual object Property4 { get; set; } public object Field1; -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/AbstractTypeWithConstructorWithMultipleParameters.cs b/tests/TestTypeFoundation/AbstractTypeWithConstructorWithMultipleParameters.cs index 1ab088a..087a7af 100644 --- a/tests/TestTypeFoundation/AbstractTypeWithConstructorWithMultipleParameters.cs +++ b/tests/TestTypeFoundation/AbstractTypeWithConstructorWithMultipleParameters.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public abstract class AbstractTypeWithConstructorWithMultipleParameters { @@ -11,4 +11,4 @@ protected AbstractTypeWithConstructorWithMultipleParameters(T1 parameter1, T2 pa public T1 Property1 { get; } public T2 Property2 { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/AbstractTypeWithNonDefaultConstructor.cs b/tests/TestTypeFoundation/AbstractTypeWithNonDefaultConstructor.cs index 17a2342..93839d8 100644 --- a/tests/TestTypeFoundation/AbstractTypeWithNonDefaultConstructor.cs +++ b/tests/TestTypeFoundation/AbstractTypeWithNonDefaultConstructor.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public abstract class AbstractTypeWithNonDefaultConstructor { @@ -10,4 +10,4 @@ protected AbstractTypeWithNonDefaultConstructor(T value) } public T Property { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ActivityScope.cs b/tests/TestTypeFoundation/ActivityScope.cs index 4f34cc0..210b697 100644 --- a/tests/TestTypeFoundation/ActivityScope.cs +++ b/tests/TestTypeFoundation/ActivityScope.cs @@ -42,4 +42,4 @@ public enum ActivityScope : long /// The set all valid scopes. /// All = OnDuty | OffDuty | Standalone | Parent | Child, -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/CollectionHolder.cs b/tests/TestTypeFoundation/CollectionHolder.cs index b0c5432..ae583fc 100644 --- a/tests/TestTypeFoundation/CollectionHolder.cs +++ b/tests/TestTypeFoundation/CollectionHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class CollectionHolder { public ICollection Collection { get; private set; } = new List(); -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/CompositeType.cs b/tests/TestTypeFoundation/CompositeType.cs index 11c503c..458d5cb 100644 --- a/tests/TestTypeFoundation/CompositeType.cs +++ b/tests/TestTypeFoundation/CompositeType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class CompositeType : AbstractType { @@ -13,4 +13,4 @@ public CompositeType(params AbstractType[] types) } public IEnumerable Types { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ConcreteType.cs b/tests/TestTypeFoundation/ConcreteType.cs index 5748a47..06d1bfd 100644 --- a/tests/TestTypeFoundation/ConcreteType.cs +++ b/tests/TestTypeFoundation/ConcreteType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ConcreteType : AbstractType { @@ -35,4 +35,4 @@ public ConcreteType(object obj1, object obj2, object obj3, object obj4) public override object Property4 { get; set; } public object Property5 { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ConcreteTypeWithPrivateParameterlessConstructor.cs b/tests/TestTypeFoundation/ConcreteTypeWithPrivateParameterlessConstructor.cs index c9ce80c..2f84bdd 100644 --- a/tests/TestTypeFoundation/ConcreteTypeWithPrivateParameterlessConstructor.cs +++ b/tests/TestTypeFoundation/ConcreteTypeWithPrivateParameterlessConstructor.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ConcreteTypeWithPrivateParameterlessConstructor { @@ -9,4 +9,4 @@ private ConcreteTypeWithPrivateParameterlessConstructor() public ConcreteTypeWithPrivateParameterlessConstructor(object obj) { } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/DoubleFieldHolder.cs b/tests/TestTypeFoundation/DoubleFieldHolder.cs index ed1cb9c..2767989 100644 --- a/tests/TestTypeFoundation/DoubleFieldHolder.cs +++ b/tests/TestTypeFoundation/DoubleFieldHolder.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class DoubleFieldHolder { public T1 Field1; public T2 Field2; -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/DoubleParameterType.cs b/tests/TestTypeFoundation/DoubleParameterType.cs index 89f5a2a..b64e594 100644 --- a/tests/TestTypeFoundation/DoubleParameterType.cs +++ b/tests/TestTypeFoundation/DoubleParameterType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class DoubleParameterType { @@ -10,4 +10,4 @@ public DoubleParameterType(T1 parameter1, T2 parameter2) public T1 Parameter1 { get; private set; } public T2 Parameter2 { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/DoublePropertyHolder.cs b/tests/TestTypeFoundation/DoublePropertyHolder.cs index 2087e7f..5e8002f 100644 --- a/tests/TestTypeFoundation/DoublePropertyHolder.cs +++ b/tests/TestTypeFoundation/DoublePropertyHolder.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class DoublePropertyHolder { public T1 Property1 { get; set; } public T2 Property2 { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/EmptyEnum.cs b/tests/TestTypeFoundation/EmptyEnum.cs index 224363e..faff840 100644 --- a/tests/TestTypeFoundation/EmptyEnum.cs +++ b/tests/TestTypeFoundation/EmptyEnum.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public enum EmptyEnum { // this must not contain any values -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/EnumType.cs b/tests/TestTypeFoundation/EnumType.cs index 8c64374..7046f9a 100644 --- a/tests/TestTypeFoundation/EnumType.cs +++ b/tests/TestTypeFoundation/EnumType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public enum EnumType { @@ -54,4 +54,4 @@ public enum ULongEnumType : ulong First = 1, Second, Third -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/EqualityResponder.cs b/tests/TestTypeFoundation/EqualityResponder.cs index 35aaab2..d53aa28 100644 --- a/tests/TestTypeFoundation/EqualityResponder.cs +++ b/tests/TestTypeFoundation/EqualityResponder.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class EqualityResponder { @@ -18,4 +18,4 @@ public override int GetHashCode() { return this.equals.GetHashCode(); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/FieldHolder.cs b/tests/TestTypeFoundation/FieldHolder.cs index c3135eb..a3f5c8d 100644 --- a/tests/TestTypeFoundation/FieldHolder.cs +++ b/tests/TestTypeFoundation/FieldHolder.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace TestTypeFoundation; @@ -11,4 +11,4 @@ public static FieldInfo GetField() return typeof(FieldHolder) .GetRuntimeField(nameof(Field)); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GenericType.cs b/tests/TestTypeFoundation/GenericType.cs index 0ccfd52..13e6d4a 100644 --- a/tests/TestTypeFoundation/GenericType.cs +++ b/tests/TestTypeFoundation/GenericType.cs @@ -9,4 +9,4 @@ public GenericType(T value) } private T Value { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedConstructorHost.cs b/tests/TestTypeFoundation/GuardedConstructorHost.cs index 418a627..a13fe3e 100644 --- a/tests/TestTypeFoundation/GuardedConstructorHost.cs +++ b/tests/TestTypeFoundation/GuardedConstructorHost.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class GuardedConstructorHost where T : class @@ -9,4 +9,4 @@ public GuardedConstructorHost(T item) } public T Item { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyField.cs b/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyField.cs index df72d37..3d720ee 100644 --- a/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyField.cs +++ b/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyField.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class GuardedConstructorHostHoldingStaticReadOnlyField where TItem : class @@ -16,4 +16,4 @@ public GuardedConstructorHostHoldingStaticReadOnlyField(TItem item) } public TItem Item { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyProperty.cs b/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyProperty.cs index bd8b30f..60431ac 100644 --- a/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyProperty.cs +++ b/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyProperty.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class GuardedConstructorHostHoldingStaticReadOnlyProperty where TItem : class @@ -16,4 +16,4 @@ public GuardedConstructorHostHoldingStaticReadOnlyProperty(TItem item) public static TStaticProperty Property { get; private set; } public TItem Item { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedMethodHost.cs b/tests/TestTypeFoundation/GuardedMethodHost.cs index b092444..73f4b40 100644 --- a/tests/TestTypeFoundation/GuardedMethodHost.cs +++ b/tests/TestTypeFoundation/GuardedMethodHost.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class GuardedMethodHost { @@ -77,4 +77,4 @@ public void ConsumeStringAndInt32AndGuid(string s, int i, Guid g) throw new ArgumentException("Guid cannot be empty.", nameof(g)); } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedPropertyHolder.cs b/tests/TestTypeFoundation/GuardedPropertyHolder.cs index 414d503..59abeee 100644 --- a/tests/TestTypeFoundation/GuardedPropertyHolder.cs +++ b/tests/TestTypeFoundation/GuardedPropertyHolder.cs @@ -10,4 +10,4 @@ public T Property get => this.property; set => this.property = value ?? throw new ArgumentNullException(nameof(value)); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedStaticMethodOnStaticTypeHost.cs b/tests/TestTypeFoundation/GuardedStaticMethodOnStaticTypeHost.cs index 1b9afba..7da6515 100644 --- a/tests/TestTypeFoundation/GuardedStaticMethodOnStaticTypeHost.cs +++ b/tests/TestTypeFoundation/GuardedStaticMethodOnStaticTypeHost.cs @@ -6,4 +6,4 @@ public static void Method(object argument) { if (argument is null) throw new ArgumentNullException(nameof(argument)); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/IInterface.cs b/tests/TestTypeFoundation/IInterface.cs index e3377b0..3e390b6 100644 --- a/tests/TestTypeFoundation/IInterface.cs +++ b/tests/TestTypeFoundation/IInterface.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public interface IInterface { object MakeIt(object obj); -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/IllBehavedPropertyHolder.cs b/tests/TestTypeFoundation/IllBehavedPropertyHolder.cs index 63a9bd2..a5867f7 100644 --- a/tests/TestTypeFoundation/IllBehavedPropertyHolder.cs +++ b/tests/TestTypeFoundation/IllBehavedPropertyHolder.cs @@ -28,4 +28,4 @@ public T PropertyIllBehavedSet this.propertyIllBehavedSet = default(T); } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/IndexedPropertyHolder.cs b/tests/TestTypeFoundation/IndexedPropertyHolder.cs index 45f6adf..6ae35d4 100644 --- a/tests/TestTypeFoundation/IndexedPropertyHolder.cs +++ b/tests/TestTypeFoundation/IndexedPropertyHolder.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class IndexedPropertyHolder { @@ -11,4 +11,4 @@ public T this[int index] get { return this.items[index]; } set { this.items[index] = value; } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/InternalGetterPropertyHolder.cs b/tests/TestTypeFoundation/InternalGetterPropertyHolder.cs index 04e5283..4638ea6 100644 --- a/tests/TestTypeFoundation/InternalGetterPropertyHolder.cs +++ b/tests/TestTypeFoundation/InternalGetterPropertyHolder.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class InternalGetterPropertyHolder { @@ -8,4 +8,4 @@ public InternalGetterPropertyHolder(T property) } public T Property { internal get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ItemContainer.cs b/tests/TestTypeFoundation/ItemContainer.cs index 77395dd..10851fa 100644 --- a/tests/TestTypeFoundation/ItemContainer.cs +++ b/tests/TestTypeFoundation/ItemContainer.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ItemContainer { @@ -18,4 +18,4 @@ public ItemContainer(params T[] items) } public IEnumerable Items { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ItemHolder.cs b/tests/TestTypeFoundation/ItemHolder.cs index 709e202..ea7a55e 100644 --- a/tests/TestTypeFoundation/ItemHolder.cs +++ b/tests/TestTypeFoundation/ItemHolder.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ItemHolder { @@ -59,4 +59,4 @@ private ItemHolder(T[] items) } public IEnumerable Items { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/MultiUnorderedConstructorType.cs b/tests/TestTypeFoundation/MultiUnorderedConstructorType.cs index 6c299aa..fc769d4 100644 --- a/tests/TestTypeFoundation/MultiUnorderedConstructorType.cs +++ b/tests/TestTypeFoundation/MultiUnorderedConstructorType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class MultiUnorderedConstructorType { @@ -34,4 +34,4 @@ public ParameterObject(string text, int number) public int Number { get; } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/MutableValueType.cs b/tests/TestTypeFoundation/MutableValueType.cs index 724247c..ea47bae 100644 --- a/tests/TestTypeFoundation/MutableValueType.cs +++ b/tests/TestTypeFoundation/MutableValueType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public struct MutableValueType { @@ -12,4 +12,4 @@ public MutableValueType(object property1, object property2, object property3) public object Property1 { get; set; } public object Property2 { get; set; } public object Property3 { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/MutableValueTypeWithoutConstructor.cs b/tests/TestTypeFoundation/MutableValueTypeWithoutConstructor.cs index 158d1a3..0ae7efd 100644 --- a/tests/TestTypeFoundation/MutableValueTypeWithoutConstructor.cs +++ b/tests/TestTypeFoundation/MutableValueTypeWithoutConstructor.cs @@ -1,7 +1,7 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public struct MutableValueTypeWithoutConstructor { public object Property1 { get; set; } public object Property2 { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/NonCompliantCollectionHolder.cs b/tests/TestTypeFoundation/NonCompliantCollectionHolder.cs index 00205a8..256d5f2 100644 --- a/tests/TestTypeFoundation/NonCompliantCollectionHolder.cs +++ b/tests/TestTypeFoundation/NonCompliantCollectionHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class NonCompliantCollectionHolder { public ICollection Collection { get; set; } = new List(); -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/NoopInterfaceImplementer.cs b/tests/TestTypeFoundation/NoopInterfaceImplementer.cs index b99cd27..97aad50 100644 --- a/tests/TestTypeFoundation/NoopInterfaceImplementer.cs +++ b/tests/TestTypeFoundation/NoopInterfaceImplementer.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class NoopInterfaceImplementer : IInterface { @@ -6,4 +6,4 @@ public object MakeIt(object obj) { return obj; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/Properties/AssemblyInfo.cs b/tests/TestTypeFoundation/Properties/AssemblyInfo.cs index 1d950fa..024d383 100644 --- a/tests/TestTypeFoundation/Properties/AssemblyInfo.cs +++ b/tests/TestTypeFoundation/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using System.Runtime.InteropServices; [assembly: AssemblyCulture("")] diff --git a/tests/TestTypeFoundation/PropertyHolder.cs b/tests/TestTypeFoundation/PropertyHolder.cs index b1e471c..5550f71 100644 --- a/tests/TestTypeFoundation/PropertyHolder.cs +++ b/tests/TestTypeFoundation/PropertyHolder.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace TestTypeFoundation; @@ -16,4 +16,4 @@ public static PropertyInfo GetProperty() return typeof(PropertyHolder) .GetRuntimeProperty(nameof(Property)); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/QuadrupleParameterType.cs b/tests/TestTypeFoundation/QuadrupleParameterType.cs index ccb9147..cb450b5 100644 --- a/tests/TestTypeFoundation/QuadrupleParameterType.cs +++ b/tests/TestTypeFoundation/QuadrupleParameterType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class QuadrupleParameterType { @@ -14,4 +14,4 @@ public QuadrupleParameterType(T1 parameter1, T2 parameter2, T3 parameter3, T4 pa public T2 Parameter2 { get; private set; } public T3 Parameter3 { get; private set; } public T4 Parameter4 { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ReadOnlyFieldHolder.cs b/tests/TestTypeFoundation/ReadOnlyFieldHolder.cs index 30250c9..6ce2d76 100644 --- a/tests/TestTypeFoundation/ReadOnlyFieldHolder.cs +++ b/tests/TestTypeFoundation/ReadOnlyFieldHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ReadOnlyFieldHolder { public readonly T Field; -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ReadOnlyPropertyHolder.cs b/tests/TestTypeFoundation/ReadOnlyPropertyHolder.cs index 392624a..3651266 100644 --- a/tests/TestTypeFoundation/ReadOnlyPropertyHolder.cs +++ b/tests/TestTypeFoundation/ReadOnlyPropertyHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ReadOnlyPropertyHolder { public T Property { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/RecordType.cs b/tests/TestTypeFoundation/RecordType.cs index 7ad88cd..5aa7691 100644 --- a/tests/TestTypeFoundation/RecordType.cs +++ b/tests/TestTypeFoundation/RecordType.cs @@ -33,4 +33,4 @@ public override int GetHashCode() { return EqualityComparer.Default.GetHashCode(this.Value); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/SingleParameterType.cs b/tests/TestTypeFoundation/SingleParameterType.cs index e157947..1928e57 100644 --- a/tests/TestTypeFoundation/SingleParameterType.cs +++ b/tests/TestTypeFoundation/SingleParameterType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class SingleParameterType { @@ -8,4 +8,4 @@ public SingleParameterType(T parameter) } public T Parameter { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/StaticFieldHolder.cs b/tests/TestTypeFoundation/StaticFieldHolder.cs index 738e055..af50e43 100644 --- a/tests/TestTypeFoundation/StaticFieldHolder.cs +++ b/tests/TestTypeFoundation/StaticFieldHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class StaticFieldHolder { public static T Field; -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/StaticPropertyHolder.cs b/tests/TestTypeFoundation/StaticPropertyHolder.cs index d95b0f7..e57d00f 100644 --- a/tests/TestTypeFoundation/StaticPropertyHolder.cs +++ b/tests/TestTypeFoundation/StaticPropertyHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class StaticPropertyHolder { public static T Property { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TestTypeFoundation.csproj b/tests/TestTypeFoundation/TestTypeFoundation.csproj index 3c758eb..87bb41a 100644 --- a/tests/TestTypeFoundation/TestTypeFoundation.csproj +++ b/tests/TestTypeFoundation/TestTypeFoundation.csproj @@ -1,19 +1,20 @@  - netstandard2.0 TestTypeFoundation TestTypeFoundation disable + false false - true + false + + false - - + diff --git a/tests/TestTypeFoundation/TriState.cs b/tests/TestTypeFoundation/TriState.cs index c88423c..5f3fadd 100644 --- a/tests/TestTypeFoundation/TriState.cs +++ b/tests/TestTypeFoundation/TriState.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public enum TriState { First = 0, Second, Third -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TripleParameterType.cs b/tests/TestTypeFoundation/TripleParameterType.cs index 952e515..56f874f 100644 --- a/tests/TestTypeFoundation/TripleParameterType.cs +++ b/tests/TestTypeFoundation/TripleParameterType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TripleParameterType { @@ -12,4 +12,4 @@ public TripleParameterType(T1 parameter1, T2 parameter2, T3 parameter3) public T1 Parameter1 { get; private set; } public T2 Parameter2 { get; private set; } public T3 Parameter3 { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TriplePropertyHolder.cs b/tests/TestTypeFoundation/TriplePropertyHolder.cs index f9ec32a..2e6c720 100644 --- a/tests/TestTypeFoundation/TriplePropertyHolder.cs +++ b/tests/TestTypeFoundation/TriplePropertyHolder.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TriplePropertyHolder { @@ -7,4 +7,4 @@ public class TriplePropertyHolder public T2 Property2 { get; set; } public T3 Property3 { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithCastOperatorsWithoutPublicConstructor.cs b/tests/TestTypeFoundation/TypeWithCastOperatorsWithoutPublicConstructor.cs index 300d37c..baeba21 100644 --- a/tests/TestTypeFoundation/TypeWithCastOperatorsWithoutPublicConstructor.cs +++ b/tests/TestTypeFoundation/TypeWithCastOperatorsWithoutPublicConstructor.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithCastOperatorsWithoutPublicConstructor { @@ -15,4 +15,4 @@ public static explicit operator TypeWithCastOperatorsWithoutPublicConstructor(st { return new TypeWithCastOperatorsWithoutPublicConstructor(); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithConcreteParameterMethod.cs b/tests/TestTypeFoundation/TypeWithConcreteParameterMethod.cs index 0007af5..b6facde 100644 --- a/tests/TestTypeFoundation/TypeWithConcreteParameterMethod.cs +++ b/tests/TestTypeFoundation/TypeWithConcreteParameterMethod.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithConcreteParameterMethod { public void DoSomething(ConcreteType param) { } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithEmptyEnumField.cs b/tests/TestTypeFoundation/TypeWithEmptyEnumField.cs index 4fcdd3c..1773fc5 100644 --- a/tests/TestTypeFoundation/TypeWithEmptyEnumField.cs +++ b/tests/TestTypeFoundation/TypeWithEmptyEnumField.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithEmptyEnumField { public EmptyEnum EmptyEnumField; public EmptyEnum EmptyEnumProperty { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithFactoryMethod.cs b/tests/TestTypeFoundation/TypeWithFactoryMethod.cs index 6921237..560d764 100644 --- a/tests/TestTypeFoundation/TypeWithFactoryMethod.cs +++ b/tests/TestTypeFoundation/TypeWithFactoryMethod.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithFactoryMethod { @@ -20,4 +20,4 @@ public static TypeWithFactoryMethod Create(IEnumerable arguments) { return new TypeWithFactoryMethod(); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithFactoryProperty.cs b/tests/TestTypeFoundation/TypeWithFactoryProperty.cs index 8355290..8b784f4 100644 --- a/tests/TestTypeFoundation/TypeWithFactoryProperty.cs +++ b/tests/TestTypeFoundation/TypeWithFactoryProperty.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithFactoryProperty { @@ -13,4 +13,4 @@ public static TypeWithFactoryProperty Factory return new TypeWithFactoryProperty(); } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithIndexer.cs b/tests/TestTypeFoundation/TypeWithIndexer.cs index e5b7c0f..3552e4f 100644 --- a/tests/TestTypeFoundation/TypeWithIndexer.cs +++ b/tests/TestTypeFoundation/TypeWithIndexer.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithIndexer { @@ -15,4 +15,4 @@ public string this[string index] this.dict[index] = value; } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithOverloadedMembers.cs b/tests/TestTypeFoundation/TypeWithOverloadedMembers.cs index 7751e05..b9f2d32 100644 --- a/tests/TestTypeFoundation/TypeWithOverloadedMembers.cs +++ b/tests/TestTypeFoundation/TypeWithOverloadedMembers.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace TestTypeFoundation; @@ -25,4 +25,4 @@ public void DoSomething(object x, object y, object z) public static MethodInfo GetDoSomethingMethod(params Type[] parameterTypes) => typeof(TypeWithOverloadedMembers) .GetMethod(nameof(DoSomething), parameterTypes); -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithPseudoFactoryMethod.cs b/tests/TestTypeFoundation/TypeWithPseudoFactoryMethod.cs index 695353f..62d2210 100644 --- a/tests/TestTypeFoundation/TypeWithPseudoFactoryMethod.cs +++ b/tests/TestTypeFoundation/TypeWithPseudoFactoryMethod.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; /// /// This type contains a method that returns an instance of the same type @@ -17,4 +17,4 @@ public static TypeWithPseudoFactoryMethod DoSomething( { return new TypeWithPseudoFactoryMethod(); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithRefMethod.cs b/tests/TestTypeFoundation/TypeWithRefMethod.cs index e709a7e..8dbc85d 100644 --- a/tests/TestTypeFoundation/TypeWithRefMethod.cs +++ b/tests/TestTypeFoundation/TypeWithRefMethod.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithRefMethod { @@ -7,4 +7,4 @@ public void InvokeIt(T x, ref T y) if (x is null) throw new ArgumentNullException(nameof(x)); if (y is null) throw new ArgumentNullException(nameof(y)); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/UnguardedConstructorHost.cs b/tests/TestTypeFoundation/UnguardedConstructorHost.cs index 5ae0dc6..40239a9 100644 --- a/tests/TestTypeFoundation/UnguardedConstructorHost.cs +++ b/tests/TestTypeFoundation/UnguardedConstructorHost.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace TestTypeFoundation; @@ -23,4 +23,4 @@ public static ParameterInfo GetParameter() { return GetConstructor().GetParameters().Single(); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/UnguardedMethodHost.cs b/tests/TestTypeFoundation/UnguardedMethodHost.cs index 6e06bb3..4b38407 100644 --- a/tests/TestTypeFoundation/UnguardedMethodHost.cs +++ b/tests/TestTypeFoundation/UnguardedMethodHost.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class UnguardedMethodHost { @@ -13,4 +13,4 @@ public void ConsumeGuardedGuidAndUnguardedString(Guid g, string s) throw new ArgumentException("Guid cannot be empty.", nameof(g)); } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/UnguardedStaticMethodOnStaticTypeHost.cs b/tests/TestTypeFoundation/UnguardedStaticMethodOnStaticTypeHost.cs index 338390c..0fd555a 100644 --- a/tests/TestTypeFoundation/UnguardedStaticMethodOnStaticTypeHost.cs +++ b/tests/TestTypeFoundation/UnguardedStaticMethodOnStaticTypeHost.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public static class UnguardedStaticMethodOnStaticTypeHost { public static void Method(object argument) { } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/UnguardedStaticPropertyOnStaticTypeHost.cs b/tests/TestTypeFoundation/UnguardedStaticPropertyOnStaticTypeHost.cs index 92c1dfe..fcc7126 100644 --- a/tests/TestTypeFoundation/UnguardedStaticPropertyOnStaticTypeHost.cs +++ b/tests/TestTypeFoundation/UnguardedStaticPropertyOnStaticTypeHost.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public static class UnguardedStaticPropertyOnStaticTypeHost { @@ -7,4 +7,4 @@ public static object Property get; set; } -} \ No newline at end of file +} From 9237e3e979f2385ccae4c1ea892b39f594d1a2d1 Mon Sep 17 00:00:00 2001 From: Andrei Ivascu <7030530+aivascu@users.noreply.github.com> Date: Mon, 7 Sep 2026 00:31:39 +0300 Subject: [PATCH 4/5] Document data source shapes and adopt AutoFixture brand assets. --- AutoFixtureLogo200x200.png | Bin 14319 -> 0 bytes CONTRIBUTING.md | 66 ++++++++++++++ Common.props | 3 +- README.md | 172 ++++++++++++++++++++++++++++++++--- assets/icon-square-color.svg | 7 ++ assets/icon.png | Bin 0 -> 61601 bytes assets/lockup-dark.svg | 18 ++++ assets/lockup-light.svg | 18 ++++ assets/readme.md | 105 +++++++++++++++++++++ 9 files changed, 376 insertions(+), 13 deletions(-) delete mode 100644 AutoFixtureLogo200x200.png create mode 100644 CONTRIBUTING.md create mode 100644 assets/icon-square-color.svg create mode 100644 assets/icon.png create mode 100644 assets/lockup-dark.svg create mode 100644 assets/lockup-light.svg create mode 100644 assets/readme.md diff --git a/AutoFixtureLogo200x200.png b/AutoFixtureLogo200x200.png deleted file mode 100644 index 32a82c5d19774c5ae7c44b9b37ccb569c4a049cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14319 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 Yq;SvdMtd^;_X{3CQc - + + diff --git a/README.md b/README.md index 648ea90..067685e 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,18 @@ [![License](https://img.shields.io/badge/license-MIT-green)](https://raw.githubusercontent.com/AutoFixture/AutoFixture.TUnit/master/LICENCE.txt) [![NuGet version](https://img.shields.io/nuget/v/AutoFixture.TUnit?logo=nuget)](https://www.nuget.org/packages/AutoFixture.TUnit) -[AutoFixture.TUnit](https://github.com/AutoFixture/AutoFixture.TUnit) is a .NET library that integrates [AutoFixture](https://github.com/AutoFixture/AutoFixture) with [TUnit](https://github.com/tunitframework/tunit), allowing you to effortlessly generate test data for your unit tests. +[AutoFixture.TUnit](https://github.com/AutoFixture/AutoFixture.TUnit) is a .NET library that integrates [AutoFixture](https://github.com/AutoFixture/AutoFixture) with [TUnit](https://github.com/thomhurst/TUnit), allowing you to effortlessly generate test data for your unit tests. By leveraging the data generators feature of TUnit, this extension turns AutoFixture into a declarative framework for writing unit tests. In many ways it becomes a unit testing DSL (Domain Specific Language). +

+ + + + AutoFixture + + +

+ ## Table of Contents - [Installation](#installation) @@ -16,8 +25,8 @@ By leveraging the data generators feature of TUnit, this extension turns AutoFix ## Installation -AutoFixture packages are distributed via NuGet. -To install the packages you can use the integrated package manager of your IDE, the .NET CLI, or reference the package directly in your project file. +AutoFixture.TUnit is distributed via NuGet. +To install the package you can use the integrated package manager of your IDE, the .NET CLI, or reference the package directly in your project file. ```cmd dotnet add package AutoFixture.TUnit @@ -41,6 +50,7 @@ public class Calculator You can write a test using AutoFixture to provide the input values: ```csharp +using TUnit; using TUnit.Assertions; using AutoFixture.TUnit; @@ -65,6 +75,7 @@ You can also combine auto-generated data with inline arguments using the `[AutoA This allows you to specify some parameters while still letting AutoFixture generate the rest. ```csharp +using TUnit; using TUnit.Assertions; using AutoFixture.TUnit; @@ -84,6 +95,141 @@ public class CalculatorTests } ``` +### Member and Class Data Sources + +Use `[AutoMemberDataSource]` when some values come from a static member (property, field, or method). +Use `[AutoClassDataSource]` when values come from a separate data provider type. +Any remaining test parameters are filled by AutoFixture. + +Supported member/class result shapes (same ideas as TUnit MethodDataSource): + +| Result shape | How it becomes test rows | +| --- | --- | +| `IEnumerable` / `IEnumerable` | Each array is one multi-column row | +| `IEnumerable` (for example `IEnumerable`) | Each item is one single-cell row | +| `IEnumerable<(T1, T2, ...)>` | Each tuple expands into columns | +| `(T1, T2, ...)` | One row with expanded columns | +| Scalar (`string`, `int`, custom type, …) | One single-cell row (`string` is not enumerated as chars) | +| `null` | One row with a single `null` cell | +| `Task` / nested `Task`s | Awaited, then the result is interpreted as above | +| `IAsyncEnumerable` | Same row rules as the sync sequences above | +| Empty sequence | No rows | + +```csharp +using System.Collections; +using System.Collections.Generic; +using TUnit; +using TUnit.Assertions; +using AutoFixture.TUnit; + +public class CalculatorTests +{ + // Multi-column rows + public static IEnumerable ObjectArrayRows => + [ + [2, 3], + [10, -4] + ]; + + // Single-cell rows from a typed sequence + public static IEnumerable StringRows => ["left", "right"]; + + // Tuples expand to columns + public static IEnumerable<(int Left, int Right)> TupleRows => + [ + (2, 3), + (10, -4) + ]; + + // One tuple => one row + public static (int Left, int Right) SingleTupleRow => (5, 8); + + // Scalar => one single-cell row + public static string StringScalar => "seed"; + + // Async method (for example loading rows from a file or database) + public static async Task> TaskObjectArrayRows() + { + await Task.Yield(); // stand-in for real I/O + return [[1, 1], [7, 8]]; + } + + // Streaming rows as they become available + public static async IAsyncEnumerable<(int Left, int Right)> AsyncTupleRows() + { + yield return (2, 3); + await Task.Yield(); + yield return (10, -4); + } + + [Test, AutoMemberDataSource(nameof(ObjectArrayRows))] + public async Task Add_ObjectArrayRows_ReturnsExpectedTotal( + int a, int b, Calculator calculator) + { + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); + } + + [Test, AutoMemberDataSource(nameof(TupleRows))] + public async Task Add_TupleRows_ReturnsExpectedTotal( + int a, int b, Calculator calculator) + { + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); + } + + [Test, AutoClassDataSource(typeof(KnownSumRows))] + public async Task Add_ClassData_ReturnsExpectedTotal( + int a, int b, Calculator calculator) + { + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); + } +} + +public class KnownSumRows : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return [1, 1]; + yield return [7, 8]; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} +``` + +Class data providers can return the same shapes (for example `IEnumerable`, `IEnumerable`, or `IEnumerable<(string, int)>`). + +Generic attribute forms (C# 11+) avoid `typeof(...)` for the provider or member host type, and strongly type a single inline argument: + +```csharp +[Test, AutoMemberDataSource(nameof(ObjectArrayRows))] +public async Task Add_GenericMember_ReturnsExpectedTotal(int a, int b, Calculator calculator) +{ + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); +} + +[Test, AutoClassDataSource] +public async Task Add_GenericClassData_ReturnsExpectedTotal(int a, int b, Calculator calculator) +{ + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); +} + +[Test, AutoArguments(2)] +public async Task Add_GenericArguments_FillsRemaining(int a, int b, Calculator calculator) +{ + await Assert.That(a).IsEqualTo(2); + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); +} + +// Prefer AutoArguments when the value is an array: non-generic +// [AutoArguments(new object[] { 1, 2 })] expands into separate cells because of params object?[]. +[Test, AutoArguments(new int[] { 1, 2 })] +public async Task Add_GenericArrayArgument_KeepsArrayAsOneParameter(int[] values, Calculator calculator) +{ + await Assert.That(values).IsEquivalentTo(new[] { 1, 2 }); + await Assert.That(calculator).IsNotNull(); +} +``` + ### Freezing Dependencies AutoFixture's `[Frozen]` attribute can be used to ensure that the same instance of a dependency is injected into multiple parameters. @@ -107,6 +253,7 @@ public class Consumer You can freeze the Dependency so that all requests for it within the test will return the same instance: ```csharp +using TUnit; using TUnit.Assertions; using AutoFixture.TUnit; @@ -127,14 +274,14 @@ public class ConsumerTests ### Data Source Attributes - **`[AutoDataSource]`** - Automatically generates test data for all parameters -- **`[AutoArguments]`** - Combines inline values with auto-generated data -- **`[AutoMemberDataSource]`** - Uses static members (properties, fields, methods) as data sources -- **`[AutoClassDataSource]`** - Uses classes implementing `IEnumerable` as data sources +- **`[AutoArguments]`** / **`[AutoArguments]`** - Combines inline values with auto-generated data (`T` is a single strongly typed inline value; C# 11+) +- **`[AutoMemberDataSource]`** / **`[AutoMemberDataSource]`** - Uses static members (properties, fields, methods) as data sources; the generic form takes the member-declaring type as `T` (C# 11+) +- **`[AutoClassDataSource]`** / **`[AutoClassDataSource]`** - Uses a provider type as a data source; the generic form takes the provider type as `T` (C# 11+). This is not the same as TUnit's `[ClassDataSource]`, which injects an instance of `T` - **`[CompositeDataSource]`** - Composes multiple data source attributes together ### Parameter Customization Attributes -- **`[Frozen]`** - Freezes a parameter value so the same instance is reused (supports various matching criteria) +- **`[Frozen]`** - Freezes a parameter value so the same instance is reused (supports various matching criteria via `Matching`) - **`[Greedy]`** - Uses the constructor with the most parameters - **`[Modest]`** - Uses the constructor with the fewest parameters - **`[NoAutoProperties]`** - Prevents auto-population of properties @@ -142,14 +289,15 @@ public class ConsumerTests - **`[FavorEnumerables]`** - Prefers constructors that take `IEnumerable` parameters - **`[FavorLists]`** - Prefers constructors that take `IList` parameters -All customization attributes can be combined and support custom fixture factories for advanced scenarios. +Customization attributes can be combined on parameters. +Data source attributes also support custom fixture factories through derived attributes for advanced scenarios. ## Contributing -Contributions are welcome! -If you would like to contribute, please review our contributing guidelines and open an issue or pull request. +Contributions are welcome! +If you would like to contribute, please review our [contributing guidelines](CONTRIBUTING.md) and open an issue or pull request. ## License -AutoFixture is Open Source software and is released under the [MIT license](LICENCE.txt). -The license allows the use of AutoFixture libraries in free and commercial applications and libraries without restrictions. +AutoFixture.TUnit is Open Source software and is released under the [MIT license](LICENCE.txt). +The license allows the use of AutoFixture.TUnit libraries in free and commercial applications and libraries without restrictions. diff --git a/assets/icon-square-color.svg b/assets/icon-square-color.svg new file mode 100644 index 0000000..583e7c4 --- /dev/null +++ b/assets/icon-square-color.svg @@ -0,0 +1,7 @@ + + AutoFixture + + + + + diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e2d290b20ab758d57bf1f0bfbe5cf7bdc0fd982c GIT binary patch literal 61601 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
bVAkSacYNwVt%{s_T@Xtjo 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 Fe*j_A0Js1E literal 0 HcmV?d00001 diff --git a/assets/lockup-dark.svg b/assets/lockup-dark.svg new file mode 100644 index 0000000..6ab3875 --- /dev/null +++ b/assets/lockup-dark.svg @@ -0,0 +1,18 @@ + + AutoFixture + + + + + + AutoFixture + + diff --git a/assets/lockup-light.svg b/assets/lockup-light.svg new file mode 100644 index 0000000..5dc350b --- /dev/null +++ b/assets/lockup-light.svg @@ -0,0 +1,18 @@ + + AutoFixture + + + + + + AutoFixture + + diff --git a/assets/readme.md b/assets/readme.md new file mode 100644 index 0000000..01eb910 --- /dev/null +++ b/assets/readme.md @@ -0,0 +1,105 @@ +# AutoFixture.TUnit + +AutoFixture.TUnit integrates [AutoFixture](https://github.com/AutoFixture/AutoFixture) with [TUnit](https://github.com/thomhurst/TUnit). Use data-source attributes to generate arguments declaratively so tests stay focused on behavior, not setup. + +Full documentation, data-shape reference, and contributing guide: [github.com/AutoFixture/AutoFixture.TUnit](https://github.com/AutoFixture/AutoFixture.TUnit). + +## Install + +```bash +dotnet add package AutoFixture.TUnit +``` + +## Quick start + +`[AutoDataSource]` fills every parameter with AutoFixture-generated values: + +```csharp +using TUnit; +using TUnit.Assertions; +using AutoFixture.TUnit; + +public class Calculator +{ + public int Add(int a, int b) => a + b; +} + +public class CalculatorTests +{ + [Test, AutoDataSource] + public async Task Add_SimpleValues_ReturnsCorrectResult( + Calculator calculator, int a, int b) + { + int result = calculator.Add(a, b); + + await Assert.That(result).IsEqualTo(a + b); + } +} +``` + +## Inline values + +`[AutoArguments]` supplies some arguments; AutoFixture fills the rest: + +```csharp +[Test] +[AutoArguments(5, 8)] +public async Task Add_SpecificValues_ReturnsCorrectResult( + int a, int b, Calculator calculator) +{ + await Assert.That(calculator.Add(a, b)).IsEqualTo(13); +} +``` + +Prefer `[AutoArguments]` (C# 11+) when you need a strongly typed single value, especially arrays that must stay one parameter: + +```csharp +[Test, AutoArguments(new int[] { 1, 2 })] +public async Task Add_GenericArrayArgument_KeepsArrayAsOneParameter( + int[] values, Calculator calculator) +{ + await Assert.That(values).IsEquivalentTo([1, 2]); + await Assert.That(calculator).IsNotNull(); +} +``` + +## Freeze shared instances + +Use `[Frozen]` when several parameters should receive the same instance: + +```csharp +public class Dependency { } + +public class Consumer +{ + public Dependency Dependency { get; } + public Consumer(Dependency dependency) => Dependency = dependency; +} + +public class ConsumerTests +{ + [Test, AutoDataSource] + public async Task Consumer_UsesSameDependency( + [Frozen] Dependency dependency, Consumer consumer) + { + await Assert.That(consumer.Dependency).IsSameReferenceAs(dependency); + } +} +``` + +## Main attributes + +| Attribute | Role | +| --- | --- | +| `[AutoDataSource]` | Generate all parameters | +| `[AutoArguments]` / `[AutoArguments]` | Mix inline values with generated data | +| `[AutoMemberDataSource]` / `[AutoMemberDataSource]` | Rows from a static member; remaining parameters are generated | +| `[AutoClassDataSource]` / `[AutoClassDataSource]` | Rows from a provider type; remaining parameters are generated | +| `[CompositeDataSource]` | Compose multiple data-source attributes | +| `[Frozen]`, `[Greedy]`, `[Modest]`, `[NoAutoProperties]`, `[FavorArrays]`, `[FavorEnumerables]`, `[FavorLists]` | Parameter / construction customizations | + +Member and class sources accept the same result shapes as TUnit method data sources (`object[]` rows, tuples, scalars, `Task`, `IAsyncEnumerable`, and more). See the [repository README](https://github.com/AutoFixture/AutoFixture.TUnit#member-and-class-data-sources) for the full shape table and examples. + +## License + +AutoFixture.TUnit is released under the [MIT license](https://github.com/AutoFixture/AutoFixture.TUnit/blob/master/LICENCE.txt). From 7cfdde34b6fc1172688093d21e8e0af3135dc3d1 Mon Sep 17 00:00:00 2001 From: Andrei Ivascu <7030530+aivascu@users.noreply.github.com> Date: Mon, 7 Sep 2026 13:14:35 +0300 Subject: [PATCH 5/5] Migrate array literals to collection expressions. Use [] where the target type is clear, and keep typed Assert.That/IsEquivalentTo only when inference is ambiguous. --- .../AutoClassDataSourceAttribute.cs | 6 +- .../AutoClassDataSourceAttribute{T}.cs | 2 +- .../BaseDataSourceAttribute.cs | 2 +- .../Internal/AutoDataSource.cs | 3 +- .../ArrayEdgeCaseScenarioTests.cs | 16 +++--- .../GetDataTests.cs | 4 +- .../ClassLevelScenarioTests.cs | 8 +-- .../GenericClassLevelScenarioTests.cs | 4 +- .../GenericUsageScenarioTests.cs | 6 +- .../GetDataTests.cs | 11 ++-- .../ResultShapeScenarioTests.cs | 18 +++--- .../UsageScenarioTests.cs | 6 +- .../GetDataTests.cs | 2 +- .../ClassLevelScenarioTests.cs | 6 +- .../ConstructionTests.cs | 4 +- .../GenericClassLevelScenarioTests.cs | 4 +- .../GenericUsageScenarioTests.cs | 7 +-- .../GetDataTests.cs | 55 +++++++++---------- .../ResultShapeScenarioTests.cs | 29 +++++----- .../UsageScenarioTests.cs | 5 +- .../AutoDataSourceTests/CombineTests.cs | 15 ++--- .../GetDataRowsAsyncTests.cs | 17 +++--- .../ClassDataSourceTests/ConstructionTests.cs | 6 +- .../FieldDataSourceTests/ConstructionTests.cs | 13 ++--- .../ConstructionTests.cs | 14 ++--- .../ConstructionTests.cs | 6 +- .../ConstructionTests.cs | 11 ++-- .../ResultShapeLeftoverTests.cs | 6 +- .../ConstructionTests.cs | 22 ++++---- .../DataSourceFixtures/MemberDataShapes.cs | 2 +- .../TestTypes/DelegatingDataSource.cs | 2 +- 31 files changed, 145 insertions(+), 167 deletions(-) diff --git a/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs index 00d8fbc..ad7c3ed 100644 --- a/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs +++ b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs @@ -52,9 +52,9 @@ public AutoClassDataSourceAttribute(Type sourceType, params object?[] parameters /// { /// public IEnumerator<object?[]> GetEnumerator() /// { - /// yield return new object?[] { 0, new int[0] }; - /// yield return new object?[] { 4, new int[] { 1, 2, 1} }; - /// yield return new object?[] { 23, new int [] { 0, 13, 15, -5 } }; + /// yield return [0, []]; + /// yield return [4, [1, 2, 1]]; + /// yield return [23, [0, 13, 15, -5]]; /// } /// /// IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); diff --git a/src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs index b553b37..7e968b4 100644 --- a/src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs +++ b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs @@ -8,7 +8,7 @@ namespace AutoFixture.TUnit; ///
/// /// The data provider type that yields test rows (for example an -/// of object arrays). +/// of object arrays). /// This is not the same as TUnit's ClassDataSource<T>, which injects an instance of /// as a dependency. /// diff --git a/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs b/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs index af7ba41..c05205c 100644 --- a/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs +++ b/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs @@ -35,7 +35,7 @@ public abstract class BaseDataSourceAttribute : Attribute, IDataSourceAttribute, if (parameters.Length == 0) { // If the method has no parameters, a single test run is enough. - yield return () => Task.FromResult(Array.Empty()); + yield return () => Task.FromResult([]); yield break; } diff --git a/src/AutoFixture.TUnit/Internal/AutoDataSource.cs b/src/AutoFixture.TUnit/Internal/AutoDataSource.cs index 411cead..4ba50c3 100644 --- a/src/AutoFixture.TUnit/Internal/AutoDataSource.cs +++ b/src/AutoFixture.TUnit/Internal/AutoDataSource.cs @@ -45,7 +45,8 @@ public AutoDataSource(Func createFixture, IDataSource? source = null) { var parameters = Array.ConvertAll(metadata.GetMethod().GetParameters(), TestParameter.From); var fixture = this.CreateFixture(); - return new[] { Array.ConvertAll(parameters, parameter => (object?)GenerateAutoValue(parameter, fixture)) }.ToAsyncDataSource(); + object[][] rows = [Array.ConvertAll(parameters, parameter => GenerateAutoValue(parameter, fixture))]; + return rows.ToAsyncDataSource(); } private async IAsyncEnumerable>> CombineValues(DataGeneratorMetadata metadata, IDataSource source) diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs index 3fd5aae..83f7174 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs @@ -4,13 +4,13 @@ namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests; /// /// Documents the params object?[] pitfall: a non-generic -/// [AutoArguments(new object[] { ... })] expands into separate cells, +/// [AutoArguments([ ... ])] expands into separate cells, /// while [AutoArguments<T[]>(...)] keeps the array as one argument. /// public class ArrayEdgeCaseScenarioTests { [Test] - [AutoArguments(new object[] { 1, 2 })] + [AutoArguments([1, 2])] public async Task WhenNonGenericObjectArray_ExpandsIntoSeparateArguments(int a, int b) { await Assert.That(a).IsEqualTo(1); @@ -18,26 +18,26 @@ public async Task WhenNonGenericObjectArray_ExpandsIntoSeparateArguments(int a, } [Test] - [AutoArguments(new object[] { 1, 2 })] + [AutoArguments([1, 2])] public async Task WhenGenericObjectArray_KeepsArrayAsSingleArgument(object[] values, MyClass leftover) { - await Assert.That(values).IsEquivalentTo(new object[] { 1, 2 }); + await Assert.That(values).IsEquivalentTo([1, 2]); await Assert.That(leftover).IsNotNull(); } [Test] - [AutoArguments(new int[] { 1, 2 })] + [AutoArguments([1, 2])] public async Task WhenGenericIntArray_KeepsArrayAsSingleArgument(int[] values, MyClass leftover) { - await Assert.That(values).IsEquivalentTo(new[] { 1, 2 }); + await Assert.That(values).IsEquivalentTo([1, 2]); await Assert.That(leftover).IsNotNull(); } [Test] - [AutoArguments(new string[] { "a", "b" })] + [AutoArguments(["a", "b"])] public async Task WhenGenericStringArray_KeepsArrayAsSingleArgument(string[] values, MyClass leftover) { - await Assert.That(values).IsEquivalentTo(new[] { "a", "b" }); + await Assert.That(values).IsEquivalentTo(["a", "b"]); await Assert.That(leftover).IsNotNull(); } } diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GetDataTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GetDataTests.cs index 030e829..ed6a09a 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GetDataTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GetDataTests.cs @@ -35,7 +35,7 @@ public async Task Constructor_WhenDefault_ValuesAreEmpty() public async Task Constructor_WhenArgumentsProvided_ValuesAreNotEmpty() { // Arrange - var expectedValues = new[] { new object(), new object(), new object() }; + object[] expectedValues = [new object(), new object(), new object()]; var sut = new AutoArgumentsAttribute(expectedValues); // Act @@ -49,7 +49,7 @@ public async Task Constructor_WhenArgumentsProvided_ValuesAreNotEmpty() public async Task Constructor_WhenExplicitValuesProvided_ValuesMatch() { // Arrange - var expectedValues = new[] { new object(), new object(), new object() }; + object[] expectedValues = [new object(), new object(), new object()]; var sut = new DerivedAutoArgumentsAttribute(() => new DelegatingFixture(), expectedValues); // Act diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs index 815e83b..bc217e5 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs @@ -15,7 +15,7 @@ public class ClassLevelPrimitiveScenarioTests(string name, int count) [Test] public async Task WhenAppliedToClass_UsesClassValueAndFillsRemaining() { - await Assert.That(new[] { "alpha", "beta" }).Contains(name); + await Assert.That(["alpha", "beta"]).Contains(name); await Assert.That(count).IsNotEqualTo(0); } } @@ -30,7 +30,7 @@ public class ClassLevelComplexTypeScenarioTests( [Test] public async Task WhenAppliedToClass_UsesClassValueAndFillsComplexRemaining() { - await Assert.That(new[] { "alpha", "beta" }).Contains(name); + await Assert.That(["alpha", "beta"]).Contains(name); await Assert.That(ph).IsNotNull(); await Assert.That(ph.Property).IsNotNull(); @@ -82,7 +82,7 @@ public ClassLevelMultiConstructorParameterizedFirstScenarioTests() [Test] public async Task WhenParameterizedConstructorDeclaredFirst_UsesClassConstructorArgument() { - await Assert.That(new[] { "alpha", "beta" }).Contains(this.name); + await Assert.That(["alpha", "beta"]).Contains(this.name); } } @@ -108,6 +108,6 @@ public ClassLevelMultiConstructorIntFirstScenarioTests(string name) public async Task WhenIntConstructorDeclaredFirst_UsesClassIntArgument() { await Assert.That(this.name).IsEqualTo("int-ctor"); - await Assert.That(new[] { 11, 22 }).Contains(this.count); + await Assert.That([11, 22]).Contains(this.count); } } diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs index 44d602f..d499cbb 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs @@ -14,7 +14,7 @@ public class GenericClassLevelPrimitiveScenarioTests(string name, int count) [Test] public async Task WhenGenericAppliedToClass_UsesClassValueAndFillsRemaining() { - await Assert.That(new[] { "alpha", "beta" }).Contains(name); + await Assert.That(["alpha", "beta"]).Contains(name); await Assert.That(count).IsNotEqualTo(0); } } @@ -29,7 +29,7 @@ public class GenericClassLevelComplexTypeScenarioTests( [Test] public async Task WhenGenericAppliedToClass_UsesClassValueAndFillsComplexRemaining() { - await Assert.That(new[] { "alpha", "beta" }).Contains(name); + await Assert.That(["alpha", "beta"]).Contains(name); await Assert.That(ph).IsNotNull(); await Assert.That(ph.Property).IsNotNull(); diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs index 5838de6..16925a0 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs @@ -12,7 +12,7 @@ public class GenericUsageScenarioTests [Test, AutoClassDataSource] public async Task WhenGenericClassSuppliesValues_UsesSuppliedValues(string s1, string s2, string s3) { - await Assert.That(new[] { "foo", "dim" }).Contains(s1); + await Assert.That(["foo", "dim"]).Contains(s1); await Assert.That(s2).IsNotEmpty(); await Assert.That(s3).IsNotEmpty(); } @@ -31,8 +31,8 @@ public async Task WhenGenericClassValuesPartial_SuppliesRemainingSpecimens( public async Task WhenGenericClassDataParameterized_ReceivesExpectedData( int p1, string p2, double p3, RecordType p4) { - var actual = new object[] { p1, p2, p3 }; - var expected = new object[] { 28, "bar", 93.102 }; + object[] actual = [p1, p2, p3]; + object[] expected = [28, "bar", 93.102]; await Assert.That(actual).IsEquivalentTo(expected); await Assert.That(p4).IsNotNull(); diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs index b61fa99..b75fb2e 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs @@ -287,12 +287,11 @@ public async Task WhenNullParameters_Passes() var sut = new AutoClassDataSourceAttribute(typeof(TestDataWithNullValues)); var testMethod = typeof(ExampleTestClass>) .GetMethod(nameof(ExampleTestClass>.TestMethod)); - var expected = new[] - { - new object[] { null, null, null, null }, - new object[] { string.Empty, null, null, null }, - new object[] { null, " ", null, null }, - }; + object[][] expected = [ + [ null, null, null, null ], + [string.Empty, null, null, null], + [null, " ", null, null], + ]; // Act var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs index 5848b9b..7a38c60 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs @@ -13,7 +13,7 @@ public class ResultShapeScenarioTests [AutoClassDataSource(typeof(StringSequenceClassData))] public async Task WhenClassYieldsStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover) { - await Assert.That(new[] { "alpha", "beta" }).Contains(value); + await Assert.That(["alpha", "beta"]).Contains(value); await Assert.That(leftover).IsNotNull(); } @@ -22,7 +22,7 @@ public async Task WhenClassYieldsStrings_ReceivesValueAndFillsRemaining(string v public async Task WhenClassYieldsTuples_ExpandsColumnsAndFillsRemaining( string left, int right, MyClass leftover) { - await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right)); await Assert.That(leftover).IsNotNull(); } @@ -31,11 +31,10 @@ public async Task WhenClassYieldsTuples_ExpandsColumnsAndFillsRemaining( public async Task WhenClassYieldsObjectArrays_UsesSuppliedValues( string a, int b, RecordType c) { - await Assert.That(new[] - { + await Assert.That<(string, int, string)[]>([ ("hello", 1, "world"), ("foo", 2, "bar") - }).Contains((a, b, c.Value)); + ]).Contains((a, b, c.Value)); } [Test] @@ -43,18 +42,17 @@ await Assert.That(new[] public async Task WhenClassYieldsAsyncObjectArrays_UsesSuppliedValues( string a, int b, RecordType c) { - await Assert.That(new[] - { + await Assert.That<(string, int, string)[]>([ ("hello", 1, "world"), ("foo", 2, "bar") - }).Contains((a, b, c.Value)); + ]).Contains((a, b, c.Value)); } [Test] [AutoClassDataSource(typeof(AsyncStringSequenceClassData))] public async Task WhenClassYieldsAsyncStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover) { - await Assert.That(new[] { "alpha", "beta" }).Contains(value); + await Assert.That(["alpha", "beta"]).Contains(value); await Assert.That(leftover).IsNotNull(); } @@ -63,7 +61,7 @@ public async Task WhenClassYieldsAsyncStrings_ReceivesValueAndFillsRemaining(str public async Task WhenClassYieldsAsyncTuples_ExpandsColumnsAndFillsRemaining( string left, int right, MyClass leftover) { - await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right)); await Assert.That(leftover).IsNotNull(); } diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs index 9201d36..eb44231 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs @@ -12,7 +12,7 @@ public class UsageScenarioTests [Test, AutoClassDataSource(typeof(StringDataClass))] public async Task WhenClassSuppliesValues_UsesSuppliedValues(string s1, string s2, string s3) { - await Assert.That(new[] { "foo", "dim" }).Contains(s1); + await Assert.That(["foo", "dim"]).Contains(s1); await Assert.That(s2).IsNotEmpty(); await Assert.That(s3).IsNotEmpty(); } @@ -39,8 +39,8 @@ public async Task WhenMixedTypes_SuppliesExpectedData(int p1, string p2, Propert [Test, AutoClassDataSource(typeof(ParameterizedDataClass), 28, "bar", 93.102)] public async Task WhenClassDataParameterized_ReceivesExpectedData(int p1, string p2, double p3, RecordType p4) { - var actual = new object[] { p1, p2, p3 }; - var expected = new object[] { 28, "bar", 93.102 }; + object[] actual = [p1, p2, p3]; + object[] expected = [28, "bar", 93.102]; await Assert.That(actual).IsEquivalentTo(expected); await Assert.That(p4).IsNotNull(); diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/GetDataTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/GetDataTests.cs index dd89c68..f4fa060 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/GetDataTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/GetDataTests.cs @@ -112,7 +112,7 @@ public async Task GetData_WhenCalled_ReturnsCorrectResult() await Assert.That(actualContext).IsNotNull(); await Assert.That(parameters).HasSingleItem(); await Assert.That(actualParameter).IsSameReferenceAs(parameters[0]); - await Assert.That(result.Single()).IsEquivalentTo(new[] { expectedResult }); + await Assert.That(result.Single()).IsEquivalentTo([expectedResult]); } [Test] diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs index 24e10a0..eaea433 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs @@ -16,7 +16,7 @@ public class ClassLevelPrimitiveScenarioTests(string name, int count) [Test] public async Task WhenAppliedToClass_UsesMemberValueAndFillsRemaining() { - await Assert.That(new[] { "one", "two" }).Contains(name); + await Assert.That(["one", "two"]).Contains(name); await Assert.That(count).IsNotEqualTo(0); } } @@ -33,7 +33,7 @@ public class ClassLevelComplexTypeScenarioTests( [Test] public async Task WhenAppliedToClass_UsesMemberValueAndFillsComplexRemaining() { - await Assert.That(new[] { "alpha", "beta" }).Contains(name); + await Assert.That(["alpha", "beta"]).Contains(name); await Assert.That(ph).IsNotNull(); await Assert.That(ph.Property).IsNotNull(); @@ -125,6 +125,6 @@ public ClassLevelMultiConstructorIntFirstScenarioTests(string name) public async Task WhenIntConstructorDeclaredFirst_UsesMemberIntArgument() { await Assert.That(this.name).IsEqualTo("int-ctor"); - await Assert.That(new[] { 11, 22 }).Contains(this.count); + await Assert.That([11, 22]).Contains(this.count); } } diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs index 3356bac..57cd663 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs @@ -14,7 +14,7 @@ public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute() public async Task Constructor_WhenMemberNameAndParameters_SetsMembers() { var memberName = Guid.NewGuid().ToString(); - var parameters = new object[] { "value-one", 3, 12.2f }; + object[] parameters = ["value-one", 3, 12.2f]; var sut = new AutoMemberDataSourceAttribute(memberName, parameters); @@ -28,7 +28,7 @@ public async Task Constructor_WhenMemberNameAndParameters_SetsMembers() public async Task Constructor_WhenTypeMemberNameAndParameters_SetsMembers() { var memberName = Guid.NewGuid().ToString(); - var parameters = new object[] { "value-one", 3, 12.2f }; + object[] parameters = ["value-one", 3, 12.2f]; var testType = typeof(ConstructionTests); var sut = new AutoMemberDataSourceAttribute(testType, memberName, parameters); diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs index 8c420c3..f89532e 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs @@ -13,7 +13,7 @@ public class GenericClassLevelPrimitiveScenarioTests(string name, int count) [Test] public async Task WhenGenericAppliedToClass_UsesMemberValueAndFillsRemaining() { - await Assert.That(new[] { "one", "two" }).Contains(name); + await Assert.That(["one", "two"]).Contains(name); await Assert.That(count).IsNotEqualTo(0); } } @@ -28,7 +28,7 @@ public class GenericClassLevelComplexTypeScenarioTests( [Test] public async Task WhenGenericAppliedToClass_UsesMemberValueAndFillsComplexRemaining() { - await Assert.That(new[] { "one", "two" }).Contains(name); + await Assert.That(["one", "two"]).Contains(name); await Assert.That(ph).IsNotNull(); await Assert.That(ph.Property).IsNotNull(); diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs index 4ebc8a6..0706c2b 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs @@ -11,7 +11,7 @@ public class GenericUsageScenarioTests [Test, AutoMemberDataSource(nameof(MemberHost.Strings))] public async Task WhenGenericMemberYieldsStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover) { - await Assert.That(new[] { "one", "two" }).Contains(value); + await Assert.That(["one", "two"]).Contains(value); await Assert.That(leftover).IsNotNull(); } @@ -19,11 +19,10 @@ public async Task WhenGenericMemberYieldsStrings_ReceivesValueAndFillsRemaining( public async Task WhenGenericMemberReturnsObjectArrays_UsesSuppliedValues( string a, int b, RecordType c) { - await Assert.That(new[] - { + await Assert.That<(string, int, string)[]>([ ("hello", 1, "world"), ("foo", 2, "bar") - }).Contains((a, b, c.Value)); + ]).Contains((a, b, c.Value)); } [Test, AutoMemberDataSource(nameof(MemberHost.StringData))] diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs index 03796fa..c9b5fca 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs @@ -140,12 +140,11 @@ public async Task GetData_WhenParameterlessMethod_GeneratesTests() var testMethod = TestTypeWithMethodData.GetSingleStringValueTestMethodInfo(); var dataGeneratorMetadata = DataGeneratorMetadataHelper .CreateDataGeneratorMetadata(testMethod); - var expected = new[] - { - new object[] { "value-one" }, - new object[] { "value-two" }, - new object[] { "value-three" } - }; + object[][] expected = [ + [ "value-one" ], + ["value-two"], + ["value-three"] + ]; // Act var testData = sut.GenerateDataSources(dataGeneratorMetadata) @@ -165,12 +164,11 @@ public async Task GetData_WhenMethodWithParameter_GeneratesTests() var testMethod = TestTypeWithMethodData.GetStringTestsFromArgumentMethodInfo(); var dataGeneratorMetadata = DataGeneratorMetadataHelper .CreateDataGeneratorMetadata(testMethod); - var expected = new[] - { - new object[] { "value-one" }, - new object[] { "value-two" }, - new object[] { "value-three" } - }; + object[][] expected = [ + [ "value-one" ], + ["value-two"], + ["value-three"] + ]; // Act var testData = sut.GenerateDataSources(dataGeneratorMetadata) @@ -188,12 +186,11 @@ public async Task GetData_WhenMultipleParameters_GeneratesTestData() var testMethod = TestTypeWithMethodData.GetMultipleValueTestMethodInfo(); var dataGeneratorMetadata = DataGeneratorMetadataHelper .CreateDataGeneratorMetadata(testMethod); - var expected = new[] - { - new object[] { "value-one", 12, 23.3m }, - new object[] { "value-two", 38, 12.7m }, - new object[] { "value-three", 94, 52.21m } - }; + object[][] expected = [ + [ "value-one", 12, 23.3m ], + ["value-two", 38, 12.7m], + ["value-three", 94, 52.21m] + ]; // Act var testData = sut.GenerateDataSources(dataGeneratorMetadata) @@ -247,12 +244,11 @@ public async Task GetData_WhenInjectedParameters_GeneratesTestData() var testMethod = TestTypeWithMethodData.GetTestWithFrozenParameter(); var dataGeneratorMetadata = DataGeneratorMetadataHelper .CreateDataGeneratorMetadata(testMethod); - var expected = new[] - { - new object[] { "value-one", "value-two", "value-two" }, - new object[] { "value-two", "value-three", "value-three" }, - new object[] { "value-three", "value-one", "value-one" } - }; + object[][] expected = [ + [ "value-one", "value-two", "value-two" ], + ["value-two", "value-three", "value-three"], + ["value-three", "value-one", "value-one"] + ]; // Act var testData = sut.GenerateDataSources(dataGeneratorMetadata) @@ -303,12 +299,11 @@ public async Task GetData_WhenMemberInherited_SupportsMember() const string memberName = nameof(TestTypeWithMethodData.GetMultipleValueTestData); var sut = new AutoMemberDataSourceAttribute(memberName); var testMethod = ChildTestTypeMethodData.GetMultipleValueTestMethodInfo(); - var expected = new[] - { - new object[] { "value-one", 12, 23.3m }, - new object[] { "value-two", 38, 12.7m }, - new object[] { "value-three", 94, 52.21m } - }; + object[][] expected = [ + [ "value-one", 12, 23.3m ], + ["value-two", 38, 12.7m], + ["value-three", 94, 52.21m] + ]; var dataGeneratorMetadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod); // Act diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs index a78400a..6e415f6 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs @@ -14,18 +14,17 @@ public class ResultShapeScenarioTests public async Task WhenMemberReturnsObjectArrays_UsesSuppliedValues( string a, int b, RecordType c) { - await Assert.That(new[] - { + await Assert.That<(string, int, string)[]>([ ("hello", 1, "world"), ("foo", 2, "bar") - }).Contains((a, b, c.Value)); + ]).Contains((a, b, c.Value)); } [Test] [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.Strings))] public async Task WhenMemberYieldsStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover) { - await Assert.That(new[] { "one", "two" }).Contains(value); + await Assert.That(["one", "two"]).Contains(value); await Assert.That(leftover).IsNotNull(); } @@ -50,7 +49,7 @@ public async Task WhenMemberReturnsObjectScalar_ReceivesValueAndFillsRemaining(o public async Task WhenMemberYieldsTuples_ExpandsColumnsAndFillsRemaining( string left, int right, MyClass leftover) { - await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right)); await Assert.That(leftover).IsNotNull(); } @@ -77,11 +76,10 @@ public async Task WhenMemberReturnsNull_ReceivesNullCellAndFillsRemaining(string public async Task WhenMemberReturnsTaskOfObjectArrays_UsesSuppliedValues( string a, int b, RecordType c) { - await Assert.That(new[] - { + await Assert.That<(string, int, string)[]>([ ("hello", 1, "world"), ("foo", 2, "bar") - }).Contains((a, b, c.Value)); + ]).Contains((a, b, c.Value)); } [Test] @@ -89,7 +87,7 @@ await Assert.That(new[] public async Task WhenMemberReturnsTaskOfTuples_ExpandsColumnsAndFillsRemaining( string left, int right, MyClass leftover) { - await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right)); await Assert.That(leftover).IsNotNull(); } @@ -98,18 +96,17 @@ public async Task WhenMemberReturnsTaskOfTuples_ExpandsColumnsAndFillsRemaining( public async Task WhenMemberReturnsAsyncObjectArrays_UsesSuppliedValues( string a, int b, RecordType c) { - await Assert.That(new[] - { + await Assert.That<(string, int, string)[]>([ ("hello", 1, "world"), ("foo", 2, "bar") - }).Contains((a, b, c.Value)); + ]).Contains((a, b, c.Value)); } [Test] [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.AsyncStrings))] public async Task WhenMemberReturnsAsyncStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover) { - await Assert.That(new[] { "one", "two" }).Contains(value); + await Assert.That(["one", "two"]).Contains(value); await Assert.That(leftover).IsNotNull(); } @@ -118,7 +115,7 @@ public async Task WhenMemberReturnsAsyncStrings_ReceivesValueAndFillsRemaining(s public async Task WhenMemberReturnsAsyncTuples_ExpandsColumnsAndFillsRemaining( string left, int right, MyClass leftover) { - await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right)); await Assert.That(leftover).IsNotNull(); } @@ -126,13 +123,13 @@ public async Task WhenMemberReturnsAsyncTuples_ExpandsColumnsAndFillsRemaining( [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.TupleField))] public async Task WhenMemberIsTupleField_ExpandsColumns(string left, int right) { - await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right)); } [Test] [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.TupleProperty))] public async Task WhenMemberIsTupleProperty_ExpandsColumns(string left, int right) { - await Assert.That(new[] { ("a", 1), ("b", 2) }).Contains((left, right)); + await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right)); } } diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs index 019c21e..e352226 100644 --- a/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs @@ -12,11 +12,10 @@ public class UsageScenarioTests [Test, LeadingAndTrailingComposite] public async Task WhenCompositeZipsPartialRows_MergesByCollapse(string a, int b, string c) { - await Assert.That(new[] - { + await Assert.That<(string, int, string)[]>([ ("alpha", 1, "tail-a"), ("beta", 2, "tail-b") - }).Contains((a, b, c)); + ]).Contains((a, b, c)); } [Test, ArgumentsThenMemberComposite] diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/AutoDataSourceTests/CombineTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/AutoDataSourceTests/CombineTests.cs index 68c58be..04c34e5 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/AutoDataSourceTests/CombineTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/AutoDataSourceTests/CombineTests.cs @@ -28,6 +28,7 @@ public async Task Constructor_WhenCreated_SetsPropertiesToExpectedValues() var sut = new AutoDataSource(fixtureFactory, source); // Assert + // Func needs an explicit type arg, or Assert.That invokes it and asserts on IFixture. await Assert.That>(sut.CreateFixture).IsSameReferenceAs(fixtureFactory); await Assert.That(sut.Source).IsSameReferenceAs(source); } @@ -90,9 +91,9 @@ public async Task GetData_WhenSourcePartial_CombinesWithAutoGeneratedValues() // Assert await Assert.That(result).IsNotNull(); await Assert.That(result.Length).IsEqualTo(3); - await Assert.That(result[0]).IsEquivalentTo(new object[] { "a", 15, 13.3 }); - await Assert.That(result[1]).IsEquivalentTo(new object[] { "b", 123, 13.3 }); - await Assert.That(result[2]).IsEquivalentTo(new object[] { "c", 999, 13.3 }); + await Assert.That(result[0]).IsEquivalentTo(["a", 15, 13.3]); + await Assert.That(result[1]).IsEquivalentTo(["b", 123, 13.3]); + await Assert.That(result[2]).IsEquivalentTo(["c", 999, 13.3]); } [Test] @@ -122,9 +123,9 @@ public async Task GetData_WhenSourceProvidesAllValues_DoesNotGenerateValues() // Assert await Assert.That(result).IsNotNull(); await Assert.That(result.Length).IsEqualTo(3); - await Assert.That(result[0]).IsEquivalentTo(new object[] { "a", 85, 913.12 }); - await Assert.That(result[1]).IsEquivalentTo(new object[] { "b", 519, 73.1 }); - await Assert.That(result[2]).IsEquivalentTo(new object[] { "c", 411, 529.6 }); + await Assert.That(result[0]).IsEquivalentTo(["a", 85, 913.12]); + await Assert.That(result[1]).IsEquivalentTo(["b", 519, 73.1]); + await Assert.That(result[2]).IsEquivalentTo(["c", 411, 529.6]); } [Test] @@ -193,7 +194,7 @@ public async Task GetData_WhenSourceReturnsNoTestData_ReturnsNoRows() // Arrange var source = new DelegatingDataSource { - TestData = Array.Empty(), + TestData = [], }; var fixture = new DelegatingFixture(); var sut = new AutoDataSource(() => fixture, source); diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs index 5a9e905..c58a1e2 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs @@ -71,14 +71,13 @@ public async Task GetDataRowsAsync_WhenMethodHasSingleParameter_ReturnsSingleIte public async Task GetDataRowsAsync_WhenCalled_ReturnsArgumentsFittingParameters() { // Arrange - var testData = new[] - { - new object[] { "hello", 16, 32.86d }, - new object[] { null, -1, -20.22 }, - new object[] { "one", 2 }, - new object[] { null }, - new object[] { }, - }; + object[][] testData = [ + [ "hello", 16, 32.86d ], + [null, -1, -20.22], + ["one", 2], + [null], + [], + ]; var sut = new DelegatingDataSource { TestData = testData }; var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); @@ -101,7 +100,7 @@ public async Task GetDataRowsAsync_WhenCalled_ReturnsArgumentsFittingParameters( public async Task GetDataRowsAsync_WhenMoreArgumentsThanParameters_Throws() { // Arrange - var testData = new[] { new object[] { "hello", 16, 32.86d, "extra" } }; + object[][] testData = [[ "hello", 16, 32.86d, "extra" ]]; var sut = new DelegatingDataSource { TestData = testData }; var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs index 20a039b..273ca6e 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs @@ -41,7 +41,7 @@ public async Task Type_WhenRead_ReturnsConstructorArgument() [Test] public async Task Parameters_WhenRead_ReturnsConstructorArguments() { - var expected = new[] { new object() }; + object[] expected = [new object()]; var sut = new ClassDataSource(typeof(object), expected); await Assert.That(sut.Parameters).IsEquivalentTo(expected); @@ -50,7 +50,7 @@ public async Task Parameters_WhenRead_ReturnsConstructorArguments() [Test] public async Task GetData_WhenConstructorParametersDontMatch_Throws() { - var parameters = new object[] { "a", 1 }; + object[] parameters = ["a", 1]; var sut = new ClassDataSource(typeof(object), parameters); var method = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); @@ -69,6 +69,6 @@ public async Task GetData_WhenConstructorParametersMatch_AppliesThem() var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); - await Assert.That(result.Single()).IsEquivalentTo(new object[] { "y", 25 }); + await Assert.That(result.Single()).IsEquivalentTo(["y", 25]); } } diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/FieldDataSourceTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/FieldDataSourceTests/ConstructionTests.cs index 3567590..84c6d81 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/FieldDataSourceTests/ConstructionTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/FieldDataSourceTests/ConstructionTests.cs @@ -79,19 +79,18 @@ public async Task GetData_WhenSourceIsScalar_ReturnsSingleRow() // Assert await Assert.That(result.Length).IsEqualTo(1); - await Assert.That(result[0]).IsEquivalentTo(new object[] { NonEnumerableField }); + await Assert.That(result[0]).IsEquivalentTo([NonEnumerableField]); } [Test] public async Task GetData_WhenCalled_ReturnsDataMatchingParameters() { // Arrange - var expected = new[] - { - new object[] { "hello", 1, new RecordType("world") }, - new object[] { "foo", 2, new RecordType("bar") }, - new object[] { "Han", 3, new RecordType("Solo") } - }; + object[][] expected = [ + [ "hello", 1, new RecordType("world") ], + ["foo", 2, new RecordType("bar")], + ["Han", 3, new RecordType("Solo")] + ]; var sourceField = typeof(FieldDataSourceTests) .GetField(nameof(TestDataFieldWithRecordValues)); var sut = new FieldDataSource(sourceField); diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/InlineDataSourceTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/InlineDataSourceTests/ConstructionTests.cs index 2616e78..fd6c575 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/InlineDataSourceTests/ConstructionTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/InlineDataSourceTests/ConstructionTests.cs @@ -11,8 +11,7 @@ public async Task Constructor_WhenCreated_IsDataSource() { // Arrange // Act - var sut = new InlineDataSource([ - ]); + var sut = new InlineDataSource([]); // Assert await Assert.That(sut).IsAssignableTo(); } @@ -30,7 +29,7 @@ await Assert.That(() => public async Task Values_WhenRead_ReturnsConstructorArguments() { // Arrange - var expectedValues = Array.Empty(); + object[] expectedValues = []; var sut = new InlineDataSource(expectedValues); // Act var result = sut.Values; @@ -42,8 +41,7 @@ public async Task Values_WhenRead_ReturnsConstructorArguments() public async Task GetData_WhenMethodIsNull_Throws() { // Arrange - var sut = new InlineDataSource([ - ]); + var sut = new InlineDataSource([]); // Act & Assert - call GetData directly so InlineDataSource's null guard is hit await Assert.That(async () => { @@ -57,7 +55,7 @@ await Assert.That(async () => public async Task GetData_WhenArgumentCountExceedsParameterCount_Throws() { // Arrange - var values = new object[] { "aloha", 42, 12.3d, "extra" }; + object[] values = ["aloha", 42, 12.3d, "extra"]; var sut = new InlineDataSource(values); var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); @@ -73,7 +71,7 @@ await Assert.That(() => public async Task GetData_WhenArgumentCountMatchesParameterCount_ReturnsTestData() { // Arrange - var values = new object[] { "aloha", 42, 12.3d }; + object[] values = ["aloha", 42, 12.3d]; var sut = new InlineDataSource(values); var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); @@ -90,7 +88,7 @@ public async Task GetData_WhenArgumentCountMatchesParameterCount_ReturnsTestData public async Task GetData_WhenArgumentCountLessThanParameterCount_ReturnsAllArguments() { // Arrange - var values = new object[] { "aloha", 42 }; + object[] values = ["aloha", 42]; var sut = new InlineDataSource(values); var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MemberDataSourceTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MemberDataSourceTests/ConstructionTests.cs index 6488939..dfd2652 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MemberDataSourceTests/ConstructionTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MemberDataSourceTests/ConstructionTests.cs @@ -10,9 +10,9 @@ public class MemberDataSourceTests public static object NonTestDataField = new(); public static object NonTestDataProperty => new(); public static object NonTestDataMethod() => new(); - public static IEnumerable EmptyTestDataField = Array.Empty(); - public static IEnumerable EmptyTestData => Array.Empty(); - public static IEnumerable GetEmptyTestData() => Array.Empty(); + public static IEnumerable EmptyTestDataField = []; + public static IEnumerable EmptyTestData => []; + public static IEnumerable GetEmptyTestData() => []; [Test] public async Task Constructor_WhenCreated_IsDataSource() diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs index f0ba263..3dc4c15 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs @@ -44,7 +44,7 @@ public async Task Constructor_WhenArgumentsIsNull_ThrowsArgumentNullException() public async Task Constructor_WhenArgumentsProvided_SetsMembers() { var methodInfo = typeof(ConstructionTests).GetMethod(nameof(this.Constructor_WhenCreated_IsDataSource)); - var arguments = new[] { new object() }; + object[] arguments = [new object()]; var sut = new MethodDataSource(methodInfo, arguments); @@ -55,11 +55,10 @@ public async Task Constructor_WhenArgumentsProvided_SetsMembers() [Test] public async Task GetData_WhenInvoked_CallsSourceMethod() { - var expected = new[] - { - new object[] { "hello", 1, new RecordType("world") }, - new object[] { "foo", 2, new RecordType("bar") } - }; + object[][] expected = [ + [ "hello", 1, new RecordType("world") ], + ["foo", 2, new RecordType("bar")] + ]; var sourceMethod = typeof(ConstructionTests).GetMethod(nameof(ObjectArrayRows)); var testMethod = typeof(SampleTestType).GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); var sut = new MethodDataSource(sourceMethod); diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs index ae53e3f..156150c 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs @@ -21,11 +21,7 @@ public async Task GetData_WhenNestedTaskOfTupleSequence_UnwrapsAllTasksAndExpand .Select(x => x()) .ToArray(); - await Assert.That(result).IsEquivalentTo(new object[][] - { - ["a", 1], - ["b", 2] - }); + await Assert.That(result).IsEquivalentTo([["a", 1], ["b", 2]]); } public static Task>> NestedTaskOfTupleSequence() => diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/PropertyDataSourceTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/PropertyDataSourceTests/ConstructionTests.cs index 2f5a4ba..d94ecfb 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/PropertyDataSourceTests/ConstructionTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/PropertyDataSourceTests/ConstructionTests.cs @@ -87,12 +87,11 @@ public async Task GetData_WhenSourceIsScalar_ReturnsSingleRow() public async Task GetData_WhenCalled_ReturnsDataMatchingParameters() { // Arrange - var expected = new[] - { - new object[] { "hello", 1, new RecordType("world") }, - new object[] { "foo", 2, new RecordType("bar") }, - new object[] { "Han", 3, new RecordType("Solo") } - }; + object[][] expected = [ + [ "hello", 1, new RecordType("world") ], + ["foo", 2, new RecordType("bar")], + ["Han", 3, new RecordType("Solo")] + ]; var sourceProperty = typeof(PropertyDataSourceTests) .GetProperty(nameof(TestDataPropertyWithRecordValues)); var sut = new PropertyDataSource(sourceProperty); @@ -119,12 +118,11 @@ public async Task GetData_WhenCalled_ReturnsDataMatchingParameters() public async Task GetData_WhenSourceReturnsNull_ReturnsNullArguments() { // Arrange - var expected = new[] - { - new object[] { null, 1, null }, - new object[] { null, 2, null }, - new object[] { null, 3, null } - }; + object[][] expected = [ + [ null, 1, null ], + [null, 2, null], + [null, 3, null] + ]; var sourceProperty = typeof(PropertyDataSourceTests) .GetProperty(nameof(TestDataPropertyWithNullValues)); var sut = new PropertyDataSource(sourceProperty); diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs index 76a890d..b329df4 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs @@ -15,7 +15,7 @@ public static class MemberDataShapes public static (string, int) SingleTuple() => ("a", 1); - public static IEnumerable EmptyObjectArrays() => Array.Empty(); + public static IEnumerable EmptyObjectArrays() => []; public static IEnumerable ObjectArrays() { diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingDataSource.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingDataSource.cs index 1481b8c..c2e124b 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingDataSource.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingDataSource.cs @@ -4,7 +4,7 @@ namespace AutoFixture.TUnit.Tests.TestTypes; public class DelegatingDataSource : BaseDataSourceAttribute, IDataSource { - public IEnumerable TestData { get; set; } = Array.Empty(); + public IEnumerable TestData { get; set; } = []; public override async IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata) {