Purview.SourceGeneratorFramework.Testing.TUnit 1.0.0-prerelease.38

This is a prerelease version of Purview.SourceGeneratorFramework.Testing.TUnit.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Purview.SourceGeneratorFramework.Testing.TUnit --version 1.0.0-prerelease.38
                    
NuGet\Install-Package Purview.SourceGeneratorFramework.Testing.TUnit -Version 1.0.0-prerelease.38
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Purview.SourceGeneratorFramework.Testing.TUnit" Version="1.0.0-prerelease.38" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Purview.SourceGeneratorFramework.Testing.TUnit" Version="1.0.0-prerelease.38" />
                    
Directory.Packages.props
<PackageReference Include="Purview.SourceGeneratorFramework.Testing.TUnit" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Purview.SourceGeneratorFramework.Testing.TUnit --version 1.0.0-prerelease.38
                    
#r "nuget: Purview.SourceGeneratorFramework.Testing.TUnit, 1.0.0-prerelease.38"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Purview.SourceGeneratorFramework.Testing.TUnit@1.0.0-prerelease.38
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Purview.SourceGeneratorFramework.Testing.TUnit&version=1.0.0-prerelease.38&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Purview.SourceGeneratorFramework.Testing.TUnit&version=1.0.0-prerelease.38&prerelease
                    
Install as a Cake Tool

Purview.SourceGeneratorFramework.Testing.TUnit

TUnit integration for testing incremental C# source generators built with Purview.SourceGeneratorFramework.

Installation

dotnet add package Purview.SourceGeneratorFramework.Testing.TUnit

What's included

  • TUnitSourceGeneratorTestBase<TGenerator> — ready-made base class for TUnit tests. It wires generator log output to TestContext.Current.OutputWriter.
  • Custom TUnit assertions for inspecting DriverRunResult instances directly in TUnit tests.
  • MSBuild .props — automatically adds global using directives for Purview.SourceGeneratorFramework.Testing.TUnit and Purview.SourceGeneratorFramework.Testing.TUnit.Assertions.

Usage

Reference the package from a TUnit test project:

<ItemGroup>
  <PackageReference Include="TUnit" />
  <PackageReference Include="Purview.SourceGeneratorFramework.Testing.TUnit" />
</ItemGroup>

Derive your test class from TUnitSourceGeneratorTestBase<TGenerator> and use the inherited GenerateAsync method:

using Purview.SourceGeneratorFramework.Testing.TUnit;

public class MyGeneratorTests : TUnitSourceGeneratorTestBase<MyGenerator>
{
    [Test]
    public async Task GeneratesExpectedSource()
    {
        var source = """
            [MyNamespace.MyAttribute]
            public partial class MyClass { }
            """;

        var result = await GenerateAsync(source);

        result.AssertNoCompilationErrors();
        var generated = result.AssertSingleGeneratedSource();

        await Assert.That(generated).Contains("public static partial class MyClass");
    }
}

The base class also provides access to the underlying SourceGeneratorTestRunner<TGenerator> behavior through GenerateAsync.

Using generated types in the TUnit project

If test source files use generated attributes or other generated declarations while the tests also derive from TUnitSourceGeneratorTestBase<TGenerator>, reference the generator project both as an analyzer and as a normal assembly:

<ItemGroup>
  
  <ProjectReference
    Include="..\..\src\MyGenerator\MyGenerator.csproj"
    PrivateAssets="all"
    OutputItemType="Analyzer"
    ReferenceOutputAssembly="false"
  />

  
  <ProjectReference
    Include="..\..\src\MyGenerator\MyGenerator.csproj"
    PrivateAssets="all"
    ReferenceOutputAssembly="true"
  />
</ItemGroup>

For example, the analyzer reference allows a test fixture to use [MyGeneratedAttribute], while the normal reference allows the test class to derive from TUnitSourceGeneratorTestBase<MyGenerator>. Do not add OutputItemType="Analyzer" to the normal reference.

For multi-target TUnit projects, the normal reference means the generator's Roslyn dependencies participate in reference resolution for every target. Build the generator against the Roslyn version that supports its API usage; this framework is built against Roslyn 5.0, which ships net8.0 and net9.0 package assets, so a .NET 8–10 test matrix still loads it. Compiler hosts that consume the generator as an analyzer must be Roslyn 5.0 or later (.NET 10 SDK / Visual Studio 2026). Do not force a newer System.Collections.Immutable version through central package management.

Which base class and method

Roslyn type Base class Method
Generator TUnitSourceGeneratorTestBase<TGenerator> GenerateAsync(source, options, ct)
Diagnostic analyzer TUnitDiagnosticAnalyzerTestBase<TAnalyzer> AnalyzeAsync(source, options, ct)
Code fix (single) TUnitCodeFixTestBase<TAnalyzer, TCodeFix> ApplyCodeFixAsync(source, options, ct)
Code fix (fix-all) TUnitCodeFixTestBase<TAnalyzer, TCodeFix> ApplyFixAllAsync(sources, options, ct)
Refactoring TUnitRefactoringTestBase<TRefactoring> RefactorAsync(source, options, ct)

For cache tests, TUnitSourceGeneratorTestBase also exposes GenerateIncrementalAsync(...).

Easy starting point: derived options

Derive a SourceGeneratorTestOptions record that seeds namespaces and additional assemblies, then pass it to every test:

public sealed record MyTestOptions : SourceGeneratorTestOptions
{
    public MyTestOptions()
    {
        AdditionalNamespaces = AdditionalNamespaces.Add("My.Namespace");
        AdditionalAssemblyTypes = AdditionalAssemblyTypes.AddRange(typeof(SomeDependencyType), typeof(TypeIdentity));
        DisableSourceGeneratorPropertyName = "DisableMyGenerator";
    }
}

public class MyGeneratorTests : TUnitSourceGeneratorTestBase<MyGenerator, MyTestOptions> { ... }

Use options.Compile() for CompileToAssembly, and the OnBeforeRun/OnBeforeRunAsync/OnAfterRun hooks for per-run customisation. Code-fix/refactoring tests select actions with EquivalenceKey or CodeActionIndex (and RefactorTestOptions.NodeSelector/Span).

Assertion extensions

All assertion extensions are under Purview.SourceGeneratorFramework.Testing.TUnit.Assertions (globally imported). await Assert.That(...) is terminal and returns the value:

  • HasGeneratedMethod / HasGeneratedMethodReturnType / HasGeneratedClass / HasGeneratedProperty / HasGeneratedField / HasGeneratedSyntaxTree — return the syntax node; HasGeneratedMethod(name, TypeReference[]) matches parameter types. HasGeneratedClass(name, arity) (or a TypeIdentity with arity) matches a generic type by its type-parameter count, so new TypeIdentity("ResourceDefinition", ns, arity: 1) finds ResourceDefinition<T> without matching the non-generic ResourceDefinition.
  • HasFixedMethod — same for code-fix and refactoring results.
  • HasPropertyOfType / HasFieldOfType / HasMethodOfType / HasConstructorOfType / HasAttributeOfType / HasNestedType — chain from a scoped CodeQueryResult<T> (for example the result of HasGeneratedClass) and return the matched member. The node-producing assertions move the chain onto the matched node, so you can append node-inspection assertions with .And:
    var method = await Assert.That(query)
        .HasGeneratedClass("Service")
        .And.HasNestedType("Builder")
        .And.WithAccessibility(Accessibility.Private)
        .And.HasMethodOfType("Build", []);
    
  • WithAccessibility / WithGetterAccessibility / WithSetterAccessibility / WithBaseType / WithGenericTypeParameter(s) / IsInNamespace / IsInGlobalNamespace — node-inspection assertions that keep the matched node on the chain. Accessibility resolves C# defaults (an unmodified nested type is Private, a top-level type Internal, interface/enum members Public, and an accessor with no modifier inherits its property's accessibility).
  • HasDiagnostic / HasDiagnostics / HasNoDiagnostics / DoesNotHaveDiagnostic / HasNoErrorDiagnostics.
  • HasSymbol(TypeIdentity) / HasSymbol("Namespace.Type").
  • GeneratesCode(expected) / ContainsGeneratedCode(expected) (whitespace-flattened).

The CodeQuery assertions operate on a CodeQuery directly, so they accept a query from any test result — result.Generated() for generated code, result.Output() for the whole compilation, or result.FixedCode() for fixed/refactored code. Convenience overloads on the test result types query the generated (or fixed) code for you.

To assert a nullable expected type, use the test-only query.MakeNullable(...) extension: it resolves the annotation against the query's compilation and, unlike TypeReference.Nullable()/TypeIdentity.MakeNullable(), does not trigger the PSGFR16 context-overload suggestion (tests have no generation context to pass).

var query = result.Generated();
MethodDeclarationSyntax method = await Assert.That(query).HasGeneratedMethod("DoWork", [intType, nullableInt]);
await Assert.That(query).HasGeneratedSyntaxTree("Service.g.cs");
await Assert.That(result.FixedCode()).HasFixedMethod("DoWork");   // code-fix / refactor results

// Scoped member chaining:
CodeQueryResult<ClassDeclarationSyntax> attributeClass = await Assert.That(query).HasGeneratedClass(hostKitAttribute);
await Assert.That(attributeClass).HasPropertyOfType("Name", query.MakeNullable(TypeLibrary.System.String));

Incremental cache tests

GenerateIncrementalAsync proves the pipeline caches stage-by-stage (first run New, identical rerun Cached/Unchanged, targeted changes mark only the affected stage Modified). A reference implementation (ServiceRegistrationCacheTests) lives in the Purview.SourceGeneratorFramework source repository's example generator tests; replicate it in your own project with your own stage names.

License

This project is licensed under the MIT license.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-prerelease.44 41 9/18/2026
1.0.0-prerelease.43 29 9/17/2026
1.0.0-prerelease.42 111 9/14/2026
1.0.0-prerelease.41 50 9/14/2026
1.0.0-prerelease.40 53 9/13/2026
1.0.0-prerelease.39 61 9/12/2026
1.0.0-prerelease.38 51 9/12/2026
1.0.0-prerelease.37 83 9/8/2026
1.0.0-prerelease.36 79 9/6/2026
1.0.0-prerelease.35 73 9/5/2026
1.0.0-prerelease.34 63 9/5/2026
1.0.0-prerelease.33 73 9/4/2026
1.0.0-prerelease.32 69 9/3/2026
1.0.0-prerelease.31 69 9/3/2026
1.0.0-prerelease.30 81 9/3/2026
1.0.0-prerelease.29 74 9/3/2026
1.0.0-prerelease.28 68 9/2/2026
1.0.0-prerelease.27 76 9/1/2026
1.0.0-prerelease.26 107 8/29/2026
1.0.0-prerelease.25 83 8/27/2026
Loading failed