Skip to content

Commit

Permalink
TUnit Templates
Browse files Browse the repository at this point in the history
  • Loading branch information
thomhurst committed Jan 18, 2025
1 parent d700e18 commit 1300de6
Show file tree
Hide file tree
Showing 15 changed files with 300 additions and 0 deletions.
5 changes: 5 additions & 0 deletions TUnit.Templates/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# TUnit.Templates

Some templates to help you get started with TUnit!

For more information, check out the repository at https://www.github.com/thomhurst/TUnit
42 changes: 42 additions & 0 deletions TUnit.Templates/TUnit.Templates.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<!-- The package metadata. Fill in the properties marked as TODO below -->
<!-- Follow the instructions on https://learn.microsoft.com/en-us/nuget/create-packages/package-authoring-best-practices -->
<PackageId>TUnit.Templates</PackageId>
<PackageVersion>1.0</PackageVersion>
<Title>TODO: fill the package name here</Title>
<Authors>Tom Longhurst</Authors>
<Description>TODO: fill the package description here</Description>
<PackageTags>TUnit,test,testing,unit,integration,acceptance</PackageTags>
<PackageProjectUrl>https://www.github.com/thomhurst/TUnit</PackageProjectUrl>

<!-- Keep package type as 'Template' to show the package as a template package on nuget.org and make your template available in dotnet new search.-->
<PackageType>Template</PackageType>
<TargetFramework>net9.0</TargetFramework>
<IncludeContentInPack>true</IncludeContentInPack>
<IncludeBuildOutput>false</IncludeBuildOutput>
<ContentTargetFolders>content</ContentTargetFolders>
<NoWarn>$(NoWarn);NU5128</NoWarn>
<NoDefaultExcludes>true</NoDefaultExcludes>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>

<PropertyGroup>
<LocalizeTemplates>false</LocalizeTemplates>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.TemplateEngine.Tasks" Version="*" PrivateAssets="all" IsImplicitlyDefined="true"/>
</ItemGroup>

<ItemGroup>
<Content Include="content\**\*" Exclude="content\**\bin\**;content\**\obj\**" />
<Compile Remove="**\*" />
</ItemGroup>

<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="" />
</ItemGroup>

</Project>
7 changes: 7 additions & 0 deletions TUnit.Templates/content/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ItemGroup>
<Using Include="TUnit.Core.HookType" Static="True" />
<Using Include="TUnit.Core" />
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions TUnit.Templates/content/Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
</Project>
42 changes: 42 additions & 0 deletions TUnit.Templates/content/TUnit/.template.config/template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"$schema": "http://json.schemastore.org/template",
"author": "Tom Longhurst",
"description": "Templates for getting started with TUnit",
"classifications": [
"Test",
"TUnit"
],
"name": "TUnit Test Project",
"identity": "TUnit.Test.Project",
"groupIdentity": "TUnit",
"shortName": "TUnit",
"tags": {
"language": "C#",
"type": "project"
},
"sourceName": "TestProject",
"preferNameDirectory": true,
"primaryOutputs": [
{
"path": "TestProject.csproj"
}
],
"postActions": [
{
"description": "Restore NuGet packages required by this project",
"manualInstructions": [
{
"text": "Run 'dotnet restore'"
}
],
"actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025",
"continueOnError": true,
"args": {
"files": [
"TestProject.csproj"
]
}
}
]
}

16 changes: 16 additions & 0 deletions TUnit.Templates/content/TUnit/Data/DataClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using TUnit.Core.Interfaces;

namespace TestProject;

public class DataClass : IAsyncInitializer, IAsyncDisposable
{
public Task InitializeAsync()
{
return Console.Out.WriteLineAsync("Classes can be injected into tests, and they can perform some initialisation logic such as starting an in-memory server or a test container.");
}

public async ValueTask DisposeAsync()
{
await Console.Out.WriteLineAsync("And when the class is finished with, we can clean up any resources.");
}
}
11 changes: 11 additions & 0 deletions TUnit.Templates/content/TUnit/Data/DataGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace TestProject.Data;

public class DataGenerator : DataSourceGeneratorAttribute<int, int, int>
{
public override IEnumerable<Func<(int, int, int)>> GenerateDataSources(DataGeneratorMetadata dataGeneratorMetadata)
{
yield return () => (1, 1, 2);
yield return () => (1, 2, 3);
yield return () => (4, 5, 9);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using TUnit.Core.Interfaces;

namespace TestProject;

public class DependencyInjectionClassConstructor : IClassConstructor
{
public T Create<T>(ClassConstructorMetadata classConstructorMetadata) where T : class
{
Console.WriteLine("You can also control how your test classes are new'd up, giving you lots of power and the ability to utilise tools such as dependency injection");

if (typeof(T) == typeof(AndEvenMoreTests))
{
return (new AndEvenMoreTests(new DataClass()) as T)!;
}

throw new NotImplementedException();
}
}
21 changes: 21 additions & 0 deletions TUnit.Templates/content/TUnit/GlobalSetup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Here you could define global logic that would affect all tests

// You can use attributes at the assembly level to apply to all tests in the assembly
[assembly: Retry(3)]

namespace TestProject;

public class GlobalHooks
{
[Before(TestSession)]
public static void SetUp()
{
Console.WriteLine("Or you can define methods that do stuff before...");
}

[After(TestSession)]
public static void CleanUp()
{
Console.WriteLine("...and after!");
}
}
14 changes: 14 additions & 0 deletions TUnit.Templates/content/TUnit/TestProject.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="TUnit" Version="0.6.121" />
</ItemGroup>

</Project>
69 changes: 69 additions & 0 deletions TUnit.Templates/content/TUnit/Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using TestProject.Data;

namespace TestProject;

public class Tests
{
[Test]
public void Basic()
{
Console.WriteLine("This is a basic test");
}

[Test]
[Arguments(1, 2, 3)]
[Arguments(2, 3, 5)]
public async Task DataDrivenArguments(int a, int b, int c)
{
Console.WriteLine("This one can accept arguments from an attribute");

var result = a + b;

await Assert.That(result).IsEqualTo(c);
}

[Test]
[MethodDataSource(nameof(DataSource))]
public async Task MethodDataSource(int a, int b, int c)
{
Console.WriteLine("This one can accept arguments from a method");

var result = a + b;

await Assert.That(result).IsEqualTo(c);
}

[Test]
[ClassDataSource<DataClass>]
[ClassDataSource<DataClass>(Shared = SharedType.PerClass)]
[ClassDataSource<DataClass>(Shared = SharedType.PerAssembly)]
[ClassDataSource<DataClass>(Shared = SharedType.PerTestSession)]
public void ClassDataSource(DataClass dataClass)
{
Console.WriteLine("This test can accept a class, which can also be pre-initialised before being injected in");

Console.WriteLine("These can also be shared among other tests, or new'd up each time, by using the `Shared` property on the attribute");
}

// You can even inject in ClassDataSources as properties to avoid repetitive constructors if you're using inheritance!
[ClassDataSource<DataClass>]
public required DataClass DataClass { get; init; }

[Test]
[DataGenerator]
public async Task CustomDataGenerator(int a, int b, int c)
{
Console.WriteLine("You can even define your own custom data generators");

var result = a + b;

await Assert.That(result).IsEqualTo(c);
}

public static IEnumerable<(int a, int b, int c)> DataSource()
{
yield return (1, 1, 2);
yield return (2, 1, 3);
yield return (3, 1, 4);
}
}
23 changes: 23 additions & 0 deletions TUnit.Templates/content/TUnit/Tests2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace TestProject;

[Arguments("Hello")]
[Arguments("World")]
public class MoreTests(string title)
{
[Test]
public void ClassLevelDataRow()
{
Console.WriteLine("Did I forget that data injection works on classes too?");
}

[Test]
public void Matrices(
[Matrix(1, 2, 3)] int a,
[Matrix(true, false)] bool b,
[Matrix("A", "B", "C")] string c)
{
Console.WriteLine("A new test will be created for each data row, whether it's on the class or method level!");

Console.WriteLine("Oh and this is a matrix test. That means all combinations of inputs are attempted.");
}
}
13 changes: 13 additions & 0 deletions TUnit.Templates/content/TUnit/Tests3.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace TestProject;

[ClassDataSource<DataClass>]
[ClassConstructor<DependencyInjectionClassConstructor>]
public class AndEvenMoreTests(DataClass dataClass)
{
[Test]
public void HaveFun()
{
Console.WriteLine("For more information, check out the documentation");
Console.WriteLine("https://thomhurst.github.io/TUnit/");
}
}
7 changes: 7 additions & 0 deletions TUnit.sln
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUnit.Analyzers.Roslyn47",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUnit.Engine.Tests", "TUnit.Engine.Tests\TUnit.Engine.Tests.csproj", "{E0E07E64-BC0A-489E-B562-2982F3836994}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TUnit.Templates\content\TUnit\TestProject.csproj", "{4BFDDFDB-96D9-42AA-85CE-9FBD017ACBE1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -183,6 +185,10 @@ Global
{E0E07E64-BC0A-489E-B562-2982F3836994}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E0E07E64-BC0A-489E-B562-2982F3836994}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E0E07E64-BC0A-489E-B562-2982F3836994}.Release|Any CPU.Build.0 = Release|Any CPU
{4BFDDFDB-96D9-42AA-85CE-9FBD017ACBE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4BFDDFDB-96D9-42AA-85CE-9FBD017ACBE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4BFDDFDB-96D9-42AA-85CE-9FBD017ACBE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4BFDDFDB-96D9-42AA-85CE-9FBD017ACBE1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -211,6 +217,7 @@ Global
{744CD312-B913-48E0-B917-531ED2A9A541} = {503DA9FA-045D-4910-8AF6-905E6048B1F1}
{54D5F1A7-7979-4C07-8FE1-426233846018} = {503DA9FA-045D-4910-8AF6-905E6048B1F1}
{E0E07E64-BC0A-489E-B562-2982F3836994} = {62AD1EAF-43C4-4AC0-B9FA-CD59739B3850}
{4BFDDFDB-96D9-42AA-85CE-9FBD017ACBE1} = {0BA988BF-ADCE-4343-9098-B4EF65C43709}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {109D285A-36B3-4503-BCDF-8E26FB0E2C5B}
Expand Down
9 changes: 9 additions & 0 deletions docs/docs/tutorial-basics/installing.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ sidebar_position: 1

# Installing TUnit

## Easily

Assuming you have the .NET SDK installed, simply run:

`dotnet new install TUnit.Templates`
`dotnet new TUnit`

## Manually

First create an empty .NET console application:

```powershell
Expand Down

0 comments on commit 1300de6

Please sign in to comment.