Skip to content
3 changes: 2 additions & 1 deletion README_Template.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Visual Studio Code is supported.

- Native AOT / Trimmed Single File application support
- Source generated tests
- Dependency injection support ([See here](https://thomhurst.github.io/TUnit/docs/tutorial-extras/class-constructors))
- Property injection
- Full async support
- Parallel by default, with mechanisms to:
- Run specific tests completely on their own
Expand All @@ -69,6 +69,7 @@ Visual Studio Code is supported.
- Class
- Test
- Designed to avoid common pitfalls such as leaky test states
- Dependency injection support ([See here](https://thomhurst.github.io/TUnit/docs/tutorial-extras/class-constructors))
- Ability to view and interrogate metadata and results from various assembly/class/test context objects

## Installation
Expand Down
2 changes: 1 addition & 1 deletion TUnit.Core/Attributes/TestData/ArgumentsAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TUnit.Core;

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)]
public sealed class ArgumentsAttribute : TestDataAttribute
{
public object?[] Values { get; }
Expand Down
2 changes: 1 addition & 1 deletion TUnit.Core/Attributes/TestData/ClassDataSourceAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace TUnit.Core;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]
public sealed class ClassDataSourceAttribute<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>
: TestDataAttribute where T : new()
{
Expand Down
10 changes: 5 additions & 5 deletions TUnit.Core/Attributes/TestData/DataSourceGeneratorAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
namespace TUnit.Core;

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)]
public abstract class DataSourceGeneratorAttribute<T> : TestDataAttribute, IDataSourceGeneratorAttribute
{
public abstract IEnumerable<T> GenerateDataSources();
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)]
public abstract class DataSourceGeneratorAttribute<T1, T2> : TestDataAttribute, IDataSourceGeneratorAttribute
{
public abstract IEnumerable<(T1, T2)> GenerateDataSources();
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)]
public abstract class DataSourceGeneratorAttribute<T1, T2, T3> : TestDataAttribute, IDataSourceGeneratorAttribute
{
public abstract IEnumerable<(T1, T2, T3)> GenerateDataSources();
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)]
public abstract class DataSourceGeneratorAttribute<T1, T2, T3, T4> : TestDataAttribute, IDataSourceGeneratorAttribute
{
public abstract IEnumerable<(T1, T2, T3, T4)> GenerateDataSources();
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)]
public abstract class DataSourceGeneratorAttribute<T1, T2, T3, T4, T5> : TestDataAttribute, IDataSourceGeneratorAttribute
{
public abstract IEnumerable<(T1, T2, T3, T4, T5)> GenerateDataSources();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TUnit.Core;

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)]
public class MethodDataSourceAttribute : TestDataAttribute
{
public Type? ClassProvidingDataSource { get; }
Expand Down
1 change: 1 addition & 0 deletions TUnit.Engine.SourceGenerator.Tests/ClassConstructorTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using TUnit.Engine.SourceGenerator.CodeGenerators;
using TUnit.Engine.SourceGenerator.Tests.Extensions;
using TUnit.Engine.SourceGenerator.Tests.Options;

namespace TUnit.Engine.SourceGenerator.Tests;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ public Task Test(int index, string classMethodName, string testMethodName) => Ru
Assert.That(generatedFiles.Length, Is.EqualTo(4));

Assert.That(generatedFiles[index], Does.Contain($"var classArgTuples = global::System.TupleExtensions.ToTuple<global::System.Int32, global::System.String, global::System.Boolean>(global::TUnit.TestProject.ClassTupleDataSourceDrivenTests.{classMethodName}());"));
Assert.That(generatedFiles[index], Does.Contain("global::System.Int32 classArg0 = classArgTuples.Item1;"));
Assert.That(generatedFiles[index], Does.Contain("global::System.Int32 classArg = classArgTuples.Item1;"));
Assert.That(generatedFiles[index], Does.Contain("global::System.String classArg1 = classArgTuples.Item2;"));
Assert.That(generatedFiles[index], Does.Contain("global::System.Boolean classArg2 = classArgTuples.Item3;"));
Assert.That(generatedFiles[index], Does.Contain("var resettableClassFactoryDelegate = () => new ResettableLazy<global::TUnit.TestProject.ClassTupleDataSourceDrivenTests>(() => new global::TUnit.TestProject.ClassTupleDataSourceDrivenTests(classArg0, classArg1, classArg2));"));
Assert.That(generatedFiles[index], Does.Contain("var resettableClassFactoryDelegate = () => new ResettableLazy<global::TUnit.TestProject.ClassTupleDataSourceDrivenTests>(() => new global::TUnit.TestProject.ClassTupleDataSourceDrivenTests(classArg, classArg1, classArg2));"));

Assert.That(generatedFiles[index], Does.Contain($"var methodArgTuples = global::System.TupleExtensions.ToTuple<global::System.Int32, global::System.String, global::System.Boolean>(global::TUnit.TestProject.ClassTupleDataSourceDrivenTests.{testMethodName}());"));
Assert.That(generatedFiles[index], Does.Contain("global::System.Int32 methodArg0 = methodArgTuples.Item1;"));
Assert.That(generatedFiles[index], Does.Contain("global::System.Int32 methodArg = methodArgTuples.Item1;"));
Assert.That(generatedFiles[index], Does.Contain("global::System.String methodArg1 = methodArgTuples.Item2;"));
Assert.That(generatedFiles[index], Does.Contain("global::System.Boolean methodArg2 = methodArgTuples.Item3;"));

Assert.That(generatedFiles[index], Does.Contain("TestMethodArguments = [methodArg0, methodArg1, methodArg2],"));
Assert.That(generatedFiles[index], Does.Contain("DisplayName = $\"DataSource_TupleMethod({methodArg0}, {methodArg1}, {methodArg2})\","));
Assert.That(generatedFiles[index], Does.Contain("TestMethodFactory = (classInstance, cancellationToken) => AsyncConvert.Convert(() => classInstance.DataSource_TupleMethod(methodArg0, methodArg1, methodArg2))"));
Assert.That(generatedFiles[index], Does.Contain("TestMethodArguments = [methodArg, methodArg1, methodArg2],"));
Assert.That(generatedFiles[index], Does.Contain("DisplayName = $\"DataSource_TupleMethod({methodArg}, {methodArg1}, {methodArg2})\","));
Assert.That(generatedFiles[index], Does.Contain("TestMethodFactory = (classInstance, cancellationToken) => AsyncConvert.Convert(() => classInstance.DataSource_TupleMethod(methodArg, methodArg1, methodArg2))"));
});
}
4 changes: 2 additions & 2 deletions TUnit.Engine.SourceGenerator.Tests/CustomDisplayNameTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public Task Test() => RunTest(Path.Combine(Git.RootDirectory.FullName,

Assert.That(generatedFiles[0], Does.Contain("DisplayName = $\"A super important test!\","));
Assert.That(generatedFiles[1], Does.Contain("DisplayName = $\"Another super important test!\","));
Assert.That(generatedFiles[2], Does.Contain("DisplayName = $\"Test with: {methodArg0} {methodArg1} {methodArg2}!\","));
Assert.That(generatedFiles[3], Does.Contain("DisplayName = $\"Test with: {methodArg0} {methodArg1} {methodArg2}!\","));
Assert.That(generatedFiles[2], Does.Contain("DisplayName = $\"Test with: {methodArg} {methodArg1} {methodArg2}!\","));
Assert.That(generatedFiles[3], Does.Contain("DisplayName = $\"Test with: {methodArg} {methodArg1} {methodArg2}!\","));
});
}
36 changes: 18 additions & 18 deletions TUnit.Engine.SourceGenerator.Tests/DataDrivenTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,35 @@ public Task Test() => RunTest(Path.Combine(Git.RootDirectory.FullName,
{
Assert.That(generatedFiles.Length, Is.EqualTo(18));

Assert.That(generatedFiles[0], Does.Contain("global::System.Int32 methodArg0 = 1;"));
Assert.That(generatedFiles[1], Does.Contain("global::System.Int32 methodArg0 = 2;"));
Assert.That(generatedFiles[2], Does.Contain("global::System.Int32 methodArg0 = 3;"));
Assert.That(generatedFiles[0], Does.Contain("global::System.Int32 methodArg = 1;"));
Assert.That(generatedFiles[1], Does.Contain("global::System.Int32 methodArg = 2;"));
Assert.That(generatedFiles[2], Does.Contain("global::System.Int32 methodArg = 3;"));

Assert.That(generatedFiles[3], Does.Contain("global::System.Int32 methodArg0 = 1;"));
Assert.That(generatedFiles[3], Does.Contain("global::System.Int32 methodArg = 1;"));
Assert.That(generatedFiles[3], Does.Contain("global::System.String methodArg1 = \"String\";"));
Assert.That(generatedFiles[4], Does.Contain("global::System.Int32 methodArg0 = 2;"));
Assert.That(generatedFiles[4], Does.Contain("global::System.Int32 methodArg = 2;"));
Assert.That(generatedFiles[4], Does.Contain("global::System.String methodArg1 = \"String2\";"));
Assert.That(generatedFiles[5], Does.Contain("global::System.Int32 methodArg0 = 3;"));
Assert.That(generatedFiles[5], Does.Contain("global::System.Int32 methodArg = 3;"));
Assert.That(generatedFiles[5], Does.Contain("global::System.String methodArg1 = \"String3\";"));

Assert.That(generatedFiles[6], Does.Contain("global::TUnit.TestProject.TestEnum methodArg0 = global::TUnit.TestProject.TestEnum.One;"));
Assert.That(generatedFiles[7], Does.Contain("global::TUnit.TestProject.TestEnum methodArg0 = global::TUnit.TestProject.TestEnum.Two;"));
Assert.That(generatedFiles[8], Does.Contain("global::TUnit.TestProject.TestEnum methodArg0 = (global::TUnit.TestProject.TestEnum)(-1);"));
Assert.That(generatedFiles[6], Does.Contain("global::TUnit.TestProject.TestEnum methodArg = global::TUnit.TestProject.TestEnum.One;"));
Assert.That(generatedFiles[7], Does.Contain("global::TUnit.TestProject.TestEnum methodArg = global::TUnit.TestProject.TestEnum.Two;"));
Assert.That(generatedFiles[8], Does.Contain("global::TUnit.TestProject.TestEnum methodArg = (global::TUnit.TestProject.TestEnum)(-1);"));

Assert.That(generatedFiles[9], Does.Contain("global::System.String methodArg0 = null;"));
Assert.That(generatedFiles[9], Does.Contain("global::System.String methodArg = null;"));

Assert.That(generatedFiles[10], Does.Contain("global::System.String methodArg0 = \"\";"));
Assert.That(generatedFiles[10], Does.Contain("global::System.String methodArg = \"\";"));

Assert.That(generatedFiles[11], Does.Contain("global::System.String methodArg0 = \"Foo bar!\";"));
Assert.That(generatedFiles[11], Does.Contain("global::System.String methodArg = \"Foo bar!\";"));

Assert.That(generatedFiles[12], Does.Contain("global::System.Boolean? methodArg0 = null;"));
Assert.That(generatedFiles[13], Does.Contain("global::System.Boolean? methodArg0 = false;"));
Assert.That(generatedFiles[14], Does.Contain("global::System.Boolean? methodArg0 = true;"));
Assert.That(generatedFiles[12], Does.Contain("global::System.Boolean? methodArg = null;"));
Assert.That(generatedFiles[13], Does.Contain("global::System.Boolean? methodArg = false;"));
Assert.That(generatedFiles[14], Does.Contain("global::System.Boolean? methodArg = true;"));

Assert.That(generatedFiles[15], Does.Contain("global::System.Type methodArg0 = typeof(global::System.Object);"));
Assert.That(generatedFiles[15], Does.Contain("global::System.Type methodArg = typeof(global::System.Object);"));

Assert.That(generatedFiles[16], Does.Contain("global::System.Int32[] methodArg0 = new[] { 1, 2, 3 };"));
Assert.That(generatedFiles[16], Does.Contain("global::System.Int32[] methodArg = new[] { 1, 2, 3 };"));

Assert.That(generatedFiles[17], Does.Contain("global::System.Int32 methodArg0 = global::System.Int32.MaxValue;"));
Assert.That(generatedFiles[17], Does.Contain("global::System.Int32 methodArg = global::System.Int32.MaxValue;"));
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ public Task Test() => RunTest(Path.Combine(Git.RootDirectory.FullName,
Assert.That(generatedFiles[2], Does.Contain("TestId = $\"CL-GAC0:TL-GAC1:TUnit.TestProject.DataSourceGeneratorTests(System.Int32,System.String,System.Boolean).GeneratedData_Method2(System.Int32,System.String,System.Boolean):0\","));
Assert.That(generatedFiles[2], Does.Contain("var methodArgGeneratedDataArray = global::System.Reflection.CustomAttributeExtensions.GetCustomAttributes<global::TUnit.TestProject.DataSourceGeneratorTests.AutoFixtureGeneratorAttribute<global::System.Int32, global::System.String, global::System.Boolean>>(methodInfo).SelectMany(x => x.GenerateDataSources());"));
Assert.That(generatedFiles[2], Does.Contain("foreach (var methodArgGeneratedData in methodArgGeneratedDataArray)"));
Assert.That(generatedFiles[2], Does.Contain("global::System.Int32 methodArg0 = methodArgGeneratedData.Item1;"));
Assert.That(generatedFiles[2], Does.Contain("global::System.Int32 methodArg = methodArgGeneratedData.Item1;"));
Assert.That(generatedFiles[2], Does.Contain("global::System.String methodArg1 = methodArgGeneratedData.Item2;"));
Assert.That(generatedFiles[2], Does.Contain("global::System.Boolean methodArg2 = methodArgGeneratedData.Item3;"));
Assert.That(generatedFiles[2], Does.Contain("classInstance.GeneratedData_Method2(methodArg0, methodArg1, methodArg2)"));
Assert.That(generatedFiles[2], Does.Contain("classInstance.GeneratedData_Method2(methodArg, methodArg1, methodArg2)"));

Assert.That(generatedFiles[4], Does.Contain("TestId = $\"CL-GAC0:TL-GAC1:TUnit.TestProject.DataSourceGeneratorTests(System.Int32,System.String,System.Boolean).GeneratedData_Method3(System.Int32,System.String,System.Boolean):0\","));
Assert.That(generatedFiles[4], Does.Contain("var methodArgGeneratedDataArray = global::System.Reflection.CustomAttributeExtensions.GetCustomAttributes<global::TUnit.TestProject.DataSourceGeneratorTests.AutoFixtureGeneratorAttribute>(methodInfo).SelectMany(x => x.GenerateDataSources());"));
Assert.That(generatedFiles[4], Does.Contain("foreach (var methodArgGeneratedData in methodArgGeneratedDataArray)"));
Assert.That(generatedFiles[4], Does.Contain("global::System.Int32 methodArg0 = methodArgGeneratedData.Item1;"));
Assert.That(generatedFiles[4], Does.Contain("global::System.Int32 methodArg = methodArgGeneratedData.Item1;"));
Assert.That(generatedFiles[4], Does.Contain("global::System.String methodArg1 = methodArgGeneratedData.Item2;"));
Assert.That(generatedFiles[4], Does.Contain("global::System.Boolean methodArg2 = methodArgGeneratedData.Item3;"));
Assert.That(generatedFiles[4], Does.Contain("classInstance.GeneratedData_Method3(methodArg0, methodArg1, methodArg2)"));
Assert.That(generatedFiles[4], Does.Contain("classInstance.GeneratedData_Method3(methodArg, methodArg1, methodArg2)"));
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ public Task Test() => RunTest(Path.Combine(Git.RootDirectory.FullName,

Assert.That(generatedFiles[0], Does.Contain("foreach (var methodData in global::TUnit.TestProject.EnumerableTupleDataSourceDrivenTests.TupleMethod())"));
Assert.That(generatedFiles[0], Does.Contain("var methodArgTuples = global::System.TupleExtensions.ToTuple<global::System.Int32, global::System.String, global::System.Boolean>(methodData);"));
Assert.That(generatedFiles[0], Does.Contain("global::System.Int32 methodArg0 = methodArgTuples.Item1;"));
Assert.That(generatedFiles[0], Does.Contain("global::System.Int32 methodArg = methodArgTuples.Item1;"));
Assert.That(generatedFiles[0], Does.Contain("global::System.String methodArg1 = methodArgTuples.Item2;"));
Assert.That(generatedFiles[0], Does.Contain("global::System.Boolean methodArg2 = methodArgTuples.Item3;"));
Assert.That(generatedFiles[0], Does.Contain("TestMethodArguments = [methodArg0, methodArg1, methodArg2],"));
Assert.That(generatedFiles[0], Does.Contain("DisplayName = $\"DataSource_TupleMethod({methodArg0}, {methodArg1}, {methodArg2})\","));
Assert.That(generatedFiles[0], Does.Contain("TestMethodFactory = (classInstance, cancellationToken) => AsyncConvert.Convert(() => classInstance.DataSource_TupleMethod(methodArg0, methodArg1, methodArg2))"));
Assert.That(generatedFiles[0], Does.Contain("TestMethodArguments = [methodArg, methodArg1, methodArg2],"));
Assert.That(generatedFiles[0], Does.Contain("DisplayName = $\"DataSource_TupleMethod({methodArg}, {methodArg1}, {methodArg2})\","));
Assert.That(generatedFiles[0], Does.Contain("TestMethodFactory = (classInstance, cancellationToken) => AsyncConvert.Convert(() => classInstance.DataSource_TupleMethod(methodArg, methodArg1, methodArg2))"));

Assert.That(generatedFiles[1], Does.Contain("foreach (var methodData in global::TUnit.TestProject.EnumerableTupleDataSourceDrivenTests.NamedTupleMethod())"));
Assert.That(generatedFiles[0], Does.Contain("var methodArgTuples = global::System.TupleExtensions.ToTuple<global::System.Int32, global::System.String, global::System.Boolean>(methodData);"));
Assert.That(generatedFiles[0], Does.Contain("global::System.Int32 methodArg0 = methodArgTuples.Item1;"));
Assert.That(generatedFiles[0], Does.Contain("global::System.Int32 methodArg = methodArgTuples.Item1;"));
Assert.That(generatedFiles[0], Does.Contain("global::System.String methodArg1 = methodArgTuples.Item2;"));
Assert.That(generatedFiles[0], Does.Contain("global::System.Boolean methodArg2 = methodArgTuples.Item3;"));
Assert.That(generatedFiles[0], Does.Contain("TestMethodArguments = [methodArg0, methodArg1, methodArg2],"));
Assert.That(generatedFiles[1], Does.Contain("TestMethodArguments = [methodArg0, methodArg1, methodArg2],"));
Assert.That(generatedFiles[1], Does.Contain("DisplayName = $\"DataSource_TupleMethod({methodArg0}, {methodArg1}, {methodArg2})\","));
Assert.That(generatedFiles[1], Does.Contain("TestMethodFactory = (classInstance, cancellationToken) => AsyncConvert.Convert(() => classInstance.DataSource_TupleMethod(methodArg0, methodArg1, methodArg2))"));
Assert.That(generatedFiles[0], Does.Contain("TestMethodArguments = [methodArg, methodArg1, methodArg2],"));
Assert.That(generatedFiles[1], Does.Contain("TestMethodArguments = [methodArg, methodArg1, methodArg2],"));
Assert.That(generatedFiles[1], Does.Contain("DisplayName = $\"DataSource_TupleMethod({methodArg}, {methodArg1}, {methodArg2})\","));
Assert.That(generatedFiles[1], Does.Contain("TestMethodFactory = (classInstance, cancellationToken) => AsyncConvert.Convert(() => classInstance.DataSource_TupleMethod(methodArg, methodArg1, methodArg2))"));
});
}
Loading