Skip to content

Conversation

Alex-Sob
Copy link

@Alex-Sob Alex-Sob commented Sep 15, 2025

I would like to propose some improvements for code analyzer tests.
I also proposed this in Roslyn SDK repo: #1226

Currently CSharpAnalyzerVerifier<TAnalyzer>.VerifyAnalyzerAsync method is used to run a code analyzer test:

public async Task Test()
{
    var source = "...";
    var expectedDiagnostics = new[] { ... };
    await VerifyCS.VerifyAnalyzerAsync(source, expectedDiagnostics); // VerifyCS is a type alias
}

Proposal

I believe that a factory method that creates a CSharpAnalyzerTest<TAnalyzer, TVerifier> could improve both usability and performance of tests. While this type comes from a package and cannot be modified, but it's possible to add such a method with the new extension members feature in C# 14:

public static class CSharpAnalyzerTestExtensions
{
    extension<TAnalyzer, TVerifier>(CSharpAnalyzerTest<TAnalyzer, TVerifier>) where ...
    {
        public static CSharpAnalyzerTest<TAnalyzer, TVerifier> Create([StringSyntax("C#-test")] string source, params ReadOnlySpan<DiagnosticResult> expectedDiagnostics);
    }

    public static CSharpAnalyzerTest<TAnalyzer, TVerifier> WithSource<TAnalyzer, TVerifier>(this CSharpAnalyzerTest<TAnalyzer, TVerifier> test, [StringSyntax("C#-test")] string source);
}

Using such a helper method could have some benefits:

  • It improves performance of tests because diagnostics are passed as params ReadOnlySpan<DiagnosticResult> that avoids array allocation. This is not possible with the async VerifyAnalyzerAsync method.

  • This allows to use additional helper methods that can be used to customize the test, to provide additional sources or test configuration if needed. For example, if each test needs some common code, test source code can be split into multiple 'files' and additional source can be provided using WithSource extension:

    private const string Program = """
        public class Program
        {
            public static void Main() { }
        }
        """;
    
    public async Task Test()
    {
        var source = "...";
        var test = CSTest.Create(source, CreateDiagnostic()).WithSource(Program); // CSTest is type alias
        await test.RunAsync();
    }

    This avoids code duplication as otherwise common code has to be included in each test. This can also keep the test source code clean so that it contains only the code necessary for a particular test without additional 'noise'.

  • Using [StringSyntax("C#-test")] attribute will ensure that test C# code gets syntax highlighting in Visual Studio for tests creating CSharpAnalyzerTest instance explicitly so that it can be customized (please see [Proposal] Analyzer test readability improvements #63642).

  • This will avoid the need to create 'local' helper methods in analyzer test classes that need to customize a test in some way.

Examples

I included some tests using this approach in #63657

@github-actions github-actions bot added the needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically label Sep 15, 2025
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Sep 15, 2025
@gfoidl gfoidl added analyzer Indicates an issue which is related to analyzer experience and removed needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically labels Sep 16, 2025
@Alex-Sob Alex-Sob closed this Sep 19, 2025
@Alex-Sob Alex-Sob reopened this Sep 19, 2025
@dotnet-policy-service dotnet-policy-service bot added this to the 11.0-preview1 milestone Sep 19, 2025
@Alex-Sob Alex-Sob closed this Sep 22, 2025
@Alex-Sob Alex-Sob reopened this Sep 22, 2025
Copy link
Contributor

Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime.
To make sure no conflicting changes have occurred, please rerun validation before merging. You can do this by leaving an /azp run comment here (requires commit rights), or by simply closing and reopening.

@dotnet-policy-service dotnet-policy-service bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Sep 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
analyzer Indicates an issue which is related to analyzer experience community-contribution Indicates that the PR has been added by a community member pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants