Dena.CodeAnalysis.Testing 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Dena.CodeAnalysis.Testing --version 1.0.0
NuGet\Install-Package Dena.CodeAnalysis.Testing -Version 1.0.0
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="Dena.CodeAnalysis.Testing" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Dena.CodeAnalysis.Testing --version 1.0.0
#r "nuget: Dena.CodeAnalysis.Testing, 1.0.0"
#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.
// Install Dena.CodeAnalysis.Testing as a Cake Addin
#addin nuget:?package=Dena.CodeAnalysis.Testing&version=1.0.0

// Install Dena.CodeAnalysis.Testing as a Cake Tool
#tool nuget:?package=Dena.CodeAnalysis.Testing&version=1.0.0

Dena.CodeAnalysis.Testing

NuGet version CircleCI

This library provides TDD friendly DiagnosticAnalyzer test helpers:

  • DiagnosticAnalyzerRunner

    A runner for Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer. The purpose of the runner is providing another runner instead of Microsoft.CodeAnalysis.Analyzer.Testing.AnalyzerVerifier.VerifyAnalyzerAsync.

    Because of the AnalyzerVerifier has several problems:

    1. Using AnalyzerVerifier, it is hard to instantiate analyzer with custom arguments (the custom args may be needed if your analyzer is composed by several smaller analyzer-like components)
    2. AnalyzerVerifier may throw some exceptions because it test Diagnostics. But it should be optional because analyzer-like smaller components may not need it. If it is not optional the tests for the components become to need to wrap try-catch statements for each call of VerifyAnalyzerAsync
  • Test Doubles for DiagnosticAnalyzer

    • NullAnalyzer: it do nothing
    • StubAnalyzer: it analyze codes with a Dena.CodeAnalysis.Testing.AnalyzerActions
    • SpyAnalyzer: it analyze codes and do not report any Diagnostics, but instead it records all actions that registered via Microsoft.CodeAnalysis.Dignostics.AnalysisContext

Requirements

  • .NET Standard 2.1 or later

Usage

Run DiagnosticAnalyzer

var analyzer = new YourAnalyzer();

// The analyzer get intialized and get to call registered actions.
await DiagnosticAnalyzerRunner.Run(
    analyzer,
    @"public static class Foo
{
    public static void Bar()
    {
        System.Console.WriteLine(""Hello, World!"");
    }
}");

Get Diagnostics

var analyzer = new YourAnalyzer();

var diagnostics = await DiagnosticAnalyzerRunner.Run(
    analyzer,
    @"public static class Foo
{
    public static void Bar()
    {
        System.Console.WriteLine(""Hello, World!"");
    }
}");

Assert.AreEqual(0, diagnostics.Length);

Assert Locations

var location = diagnostic.Location;

LocationAssert.HaveTheSpan(
    "/0/Test0.",             // Optional. Skip path assertion if the path not specified,  
    new LinePosition(1, 0),
    new LinePosition(8, 5),
    location
);
var diagnostics = await DiagnosticAnalyzerRunner.Run(
    anyAnalyzer,
    @"
internal static class Foo
{
    internal static void Bar()
    {
        System.Console.WriteLine(""Hello, World!"");
    }
}
ERROR");

Assert.AreEqual(0, diagnostics.Length, DiagnosticsFormatter.Format(diagnostics));
// This message is like:
//
//   // /0/Test0.cs(9,1): error CS0116: A namespace cannot directly contain members such as fields or methods
//   DiagnosticResult.CompilerError(""CS0116"").WithSpan(""/0/Test0.cs"", 9, 1, 9, 6),

Check whether the DiagnosticAnalyzer.Initialize have been called

var spyAnalyzer = new SpyAnalyzer();

var diagnostics = await DiagnosticAnalyzerRunner.Run(
    spyAnalyzer,
    @"public static class Foo
{
    public static void Bar()
    {
        System.Console.WriteLine(""Hello, World!"");
    }
}");

Assert.IsTrue(spyAnalyzer.IsInitialized);

Check recorded actions

var spyAnalyzer = new SpyAnalyzer();

var diagnostics = await DiagnosticAnalyzerRunner.Run(
    spyAnalyzer,
    @"public static class Foo
{
    public static void Bar()
    {
        System.Console.WriteLine(""Hello, World!"");
    }
}");

// CompilationActionHistory hold the Compilation object that given
// to the action registered by AnalysisContext.RegisterCompilationAction.
Assert.AreEqual(1, spyAnalyzer.CompilationActionHistory.Count);

// Other available histories are:
//
//   - spyAnalyzer.CodeBlockActionHistory
//   - spyAnalyzer.CodeBlockStartActionHistory
//   - spyAnalyzer.CompilationActionHistory
//   - spyAnalyzer.CompilationStartActionHistory
//   - spyAnalyzer.OperationActionHistory
//   - spyAnalyzer.OperationBlockActionHistory
//   - spyAnalyzer.OperationBlockStartAction
//   - spyAnalyzer.OperationBlockStartActionHistory
//   - spyAnalyzer.SemanticModelActionHistory
//   - spyAnalyzer.SymbolActionHistory
//   - spyAnalyzer.SymbolStartActionHistory
//   - spyAnalyzer.SyntaxNodeActionHistory
//   - spyAnalyzer.SyntaxTreeActionHistory

Do something in action

var stubAnalyzer = new StubAnalyzer(
    new AnalyzerActions
    {
        CodeBlockStartAction = context => DoSomething()
    }
);

await DiagnosticAnalyzerRunner.Run(
    stubAnalyzer,
    @"public static class Foo
{
    public static void Bar()
    {
        System.Console.WriteLine(""Hello, World!"");
    }
}");

// Other available actions are:
//
//   - stubAnalyzer.CodeBlockAction
//   - stubAnalyzer.CodeBlockStartAction
//   - stubAnalyzer.CompilationAction
//   - stubAnalyzer.CompilationStartAction
//   - stubAnalyzer.OperationAction
//   - stubAnalyzer.OperationBlockAction
//   - stubAnalyzer.OperationBlockStartAction
//   - stubAnalyzer.OperationBlockStartAction
//   - stubAnalyzer.SemanticModelAction
//   - stubAnalyzer.SymbolAction
//   - stubAnalyzer.SymbolStartAction
//   - stubAnalyzer.SyntaxNodeAction
//   - stubAnalyzer.SyntaxTreeAction

License

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 was computed.  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. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen 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.

This package has no dependencies.

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
3.0.4 167 2/5/2024
3.0.3 323 10/3/2023
3.0.2 974 2/14/2023
3.0.1 261 2/14/2023
3.0.0 2,171 10/29/2021
2.0.0 626 9/9/2021
1.0.1 294 7/6/2021
1.0.0 317 2/22/2021
1.0.0-alpha3 180 2/19/2021
1.0.0-alpha2 188 2/19/2021
1.0.0-alpha1 204 2/19/2021
1.0.0-alpha0 222 2/19/2021