Awesome
<img src="/src/icon.png" height="30px"> Verify.SourceGenerators
Extends Verify to allow verification of C# Source Generators.
See Milestones for release notes.
NuGet package
https://nuget.org/packages/Verify.SourceGenerators/
Install one of the Verify testing framework adapters NuGet packages.
Initialize
<!-- snippet: enable --><a id='snippet-enable'></a>
[ModuleInitializer]
public static void Init() =>
VerifySourceGenerators.Initialize();
<sup><a href='/src/Tests/ModuleInitializer.cs#L3-L9' title='Snippet source file'>snippet source</a> | <a href='#snippet-enable' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->Generator
Given a Source Generator:
<!-- snippet: HelloWorldGenerator.cs --><a id='snippet-HelloWorldGenerator.cs'></a>
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
[Generator]
public class HelloWorldGenerator :
ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var source1 = """
using System;
public static class Helper
{
public static void Method()
{
}
}
""";
context.AddSource("helper", SourceText.From(source1, Encoding.UTF8));
var source2 = """
using System;
public static class HelloWorld
{
public static void SayHello()
{
Console.WriteLine("Hello from generated code!");
}
}
""";
var sourceText = SourceText.From(source2, Encoding.UTF8);
context.AddSource("helloWorld", sourceText);
var descriptor = new DiagnosticDescriptor(
id: "theId",
title: "the title",
messageFormat: "the message from {0}",
category: "the category",
DiagnosticSeverity.Info,
isEnabledByDefault: true);
var location = Location.Create(
Path.Combine("dir", "theFile.cs"),
new(1, 2),
new(
new(1, 2),
new(3, 4)));
var diagnostic = Diagnostic.Create(descriptor, location, "hello world generator");
context.ReportDiagnostic(diagnostic);
}
public void Initialize(GeneratorInitializationContext context)
{
}
}
<sup><a href='/src/SampleGenerator/HelloWorldGenerator.cs#L1-L55' title='Snippet source file'>snippet source</a> | <a href='#snippet-HelloWorldGenerator.cs' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->Test
Can be tested as follows:
This snippets assumes use of the XUnit Verify adapter, change the using VerifyXUnit
if using other testing frameworks.
<a id='snippet-SampleTest.cs'></a>
public class SampleTest
{
[Fact]
public Task Driver()
{
var driver = BuildDriver();
return Verify(driver);
}
[Fact]
public Task RunResults()
{
var driver = BuildDriver();
var results = driver.GetRunResult();
return Verify(results);
}
[Fact]
public Task RunResult()
{
var driver = BuildDriver();
var result = driver.GetRunResult().Results.Single();
return Verify(result);
}
static GeneratorDriver BuildDriver()
{
var compilation = CSharpCompilation.Create("name");
var generator = new HelloWorldGenerator();
var driver = CSharpGeneratorDriver.Create(generator);
return driver.RunGenerators(compilation);
}
}
<sup><a href='/src/Tests/SampleTest.cs#L1-L37' title='Snippet source file'>snippet source</a> | <a href='#snippet-SampleTest.cs' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->Results
And will result in the following verified files:
Info file
An info file containing all metadata about the current state. eg any Diagnostics.
<!-- snippet: SampleTest.Driver.verified.txt --><a id='snippet-SampleTest.Driver.verified.txt'></a>
{
Diagnostics: [
{
Location: dir\theFile.cs: (1,2)-(3,4),
Message: the message from hello world generator,
Severity: Info,
WarningLevel: 1,
Descriptor: {
Id: theId,
Title: the title,
MessageFormat: the message from {0},
Category: the category,
DefaultSeverity: Info,
IsEnabledByDefault: true
}
}
]
}
<sup><a href='/src/Tests/SampleTest.Driver.verified.txt#L1-L18' title='Snippet source file'>snippet source</a> | <a href='#snippet-SampleTest.Driver.verified.txt' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->Source Files
Multiple source files. One for each GeneratorDriverRunResult.Results.GeneratedSources
.
<a id='snippet-SampleTest.Driver#helloWorld.verified.cs'></a>
//HintName: helloWorld.cs
using System;
public static class HelloWorld
{
public static void SayHello()
{
Console.WriteLine("Hello from generated code!");
}
}
<sup><a href='/src/Tests/SampleTest.Driver#helloWorld.verified.cs#L1-L9' title='Snippet source file'>snippet source</a> | <a href='#snippet-SampleTest.Driver#helloWorld.verified.cs' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->Manipulating Source
To manipulating the source of the generated cs files, use Scrubbers.
For example to remove all lines start with using
:
<a id='snippet-ScrubLines'></a>
[Fact]
public Task ScrubLines()
{
var driver = GeneratorDriver();
return Verify(driver)
.ScrubLines(_ => _.StartsWith("using "));
}
<sup><a href='/src/Tests/ScrubTest.cs#L3-L12' title='Snippet source file'>snippet source</a> | <a href='#snippet-ScrubLines' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->Ignoring Files
To ignore specific source text use IgnoreGeneratedResult
. This uses an expression of type Func<GeneratedSourceResult, bool>
to determine which outputs are ignored.
For example to ignore files with the name helper
or that contain the text static void SayHello()
:
<a id='snippet-IgnoreFile'></a>
[Fact]
public Task IgnoreFile()
{
var driver = GeneratorDriver();
return Verify(driver)
.IgnoreGeneratedResult(
_ => _.HintName.Contains("helper") ||
_.SourceText
.ToString()
.Contains("static void SayHello()"));
}
<sup><a href='/src/Tests/IgnoreTest.cs#L3-L18' title='Snippet source file'>snippet source</a> | <a href='#snippet-IgnoreFile' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->Notes:
Icon
Sauce designed by April Hsuan from The Noun Project.