Skip to content

Conversation

Alex-Sob
Copy link

@Alex-Sob Alex-Sob commented Aug 18, 2025

I would like to suggest a couple of changes that can improve performance and readability of code analyzer tests (also submitted proposal to Roslyn SDK repo in #1226):

  • Use raw string literals for C# test source code in all unit tests for code analyzers.

  • Provide a helper method that creates Test instances. In most cases analyzer tests call VerifyCS.VerifyAnalyzerAsync passing test C# code. But it's often needed to specify additional test settings, like the language version in the case when a unit test needs to use language features introduced in a specific C# version. Currently it's done with a code like this:

    await new VerifyCS.Test
    {
        TestCode = @"...",
        LanguageVersion = LanguageVersion.CSharp8
    }.RunAsync();

    Currently C# code specified for TestCode does not get syntax highlighting.

    What about providing a helper method like this:

    public class Test : ...
    {
        public static Test Create([StringSyntax("C#-test")] string source, LanguageVersion languageVersion = DefaultLanguageVersion, params ReadOnlySpan<DiagnosticResult> expected) { ... }
    }

Currently the code in a test might look like this:

image

With raw string literals and a helper method, this is what it will look like:

image

Using such a helper could have some benefits:

  • This will improve performance of tests because diagnostics are passed as params ReadOnlySpan<DiagnosticResult> instead of params DiagnosticResult[]. Span-based parameter cannot be used in the async method VerifyCS.VerifyAnalyzerAsync.

  • Test code gets syntax highlighting.

  • 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 = VerifyCS.Test.Create(source, CreateDiagnostic()).WithSource(Program);
        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'.

  • VS draws a nice vertical line for raw string literals, which also means that there's no extra whitespace before the code so that it does not have to start from the very left overflowing the test.

  • Some test classes have their own helper methods that create a Test that may lack [StringSyntax] attribute for C# source code parameter (e.g. in Avoid reporting CA1859 for properties with setter more accessible than getter #50488). With a single helper that could be used instead, the attribute can be applied only in one place.

Examples

I included some tests using this approach in #50339

@Alex-Sob Alex-Sob requested a review from a team as a code owner August 18, 2025 13:30
@Alex-Sob Alex-Sob changed the title [Proposal] Analyzer test readability improvements [Proposal] Analyzer test readability/performance improvements Sep 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant