Purview.SourceGeneratorFramework.Testing.TUnit
1.0.0-prerelease.42
See the version list below for details.
dotnet add package Purview.SourceGeneratorFramework.Testing.TUnit --version 1.0.0-prerelease.42
NuGet\Install-Package Purview.SourceGeneratorFramework.Testing.TUnit -Version 1.0.0-prerelease.42
<PackageReference Include="Purview.SourceGeneratorFramework.Testing.TUnit" Version="1.0.0-prerelease.42" />
<PackageVersion Include="Purview.SourceGeneratorFramework.Testing.TUnit" Version="1.0.0-prerelease.42" />
<PackageReference Include="Purview.SourceGeneratorFramework.Testing.TUnit" />
paket add Purview.SourceGeneratorFramework.Testing.TUnit --version 1.0.0-prerelease.42
#r "nuget: Purview.SourceGeneratorFramework.Testing.TUnit, 1.0.0-prerelease.42"
#:package Purview.SourceGeneratorFramework.Testing.TUnit@1.0.0-prerelease.42
#addin nuget:?package=Purview.SourceGeneratorFramework.Testing.TUnit&version=1.0.0-prerelease.42&prerelease
#tool nuget:?package=Purview.SourceGeneratorFramework.Testing.TUnit&version=1.0.0-prerelease.42&prerelease
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 toTestContext.Current.OutputWriter.- Custom TUnit assertions for inspecting
DriverRunResultinstances directly in TUnit tests. - MSBuild
.props— automatically addsglobal usingdirectives forPurview.SourceGeneratorFramework.Testing.TUnitandPurview.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 aTypeIdentitywith arity) matches a generic type by its type-parameter count, sonew TypeIdentity("ResourceDefinition", ns, arity: 1)findsResourceDefinition<T>without matching the non-genericResourceDefinition.HasFixedMethod— same for code-fix and refactoring results.HasPropertyOfType/HasFieldOfType/HasMethodOfType/HasConstructorOfType/HasAttributeOfType/HasNestedType— chain from a scopedCodeQueryResult<T>(for example the result ofHasGeneratedClass) 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 isPrivate, a top-level typeInternal, interface/enum membersPublic, 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 | Versions 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. |
-
.NETStandard 2.0
- Microsoft.CodeAnalysis.Analyzers (>= 5.9.0)
- Microsoft.CodeAnalysis.CSharp (>= 5.9.0)
- Microsoft.CodeAnalysis.CSharp.Workspaces (>= 5.9.0)
- Purview.SourceGeneratorFramework.Testing (>= 1.0.0-prerelease.42)
- System.Collections.Immutable (>= 10.0.1)
- System.Reflection.MetadataLoadContext (>= 10.0.1)
- TUnit.Assertions (>= 1.67.0)
- TUnit.Core (>= 1.67.0)
-
net10.0
- Microsoft.CodeAnalysis.Analyzers (>= 5.9.0)
- Microsoft.CodeAnalysis.CSharp (>= 5.9.0)
- Microsoft.CodeAnalysis.CSharp.Workspaces (>= 5.9.0)
- Purview.SourceGeneratorFramework.Testing (>= 1.0.0-prerelease.42)
- System.Reflection.MetadataLoadContext (>= 10.0.1)
- TUnit.Assertions (>= 1.67.0)
- TUnit.Core (>= 1.67.0)
-
net8.0
- Microsoft.CodeAnalysis.Analyzers (>= 5.9.0)
- Microsoft.CodeAnalysis.CSharp (>= 5.9.0)
- Microsoft.CodeAnalysis.CSharp.Workspaces (>= 5.9.0)
- Purview.SourceGeneratorFramework.Testing (>= 1.0.0-prerelease.42)
- System.Collections.Immutable (>= 10.0.1)
- System.Reflection.MetadataLoadContext (>= 10.0.1)
- TUnit.Assertions (>= 1.67.0)
- TUnit.Core (>= 1.67.0)
-
net9.0
- Microsoft.CodeAnalysis.Analyzers (>= 5.9.0)
- Microsoft.CodeAnalysis.CSharp (>= 5.9.0)
- Microsoft.CodeAnalysis.CSharp.Workspaces (>= 5.9.0)
- Purview.SourceGeneratorFramework.Testing (>= 1.0.0-prerelease.42)
- System.Collections.Immutable (>= 10.0.1)
- System.Reflection.MetadataLoadContext (>= 10.0.1)
- TUnit.Assertions (>= 1.67.0)
- TUnit.Core (>= 1.67.0)
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 |