From 023fd1ab39d781c74aec388f0fc8bb74ab34873c Mon Sep 17 00:00:00 2001 From: Jean-Sebastien Carle <29762210+jscarle@users.noreply.github.com> Date: Sat, 20 Jun 2026 20:40:41 -0400 Subject: [PATCH] Added snapshot filename overloads. --- README.md | 7 ++ .../GeneratorDriverTestBase.cs | 77 ++++++++++++++++++- .../SourceGeneratorTestHelpers.MSTest.csproj | 6 +- .../GeneratorDriverRunResultExtensions.cs | 77 ++++++++++++++++++- .../SourceGeneratorTestHelpers.NUnit.csproj | 6 +- .../GeneratorDriverRunResultExtensions.cs | 77 ++++++++++++++++++- .../SourceGeneratorTestHelpers.XUnit.csproj | 6 +- 7 files changed, 235 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 024e101..cdbd042 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ result.ShouldProduce("TestId.g.cs", "expected source", false); ### Verify the difference Support for [Verify](https://github.com/VerifyTests/Verify) is built-in using the `VerifyAsync` method. +Generated source text is normalized to LF line endings before it is passed to Verify. #### XUnit @@ -105,6 +106,12 @@ public class SourceGeneratorTests } ``` +For parameterized tests, pass a stable snapshot name to avoid framework-specific parameter text in the snapshot file name: + +```cs +return result.VerifyAsync("TestId.g.cs", snapshotName: "SourceGeneratorTests.ShouldProduceTestId"); +``` + #### NUnit ```cs diff --git a/src/SourceGeneratorTestHelpers.MSTest/GeneratorDriverTestBase.cs b/src/SourceGeneratorTestHelpers.MSTest/GeneratorDriverTestBase.cs index 57c4d41..6b17ed8 100644 --- a/src/SourceGeneratorTestHelpers.MSTest/GeneratorDriverTestBase.cs +++ b/src/SourceGeneratorTestHelpers.MSTest/GeneratorDriverTestBase.cs @@ -64,23 +64,85 @@ public SettingsTask VerifyAsync( ArgumentNullException.ThrowIfNull(result); var generatedSource = result.InternalGetSource(filePathEndsWith); - var source = generatedSource.HasValue ? generatedSource.Value.Source : ""; + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; // ReSharper disable once ExplicitCallerInfoArgument - return Verify(source, "txt", verifySettings, sourceFile); + return VerifySource(source, verifySettings, sourceFile); } /// Verifies that the generated source from a with a specific file path using . /// The to get the source from. /// The string that the generated source's file path should end with. + /// The stable snapshot file name to use. + /// The verify settings. + /// The source file. + /// If is null. + /// If is null or whitespace. + public SettingsTask VerifyAsync( + GeneratorDriverRunResult result, + string filePathEndsWith, + string snapshotName, + VerifySettings? verifySettings = null, + [CallerFilePath] string sourceFile = "" + ) + { + ArgumentNullException.ThrowIfNull(result); + ArgumentException.ThrowIfNullOrWhiteSpace(snapshotName); + + var generatedSource = result.InternalGetSource(filePathEndsWith); + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; + + // ReSharper disable once ExplicitCallerInfoArgument + return VerifySource(source, verifySettings, sourceFile, snapshotName); + } + + /// Verifies that the generated source from a with a specific file path using . + /// The to get the source from. + /// The string that the generated source's file path should end with. + /// to assert on reported errors, othwerwise. Defaults to . + /// to assert on reported warnings, othwerwise. Defaults to . + /// The verify settings. + /// The source file. + /// If is null. + public SettingsTask VerifyAsync( + (ImmutableArray CompilationDiagnostics, GeneratorDriverRunResult Result) result, + string filePathEndsWith, + bool assertOnErrors = true, + bool assertOnWarnings = false, + VerifySettings? verifySettings = null, + [CallerFilePath] string sourceFile = "" + ) + { + ArgumentNullException.ThrowIfNull(result.Result); + + result.CompilationDiagnostics.InternalAssertOnDiagnostics(assertOnErrors, assertOnWarnings, message => throw new AssertFailedException(message), + "There were errors in the compilation." + ); + result.Result.Diagnostics.InternalAssertOnDiagnostics(assertOnErrors, assertOnWarnings, message => throw new AssertFailedException(message), + "There were errors in the output generated by the source generator." + ); + + var generatedSource = result.Result.InternalGetSource(filePathEndsWith); + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; + + // ReSharper disable once ExplicitCallerInfoArgument + return VerifySource(source, verifySettings, sourceFile); + } + + /// Verifies that the generated source from a with a specific file path using . + /// The to get the source from. + /// The string that the generated source's file path should end with. + /// The stable snapshot file name to use. /// to assert on reported errors, othwerwise. Defaults to . /// to assert on reported warnings, othwerwise. Defaults to . /// The verify settings. /// The source file. /// If is null. + /// If is null or whitespace. public SettingsTask VerifyAsync( (ImmutableArray CompilationDiagnostics, GeneratorDriverRunResult Result) result, string filePathEndsWith, + string snapshotName, bool assertOnErrors = true, bool assertOnWarnings = false, VerifySettings? verifySettings = null, @@ -88,6 +150,7 @@ public SettingsTask VerifyAsync( ) { ArgumentNullException.ThrowIfNull(result.Result); + ArgumentException.ThrowIfNullOrWhiteSpace(snapshotName); result.CompilationDiagnostics.InternalAssertOnDiagnostics(assertOnErrors, assertOnWarnings, message => throw new AssertFailedException(message), "There were errors in the compilation." @@ -97,9 +160,15 @@ public SettingsTask VerifyAsync( ); var generatedSource = result.Result.InternalGetSource(filePathEndsWith); - var source = generatedSource.HasValue ? generatedSource.Value.Source : ""; + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; // ReSharper disable once ExplicitCallerInfoArgument - return Verify(source, "txt", verifySettings, sourceFile); + return VerifySource(source, verifySettings, sourceFile, snapshotName); + } + + private SettingsTask VerifySource(string source, VerifySettings? verifySettings, string sourceFile, string? snapshotName = null) + { + var task = Verify(source, "txt", verifySettings, sourceFile); + return snapshotName is null ? task : task.UseFileName(snapshotName); } } diff --git a/src/SourceGeneratorTestHelpers.MSTest/SourceGeneratorTestHelpers.MSTest.csproj b/src/SourceGeneratorTestHelpers.MSTest/SourceGeneratorTestHelpers.MSTest.csproj index f99669a..5bcd249 100644 --- a/src/SourceGeneratorTestHelpers.MSTest/SourceGeneratorTestHelpers.MSTest.csproj +++ b/src/SourceGeneratorTestHelpers.MSTest/SourceGeneratorTestHelpers.MSTest.csproj @@ -6,7 +6,7 @@ enable SourceGeneratorTestHelpers.MSTest latest - 10.1.0 + 10.1.2 SourceGeneratorTestHelpers.MSTest Jean-Sebastien Carle Test helpers and extension methods to simplify testing of .NET source generators. @@ -18,8 +18,8 @@ https://github.com/jscarle/SourceGeneratorTestHelpers git testing source-generators mstest - 10.1.0.0 - 10.1.0.0 + 10.1.2.0 + 10.1.2.0 en-US true snupkg diff --git a/src/SourceGeneratorTestHelpers.NUnit/GeneratorDriverRunResultExtensions.cs b/src/SourceGeneratorTestHelpers.NUnit/GeneratorDriverRunResultExtensions.cs index 85b9f3c..3f94b44 100644 --- a/src/SourceGeneratorTestHelpers.NUnit/GeneratorDriverRunResultExtensions.cs +++ b/src/SourceGeneratorTestHelpers.NUnit/GeneratorDriverRunResultExtensions.cs @@ -64,23 +64,85 @@ public static SettingsTask VerifyAsync( ArgumentNullException.ThrowIfNull(result); var generatedSource = result.InternalGetSource(filePathEndsWith); - var source = generatedSource.HasValue ? generatedSource.Value.Source : ""; + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; // ReSharper disable once ExplicitCallerInfoArgument - return Verify(source, "txt", verifySettings, sourceFile); + return VerifySource(source, verifySettings, sourceFile); } /// Verifies that the generated source from a with a specific file path using . /// The to get the source from. /// The string that the generated source's file path should end with. + /// The stable snapshot file name to use. + /// The verify settings. + /// The source file. + /// If is null. + /// If is null or whitespace. + public static SettingsTask VerifyAsync( + this GeneratorDriverRunResult result, + string filePathEndsWith, + string snapshotName, + VerifySettings? verifySettings = null, + [CallerFilePath] string sourceFile = "" + ) + { + ArgumentNullException.ThrowIfNull(result); + ArgumentException.ThrowIfNullOrWhiteSpace(snapshotName); + + var generatedSource = result.InternalGetSource(filePathEndsWith); + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; + + // ReSharper disable once ExplicitCallerInfoArgument + return VerifySource(source, verifySettings, sourceFile, snapshotName); + } + + /// Verifies that the generated source from a with a specific file path using . + /// The to get the source from. + /// The string that the generated source's file path should end with. + /// to assert on reported errors, othwerwise. Defaults to . + /// to assert on reported warnings, othwerwise. Defaults to . + /// The verify settings. + /// The source file. + /// If is null. + public static SettingsTask VerifyAsync( + this (ImmutableArray CompilationDiagnostics, GeneratorDriverRunResult Result) result, + string filePathEndsWith, + bool assertOnErrors = true, + bool assertOnWarnings = false, + VerifySettings? verifySettings = null, + [CallerFilePath] string sourceFile = "" + ) + { + ArgumentNullException.ThrowIfNull(result.Result); + + result.CompilationDiagnostics.InternalAssertOnDiagnostics(assertOnErrors, assertOnWarnings, message => throw new AssertionException(message), + "There were errors in the compilation." + ); + result.Result.Diagnostics.InternalAssertOnDiagnostics(assertOnErrors, assertOnWarnings, message => throw new AssertionException(message), + "There were errors in the output generated by the source generator." + ); + + var generatedSource = result.Result.InternalGetSource(filePathEndsWith); + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; + + // ReSharper disable once ExplicitCallerInfoArgument + return VerifySource(source, verifySettings, sourceFile); + } + + /// Verifies that the generated source from a with a specific file path using . + /// The to get the source from. + /// The string that the generated source's file path should end with. + /// The stable snapshot file name to use. /// to assert on reported errors, othwerwise. Defaults to . /// to assert on reported warnings, othwerwise. Defaults to . /// The verify settings. /// The source file. /// If is null. + /// If is null or whitespace. public static SettingsTask VerifyAsync( this (ImmutableArray CompilationDiagnostics, GeneratorDriverRunResult Result) result, string filePathEndsWith, + string snapshotName, bool assertOnErrors = true, bool assertOnWarnings = false, VerifySettings? verifySettings = null, @@ -88,6 +150,7 @@ public static SettingsTask VerifyAsync( ) { ArgumentNullException.ThrowIfNull(result.Result); + ArgumentException.ThrowIfNullOrWhiteSpace(snapshotName); result.CompilationDiagnostics.InternalAssertOnDiagnostics(assertOnErrors, assertOnWarnings, message => throw new AssertionException(message), "There were errors in the compilation." @@ -97,9 +160,15 @@ public static SettingsTask VerifyAsync( ); var generatedSource = result.Result.InternalGetSource(filePathEndsWith); - var source = generatedSource.HasValue ? generatedSource.Value.Source : ""; + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; // ReSharper disable once ExplicitCallerInfoArgument - return Verify(source, "txt", verifySettings, sourceFile); + return VerifySource(source, verifySettings, sourceFile, snapshotName); + } + + private static SettingsTask VerifySource(string source, VerifySettings? verifySettings, string sourceFile, string? snapshotName = null) + { + var task = Verify(source, "txt", verifySettings, sourceFile); + return snapshotName is null ? task : task.UseFileName(snapshotName); } } diff --git a/src/SourceGeneratorTestHelpers.NUnit/SourceGeneratorTestHelpers.NUnit.csproj b/src/SourceGeneratorTestHelpers.NUnit/SourceGeneratorTestHelpers.NUnit.csproj index 8b2e9bd..5f91f86 100644 --- a/src/SourceGeneratorTestHelpers.NUnit/SourceGeneratorTestHelpers.NUnit.csproj +++ b/src/SourceGeneratorTestHelpers.NUnit/SourceGeneratorTestHelpers.NUnit.csproj @@ -6,7 +6,7 @@ enable SourceGeneratorTestHelpers.NUnit latest - 10.1.0 + 10.1.2 SourceGeneratorTestHelpers.NUnit Jean-Sebastien Carle Test helpers and extension methods to simplify testing of .NET source generators. @@ -18,8 +18,8 @@ https://github.com/jscarle/SourceGeneratorTestHelpers git testing source-generators nunit - 10.1.0.0 - 10.1.0.0 + 10.1.2.0 + 10.1.2.0 en-US true snupkg diff --git a/src/SourceGeneratorTestHelpers.XUnit/GeneratorDriverRunResultExtensions.cs b/src/SourceGeneratorTestHelpers.XUnit/GeneratorDriverRunResultExtensions.cs index 1b97639..298d006 100644 --- a/src/SourceGeneratorTestHelpers.XUnit/GeneratorDriverRunResultExtensions.cs +++ b/src/SourceGeneratorTestHelpers.XUnit/GeneratorDriverRunResultExtensions.cs @@ -64,23 +64,85 @@ public static SettingsTask VerifyAsync( ArgumentNullException.ThrowIfNull(result); var generatedSource = result.InternalGetSource(filePathEndsWith); - var source = generatedSource.HasValue ? generatedSource.Value.Source : ""; + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; // ReSharper disable once ExplicitCallerInfoArgument - return Verify(source, "txt", verifySettings, sourceFile); + return VerifySource(source, verifySettings, sourceFile); } /// Verifies that the generated source from a with a specific file path using . /// The to get the source from. /// The string that the generated source's file path should end with. + /// The stable snapshot file name to use. + /// The verify settings. + /// The source file. + /// If is null. + /// If is null or whitespace. + public static SettingsTask VerifyAsync( + this GeneratorDriverRunResult result, + string filePathEndsWith, + string snapshotName, + VerifySettings? verifySettings = null, + [CallerFilePath] string sourceFile = "" + ) + { + ArgumentNullException.ThrowIfNull(result); + ArgumentException.ThrowIfNullOrWhiteSpace(snapshotName); + + var generatedSource = result.InternalGetSource(filePathEndsWith); + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; + + // ReSharper disable once ExplicitCallerInfoArgument + return VerifySource(source, verifySettings, sourceFile, snapshotName); + } + + /// Verifies that the generated source from a with a specific file path using . + /// The to get the source from. + /// The string that the generated source's file path should end with. + /// to assert on reported errors, othwerwise. Defaults to . + /// to assert on reported warnings, othwerwise. Defaults to . + /// The verify settings. + /// The source file. + /// If is null. + public static SettingsTask VerifyAsync( + this (ImmutableArray CompilationDiagnostics, GeneratorDriverRunResult Result) result, + string filePathEndsWith, + bool assertOnErrors = true, + bool assertOnWarnings = false, + VerifySettings? verifySettings = null, + [CallerFilePath] string sourceFile = "" + ) + { + ArgumentNullException.ThrowIfNull(result.Result); + + result.CompilationDiagnostics.InternalAssertOnDiagnostics(assertOnErrors, assertOnWarnings, message => throw new XunitException(message), + "There were errors in the compilation." + ); + result.Result.Diagnostics.InternalAssertOnDiagnostics(assertOnErrors, assertOnWarnings, message => throw new XunitException(message), + "There were errors in the output generated by the source generator." + ); + + var generatedSource = result.Result.InternalGetSource(filePathEndsWith); + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; + + // ReSharper disable once ExplicitCallerInfoArgument + return VerifySource(source, verifySettings, sourceFile); + } + + /// Verifies that the generated source from a with a specific file path using . + /// The to get the source from. + /// The string that the generated source's file path should end with. + /// The stable snapshot file name to use. /// to assert on reported errors, othwerwise. Defaults to . /// to assert on reported warnings, othwerwise. Defaults to . /// The verify settings. /// The source file. /// If is null. + /// If is null or whitespace. public static SettingsTask VerifyAsync( this (ImmutableArray CompilationDiagnostics, GeneratorDriverRunResult Result) result, string filePathEndsWith, + string snapshotName, bool assertOnErrors = true, bool assertOnWarnings = false, VerifySettings? verifySettings = null, @@ -88,6 +150,7 @@ public static SettingsTask VerifyAsync( ) { ArgumentNullException.ThrowIfNull(result.Result); + ArgumentException.ThrowIfNullOrWhiteSpace(snapshotName); result.CompilationDiagnostics.InternalAssertOnDiagnostics(assertOnErrors, assertOnWarnings, message => throw new XunitException(message), "There were errors in the compilation." @@ -97,9 +160,15 @@ public static SettingsTask VerifyAsync( ); var generatedSource = result.Result.InternalGetSource(filePathEndsWith); - var source = generatedSource.HasValue ? generatedSource.Value.Source : ""; + var source = generatedSource.HasValue ? generatedSource.Value.Source.ReplaceLineEndings("\n") : ""; // ReSharper disable once ExplicitCallerInfoArgument - return Verify(source, "txt", verifySettings, sourceFile); + return VerifySource(source, verifySettings, sourceFile, snapshotName); + } + + private static SettingsTask VerifySource(string source, VerifySettings? verifySettings, string sourceFile, string? snapshotName = null) + { + var task = Verify(source, "txt", verifySettings, sourceFile); + return snapshotName is null ? task : task.UseFileName(snapshotName); } } diff --git a/src/SourceGeneratorTestHelpers.XUnit/SourceGeneratorTestHelpers.XUnit.csproj b/src/SourceGeneratorTestHelpers.XUnit/SourceGeneratorTestHelpers.XUnit.csproj index 16df5b8..c82567f 100644 --- a/src/SourceGeneratorTestHelpers.XUnit/SourceGeneratorTestHelpers.XUnit.csproj +++ b/src/SourceGeneratorTestHelpers.XUnit/SourceGeneratorTestHelpers.XUnit.csproj @@ -6,7 +6,7 @@ enable SourceGeneratorTestHelpers.XUnit latest - 10.1.1 + 10.1.2 SourceGeneratorTestHelpers.XUnit Jean-Sebastien Carle Test helpers and extension methods to simplify testing of .NET source generators. @@ -18,8 +18,8 @@ https://github.com/jscarle/SourceGeneratorTestHelpers git testing source-generators xunit - 10.1.1.0 - 10.1.1.0 + 10.1.2.0 + 10.1.2.0 en-US true snupkg