diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/AssemblyLoaderGenerator.cs b/TUnit.Core.SourceGenerator/CodeGenerators/AssemblyLoaderGenerator.cs
index 1a85f53357..57e91c9efe 100644
--- a/TUnit.Core.SourceGenerator/CodeGenerators/AssemblyLoaderGenerator.cs
+++ b/TUnit.Core.SourceGenerator/CodeGenerators/AssemblyLoaderGenerator.cs
@@ -17,10 +17,27 @@ public class AssemblyLoaderGenerator : IIncrementalGenerator
];
public void Initialize(IncrementalGeneratorInitializationContext context)
{
+ var enabledProvider = context.AnalyzerConfigOptionsProvider
+ .Select((options, _) =>
+ {
+ options.GlobalOptions.TryGetValue("build_property.EnableTUnitSourceGeneration", out var value);
+ return !string.Equals(value, "false", StringComparison.OrdinalIgnoreCase);
+ });
+
var provider = context.CompilationProvider
- .WithComparer(new PreventCompilationTriggerOnEveryKeystrokeComparer());
+ .WithComparer(new PreventCompilationTriggerOnEveryKeystrokeComparer())
+ .Combine(enabledProvider);
+
+ context.RegisterSourceOutput(provider, (sourceProductionContext, data) =>
+ {
+ var (compilation, isEnabled) = data;
+ if (!isEnabled)
+ {
+ return;
+ }
- context.RegisterSourceOutput(provider, (sourceProductionContext, source) => GenerateCode(sourceProductionContext, source));
+ GenerateCode(sourceProductionContext, compilation);
+ });
}
private void GenerateCode(SourceProductionContext context, Compilation compilation)
diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/DisableReflectionScannerGenerator.cs b/TUnit.Core.SourceGenerator/CodeGenerators/DisableReflectionScannerGenerator.cs
index 7fd52ff284..9374f6526c 100644
--- a/TUnit.Core.SourceGenerator/CodeGenerators/DisableReflectionScannerGenerator.cs
+++ b/TUnit.Core.SourceGenerator/CodeGenerators/DisableReflectionScannerGenerator.cs
@@ -9,10 +9,27 @@ public class DisableReflectionScannerGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
+ var enabledProvider = context.AnalyzerConfigOptionsProvider
+ .Select((options, _) =>
+ {
+ options.GlobalOptions.TryGetValue("build_property.EnableTUnitSourceGeneration", out var value);
+ return !string.Equals(value, "false", StringComparison.OrdinalIgnoreCase);
+ });
+
var provider = context.CompilationProvider
- .WithComparer(new PreventCompilationTriggerOnEveryKeystrokeComparer());
+ .WithComparer(new PreventCompilationTriggerOnEveryKeystrokeComparer())
+ .Combine(enabledProvider);
+
+ context.RegisterSourceOutput(provider, (sourceProductionContext, data) =>
+ {
+ var (_, isEnabled) = data;
+ if (!isEnabled)
+ {
+ return;
+ }
- context.RegisterSourceOutput(provider, (sourceProductionContext, _) => GenerateCode(sourceProductionContext));
+ GenerateCode(sourceProductionContext);
+ });
}
private void GenerateCode(SourceProductionContext context)
diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/DynamicTestsGenerator.cs b/TUnit.Core.SourceGenerator/CodeGenerators/DynamicTestsGenerator.cs
index 909f407905..e9ac52adf7 100644
--- a/TUnit.Core.SourceGenerator/CodeGenerators/DynamicTestsGenerator.cs
+++ b/TUnit.Core.SourceGenerator/CodeGenerators/DynamicTestsGenerator.cs
@@ -11,14 +11,31 @@ public class DynamicTestsGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
+ var enabledProvider = context.AnalyzerConfigOptionsProvider
+ .Select((options, _) =>
+ {
+ options.GlobalOptions.TryGetValue("build_property.EnableTUnitSourceGeneration", out var value);
+ return !string.Equals(value, "false", StringComparison.OrdinalIgnoreCase);
+ });
+
var standardTests = context.SyntaxProvider
.ForAttributeWithMetadataName(
"TUnit.Core.DynamicTestBuilderAttribute",
predicate: static (_, _) => true,
transform: static (ctx, _) => GetSemanticTargetForTestMethodGeneration(ctx))
- .Where(static m => m is not null);
+ .Where(static m => m is not null)
+ .Combine(enabledProvider);
+
+ context.RegisterSourceOutput(standardTests, (sourceContext, data) =>
+ {
+ var (testData, isEnabled) = data;
+ if (!isEnabled)
+ {
+ return;
+ }
- context.RegisterSourceOutput(standardTests, (sourceContext, data) => GenerateTests(sourceContext, data!));
+ GenerateTests(sourceContext, testData!);
+ });
}
static DynamicTestSourceDataModel? GetSemanticTargetForTestMethodGeneration(GeneratorAttributeSyntaxContext context)
diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/LanguageVersionCheckGenerator.cs b/TUnit.Core.SourceGenerator/CodeGenerators/LanguageVersionCheckGenerator.cs
index 412fea7a60..93e0aea6b9 100644
--- a/TUnit.Core.SourceGenerator/CodeGenerators/LanguageVersionCheckGenerator.cs
+++ b/TUnit.Core.SourceGenerator/CodeGenerators/LanguageVersionCheckGenerator.cs
@@ -8,6 +8,13 @@ public class LanguageVersionCheckGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
+ var enabledProvider = context.AnalyzerConfigOptionsProvider
+ .Select((options, _) =>
+ {
+ options.GlobalOptions.TryGetValue("build_property.EnableTUnitSourceGeneration", out var value);
+ return !string.Equals(value, "false", StringComparison.OrdinalIgnoreCase);
+ });
+
var settings = context.CompilationProvider
.Select((c, _) =>
{
@@ -16,10 +23,18 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
: null;
return csharpVersion;
- });
+ })
+ .Combine(enabledProvider);
- context.RegisterSourceOutput(settings, static (sourceProductionContext, languageVersion) =>
+ context.RegisterSourceOutput(settings, static (sourceProductionContext, data) =>
{
+ var (languageVersion, isEnabled) = data;
+
+ if (!isEnabled)
+ {
+ return;
+ }
+
if (languageVersion is null)
{
return;
diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/StaticPropertyInitializationGenerator.cs b/TUnit.Core.SourceGenerator/CodeGenerators/StaticPropertyInitializationGenerator.cs
index 5dafe1d93f..7f4cf2e9d6 100644
--- a/TUnit.Core.SourceGenerator/CodeGenerators/StaticPropertyInitializationGenerator.cs
+++ b/TUnit.Core.SourceGenerator/CodeGenerators/StaticPropertyInitializationGenerator.cs
@@ -15,15 +15,31 @@ public class StaticPropertyInitializationGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
+ var enabledProvider = context.AnalyzerConfigOptionsProvider
+ .Select((options, _) =>
+ {
+ options.GlobalOptions.TryGetValue("build_property.EnableTUnitSourceGeneration", out var value);
+ return !string.Equals(value, "false", StringComparison.OrdinalIgnoreCase);
+ });
+
var testClasses = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (s, _) => s is ClassDeclarationSyntax,
transform: static (ctx, _) => GetSemanticTargetForGeneration(ctx))
.Where(static t => t is not null)
- .Collect();
+ .Collect()
+ .Combine(enabledProvider);
+
+ context.RegisterSourceOutput(testClasses, (sourceProductionContext, data) =>
+ {
+ var (classes, isEnabled) = data;
+ if (!isEnabled)
+ {
+ return;
+ }
- context.RegisterSourceOutput(testClasses, (sourceProductionContext, testClasses) =>
- GenerateStaticPropertyInitialization(sourceProductionContext, testClasses.Where(t => t != null).ToImmutableArray()!));
+ GenerateStaticPropertyInitialization(sourceProductionContext, classes.Where(t => t != null).ToImmutableArray()!);
+ });
}
private static INamedTypeSymbol? GetSemanticTargetForGeneration(GeneratorSyntaxContext context)
diff --git a/TUnit.Core/TUnit.Core.props b/TUnit.Core/TUnit.Core.props
index 39e51639ab..b9533b105d 100644
--- a/TUnit.Core/TUnit.Core.props
+++ b/TUnit.Core/TUnit.Core.props
@@ -38,8 +38,14 @@
true
+
+
+ true
+
+
+
diff --git a/docs/docs/execution/engine-modes.md b/docs/docs/execution/engine-modes.md
index 009d9f59a6..4a6eefbc0b 100644
--- a/docs/docs/execution/engine-modes.md
+++ b/docs/docs/execution/engine-modes.md
@@ -91,6 +91,59 @@ Alternatively, you can configure this in a `.runsettings` file:
```
+### Optimizing Build Performance in Reflection Mode
+
+When using reflection mode exclusively (via `[assembly: ReflectionMode]`), you can improve build performance by disabling source generation entirely. Since the generated code won't be used at runtime in reflection mode, skipping source generation reduces compile times.
+
+Add this MSBuild property to your test project file (`.csproj`):
+
+```xml
+
+ false
+
+```
+
+**Example: bUnit Test Project with Optimized Build**
+```xml
+
+
+ net9.0
+
+ false
+
+
+
+
+
+
+
+```
+
+Then in your code:
+```csharp
+// Enable reflection mode for Razor component testing
+[assembly: ReflectionMode]
+
+namespace MyApp.Tests;
+
+public class CounterComponentTests : TestContext
+{
+ [Test]
+ public void CounterStartsAtZero()
+ {
+ var cut = RenderComponent();
+ cut.Find("p").TextContent.ShouldBe("Current count: 0");
+ }
+}
+```
+
+**Benefits:**
+- **Faster Builds**: Eliminates source generator execution at compile time
+- **Reduced Compiler Overhead**: Less work for the compiler to do
+- **Clear Intent**: Explicitly indicates the project uses reflection mode
+
+**Note:** This optimization is only beneficial when you're exclusively using reflection mode. If you're using source generation mode (the default), keep `EnableTUnitSourceGeneration` set to `true` (or omit it entirely, as `true` is the default).
+
## Native AOT Support
When publishing with Native AOT, TUnit's source generation mode provides additional benefits: