Skip to content

TUnit Support #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
root = true

[*.{cs,fs,fsx}]
indent_size = 4
indent_style = space

[*.{sln,csproj,fsproj,config,xml,props}]
indent_size = 2
indent_style = space

[*.cs]
indent_size = 4
indent_style = space

# Require "this." keyword qualification in code
dotnet_style_qualification_for_field = true:suggestion
dotnet_style_qualification_for_property = true:suggestion
dotnet_style_qualification_for_method = true:suggestion
dotnet_style_qualification_for_event = true:suggestion

dotnet_diagnostic.CA1510.severity = suggestion
dotnet_diagnostic.CA1859.severity = suggestion
2 changes: 1 addition & 1 deletion .nuke/build.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
},
"Solution": {
"type": "string",
"description": "Path to a solution file that is automatically loaded"
"description": "Path to a solution file that is automatically loaded. Default is AutoFixture.TUnit.sln"
}
}
},
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions AutoFixture.globalconfig → AutoFixture.TUnit.globalconfig
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ dotnet_diagnostic.CA5394.severity = none # CA5394: Do not use insecure randomnes

## 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
Expand All @@ -35,6 +36,7 @@ dotnet_diagnostic.SA1202.severity = none # SA1202: 'public' members should come
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
Expand Down
11 changes: 11 additions & 0 deletions AutoFixture.TUnit.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Common.props = Common.props
Common.Test.props = Common.Test.props
LICENCE.txt = LICENCE.txt
AutoFixture.TUnit.globalconfig = AutoFixture.TUnit.globalconfig
AutoFixture.TUnit.sln.DotSettings = AutoFixture.TUnit.sln.DotSettings
AutoFixture.TUnit.Tests.globalconfig = AutoFixture.TUnit.Tests.globalconfig
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestTypeFoundation", "tests\TestTypeFoundation\TestTypeFoundation.csproj", "{5F812210-5B61-4CBF-A033-4C33067A5DE9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -41,6 +46,12 @@ Global
{4056BD12-5FA8-4D2E-274A-7E85E858A5FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4056BD12-5FA8-4D2E-274A-7E85E858A5FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4056BD12-5FA8-4D2E-274A-7E85E858A5FC}.Verify|Any CPU.ActiveCfg = Verify|Any CPU
{5F812210-5B61-4CBF-A033-4C33067A5DE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F812210-5B61-4CBF-A033-4C33067A5DE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F812210-5B61-4CBF-A033-4C33067A5DE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F812210-5B61-4CBF-A033-4C33067A5DE9}.Release|Any CPU.Build.0 = Release|Any CPU
{5F812210-5B61-4CBF-A033-4C33067A5DE9}.Verify|Any CPU.ActiveCfg = Verify|Any CPU
{5F812210-5B61-4CBF-A033-4C33067A5DE9}.Verify|Any CPU.Build.0 = Verify|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion Common.Test.props
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@
</ItemGroup>

<ItemGroup>
<GlobalAnalyzerConfigFiles Include="$(MSBuildThisFileDirectory)/AutoFixture.Tests.globalconfig" />
<GlobalAnalyzerConfigFiles Include="$(MSBuildThisFileDirectory)/AutoFixture.TUnit.Tests.globalconfig" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion Common.props
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
</PropertyGroup>

<ItemGroup>
<GlobalAnalyzerConfigFiles Include="$(MSBuildThisFileDirectory)/AutoFixture.globalconfig" />
<GlobalAnalyzerConfigFiles Include="$(MSBuildThisFileDirectory)/AutoFixture.TUnit.globalconfig" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions build/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ csharp_style_expression_bodied_methods = true:silent
csharp_style_expression_bodied_properties = true:warning
csharp_style_expression_bodied_indexers = true:warning
csharp_style_expression_bodied_accessors = true:warning

dotnet_naming_style.field_style.capitalization = pascal_case
24 changes: 12 additions & 12 deletions build/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,20 @@
"continuous",
GitHubActionsImage.WindowsLatest,
AutoGenerate = false,
OnPullRequestBranches = new[] { MasterBranch, ReleaseBranch },
OnPullRequestBranches = [MasterBranch, ReleaseBranch],
PublishArtifacts = false,
InvokedTargets = new[] { nameof(Verify), nameof(Cover), nameof(Pack) },
InvokedTargets = [nameof(Verify), nameof(Cover), nameof(Pack)],
EnableGitHubToken = true)]
[GitHubActions(
"release",
GitHubActionsImage.WindowsLatest,
AutoGenerate = false,
OnPushTags = new[] { "v*" },
OnPushTags = ["v*"],
PublishArtifacts = true,
InvokedTargets = new[] { nameof(Verify), nameof(Cover), nameof(Publish) },
InvokedTargets = [nameof(Verify), nameof(Cover), nameof(Publish)],
EnableGitHubToken = true,
ImportSecrets = new[] { Secrets.NuGetApiKey })]
partial class Build : NukeBuild
ImportSecrets = [Secrets.NuGetApiKey])]
class Build : NukeBuild
{
public static int Main() => Execute<Build>(x => x.Compile);

Expand All @@ -43,22 +43,22 @@ partial class Build : NukeBuild
[Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")]
readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;

[Solution] readonly Solution Solution;
[Solution("AutoFixture.TUnit.sln")] readonly Solution Solution;
[GitRepository] readonly GitRepository GitRepository;
[GitVersion] readonly GitVersion GitVersion;
[CI] readonly GitHubActions GitHubActions;

[Parameter("GitHub auth token", Name = "github-token"), Secret] readonly string GitHubToken;
[Parameter("Forces the continuous integration build flag")] readonly bool CI;

[Secret] [Parameter("NuGet API Key (secret)", Name = Secrets.NuGetApiKey)] readonly string NuGetApiKey;
[Secret][Parameter("NuGet API Key (secret)", Name = Secrets.NuGetApiKey)] readonly string NuGetApiKey;
readonly string NuGetSource = "https://api.nuget.org/v3/index.json";

IEnumerable<Project> Excluded => new[]
{
IEnumerable<Project> Excluded =>
[
Solution.GetProject("_build"),
Solution.GetProject("TestTypeFoundation")
};
];

IEnumerable<Project> TestProjects => Solution.GetAllProjects("*Tests");
IEnumerable<Project> Libraries => Solution.Projects.Except(TestProjects).Except(Excluded);
Expand Down Expand Up @@ -147,7 +147,7 @@ partial class Build : NukeBuild
.Executes(() =>
{
ReportGenerator(_ => _
.SetFramework("net5.0")
.SetFramework("net8.0")
.SetAssemblyFilters("-TestTypeFoundation*")
.SetReports(TestResultsDirectory / "**" / "coverage.cobertura.xml")
.SetTargetDirectory(ReportsDirectory)
Expand Down
6 changes: 3 additions & 3 deletions build/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
[TypeConverter(typeof(TypeConverter<Configuration>))]
public class Configuration : Enumeration
{
public static Configuration Debug = new() { Value = nameof(Debug) };
public static Configuration Release = new() { Value = nameof(Release) };
public static Configuration Verify = new() { Value = nameof(Verify) };
public static readonly Configuration Debug = new() { Value = nameof(Debug) };
public static readonly Configuration Release = new() { Value = nameof(Release) };
public static readonly Configuration Verify = new() { Value = nameof(Verify) };

public static implicit operator string(Configuration configuration)
{
Expand Down
19 changes: 10 additions & 9 deletions build/GitHubActionsExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using System.Text.RegularExpressions;
using Nuke.Common.CI.GitHubActions;

namespace Nuke.Common.CI.GitHubActions
public static partial class GitHubActionsExtensions
{
public static class GitHubActionsExtensions
{
private static readonly Regex SemVerRef = new(@"^refs\/tags\/v(?<version>\d+\.\d+\.\d+)", RegexOptions.Compiled);
private static readonly Regex SemVerRef = GetSemVerRegex();

public static bool IsOnSemVerTag(this GitHubActions source)
{
return !string.IsNullOrWhiteSpace(source?.Ref)
&& SemVerRef.IsMatch(source.Ref);
}
public static bool IsOnSemVerTag(this GitHubActions source)
{
return !string.IsNullOrWhiteSpace(source?.Ref)
&& SemVerRef.IsMatch(source.Ref);
}

[GeneratedRegex(@"^refs\/tags\/v(?<version>\d+\.\d+\.\d+)", RegexOptions.Compiled)]
private static partial Regex GetSemVerRegex();
}
1 change: 1 addition & 0 deletions build/_build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<!-- NETSDK1138: Ignore .NET SDK deprecation notice -->
<NoWarn>$(NoWarn);NETSDK1138;NU1902;NU1903</NoWarn>
<Configurations>Debug;Release;Verify</Configurations>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
Expand Down
52 changes: 52 additions & 0 deletions src/AutoFixture.TUnit/ArgumentsAutoDataAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System.Diagnostics.CodeAnalysis;
using AutoFixture.TUnit.Internal;

namespace AutoFixture.TUnit;

/// <summary>
/// Provides a data source for a data theory, with the data coming from inline
/// values combined with auto-generated data specimens generated by AutoFixture.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
Justification = "This attribute is the root of a potential attribute hierarchy.")]
public class ArgumentsAutoDataAttribute : AutoFixtureDataSourceAttribute
{
/// <summary>
/// Initializes a new instance of the <see cref="ArgumentsAutoDataAttribute" /> class.
/// </summary>
/// <param name="values">The data values to pass to the theory.</param>
public ArgumentsAutoDataAttribute(params object?[] values)
: this(() => new Fixture(), values)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ArgumentsAutoDataAttribute" /> class.
/// </summary>
/// <param name="fixtureFactory">The fixture factory.</param>
/// <param name="values">The data values to pass to the theory.</param>
/// <exception cref="ArgumentNullException"></exception>
protected ArgumentsAutoDataAttribute(Func<IFixture> fixtureFactory, params object?[]? values)
{
this.FixtureFactory = fixtureFactory ?? throw new ArgumentNullException(nameof(fixtureFactory));
this.Values = values ?? [null];
}

/// <summary>
/// Gets the fixture factory.
/// </summary>
public Func<IFixture> FixtureFactory { get; }

/// <summary>
/// Gets the data values to pass to the theory.
/// </summary>
public object?[] Values { get; }

/// <inheritdoc />
public override IEnumerable<object?[]> GetData(DataGeneratorMetadata dataGeneratorMetadata)
{
return new AutoDataSource(this.FixtureFactory, new InlineDataSource(this.Values))
.GenerateDataSources(dataGeneratorMetadata)
.Select(x => x());
}
}
51 changes: 51 additions & 0 deletions src/AutoFixture.TUnit/AutoDataAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System.Diagnostics.CodeAnalysis;
using AutoFixture.TUnit.Internal;

namespace AutoFixture.TUnit;

/// <summary>
/// Provides auto-generated data specimens generated by AutoFixture as an extension to
/// xUnit.net's Theory attribute.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
Justification = "This attribute is the root of a potential attribute hierarchy.")]
public class AutoDataAttribute : AutoFixtureDataSourceAttribute
{
/// <summary>
/// Initializes a new instance of the <see cref="AutoDataAttribute" /> class.
/// </summary>
/// <remarks>
/// <para>
/// This constructor overload initializes the <see cref="Fixture" /> to an instance of
/// <see cref="Fixture" />.
/// </para>
/// </remarks>
public AutoDataAttribute()
: this(() => new Fixture())
{
}

/// <summary>
/// Initializes a new instance of the <see cref="AutoDataAttribute" /> class
/// with the supplied <paramref name="fixtureFactory" />. Fixture will be created
/// on demand using the provided factory.
/// </summary>
/// <param name="fixtureFactory">The fixture factory used to construct the fixture.</param>
protected AutoDataAttribute(Func<IFixture> fixtureFactory)
{
this.FixtureFactory = fixtureFactory ?? throw new ArgumentNullException(nameof(fixtureFactory));
}

/// <summary>
/// Gets the fixture factory.
/// </summary>
public Func<IFixture> FixtureFactory { get; }

/// <inheritdoc />
public override IEnumerable<object?[]> GetData(DataGeneratorMetadata dataGeneratorMetadata)
{
var source = new AutoDataSource(this.FixtureFactory);

return source.GenerateDataSources(dataGeneratorMetadata).Select(x => x());
}
}
56 changes: 56 additions & 0 deletions src/AutoFixture.TUnit/AutoFixtureDataSourceAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using AutoFixture.TUnit.Internal;

namespace AutoFixture.TUnit;

/// <summary>
/// Base class for data sources that provide AutoFixture test data for TUnit data driven tests.
/// </summary>
public abstract class AutoFixtureDataSourceAttribute : NonTypedDataSourceGeneratorAttribute, IDataSource
{
/// <summary>
/// Returns the test data provided by the source.
/// </summary>
/// <param name="dataGeneratorMetadata"></param>
/// <returns></returns>
public abstract IEnumerable<object?[]?> GetData(DataGeneratorMetadata dataGeneratorMetadata);

/// <inheritdoc />
public override IEnumerable<Func<object?[]>> GenerateDataSources(DataGeneratorMetadata dataGeneratorMetadata)
{
if (dataGeneratorMetadata is null)
{
throw new ArgumentNullException(nameof(dataGeneratorMetadata));
}

return GetTestDataEnumerable();

IEnumerable<Func<object?[]>> GetTestDataEnumerable()
{
var parameters = dataGeneratorMetadata.MembersToGenerate;
if (parameters.Length == 0)
{
// If the method has no parameters, a single test run is enough.
yield return () => [];
yield break;
}

var enumerable = this.GetData(dataGeneratorMetadata)
?? throw new InvalidOperationException("The source member yielded no test data.");

foreach (var testData in enumerable)
{
if (testData is null)
{
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.");
}

yield return () => testData;
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 0 additions & 14 deletions src/AutoFixture.TUnit/Class1.cs

This file was deleted.

Loading