version | downloads | package |
---|---|---|
CodeAnalysis.TestTools |
The package provides tooling to verify the behavior of Diagnostic Analyzers, and Code Fix Providers. It does this by providing a (test) context builder, and a mechanism to define expected issues in code (files).
THe idea of defining expected issues that way, has been inspired by SonarSource. The same patterns are used, and their implementation has been an inspiration for this one.
The basic idea is that by adding comments (of a certain format) to a code file the verifier compare the actual raised issues and errors to the expected onces. If there are differences, the verification fails.
The easiest way to do this, is by adding // Noncompliant
to the end of a line
that contains an issue:
class MyClass { } // Noncompliant
By also adding {{Some expected message}}
the message itself is also checked:
class MyClass { } // Noncompliant {{Visibility should be specified.}}
To check the text span that is been reported on, two different options are supported:
namespace MyNameSpace
{
class MyClass { } // Noncompliant {{Visibility should be specified.}}
// ^^^^^^^^^^^^^
}
Or, Alternatively:
namespace MyNameSpace
{
class MyClass { } // Noncompliant ^4#12 {{Visibility should be specified.}}
}
If wanted, also the expected diagnostic ID can be specified:
class MyClass { } // Noncompliant [IDE0005] {{Visibility should be specified.}}
or multiple:
class MyClass { } // Noncompliant [IDE0005,XS034]
In some cases, it makes more sense to put the comment on another line than on the line of the issue. In that case, a (line) offset can be provided:
// Noncompliant@+1 [IDE0005,XS034]
class MyClass { }
Instead of a line of code being noncompliant, it is possible to mark a line as
an error too. Just use Error
instead of Noncompliant
:
public class Missing { // Error [CS1513]
A test can be setup using a test framework of choice. The examples here use NUnit.
[Test]
public void Verify_MyCSharpAnalyzer()
=> new MyCSharpAnalyzer()
.ForCS()
// or use .AddSnippet() where you provide the code as string.
.AddSource("Path/to/testcode.cs")
.Verify();
[Test]
public void Verify_MyVBAnalyzer()
=> new MyVBAnalyzer()
.ForVB()
.AddSource("Path/to/testcode.vb")
.Verify();
[Test]
public void Verify_MyAnalyzer()
=> new MyAnalyzer()
.ForProject(new FileInfo("myproject.csproj")
.Verify();
This will run your analyzer on the provided code, and throw a
VerificationFailed
exception if any expected issue did not raise or if any
unexpected issue (or error) occurred.
By default the following external references are included:
System.Data.Common
System.Linq
System.Runtime
System.Globalization
Microsoft.VisualBasic
(Visual Basic only)
The code base is compiled against the latest language version (currently C# 12, and Visual Basic 16.9).
The initialized context has been for one language. All changes/additions take that in to consideration. So extra analyzers/source files, etcetera, must be supported by that language.
Extra analyzers can be added using .Add(DiagnosticAnalyzer analyzer)
.
Extra files can be added using .AddSource(string path)
.
Extra code snippets can be added using .AddSnippet(string snippet)
.
Extra references can be added using .AddReference<TContainingType>()
,
where the assembly of TContainingType
is added. Alternatively
.AddReferences(params MetadataReference[] references)
and
.AddPackages(params NuGetPackage[] packages)
can be used.
The output kind of the assembly built (default OutputKind.DynamicallyLinkedLibrary
)
can be changed using .WithOutputKind(OutputKind outputKind)
.
The easiest way to change the language version (and with that the parsings
options) is by using .WithLanguageVersion(LanguageVersion version)
.
Alternatively .WithOptions(ParseOptions options)
can be used.
The arguments are based on the context of choice (C# or Visual Basic), so
you can not change the language with these methods.
Some (build) errors and warnings should/could be ignored. This can be done by
using .WithIgnoredDiagnostics(params string[] diagnosticIds)
.
If desired, AllowUnsafe
can be set to true
by using .WithUnsafeCode(true)
.
The global imports can be changed with .WithGlobalImports(IEnumerable<GlobalImport> imports)
.
By default these imports are done globally:
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Data
Imports System.Diagnostics
Imports System.Linq
Imports System.Threading.Tasks
Verifying code fix providers is an extension on the test context used for verifying diagnostics analyzers:
[Test]
public void Verify_MyCSharpCodeFixer()
=> new MyCSharpCodeAnalyzer()
.ForCS()
.AddSource("Path/to/testcode.tofix.cs")
.ForFix<MyCSharpCodeFixer>()
.AddSource("Path/to/testcode.fixed.cs")
.Verify();
It will iteratively fix all issues reported by the analyzer attached, until no new changes are reported. Then it will verify if that has resulted in the expected code changes.