From a4ed176afbf1acb4e513b33f2abca84fa8a0a859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Fri, 15 Mar 2024 12:27:33 +0100 Subject: [PATCH 1/3] wip --- .../AnalyzerReleases.Unshipped.md | 1 + .../DynamicDataShouldBeValidAnalyzer.cs | 93 ++++++++++++ .../MSTest.Analyzers/Helpers/DiagnosticIds.cs | 3 +- .../Helpers/WellKnownTypeNames.cs | 1 + .../DynamicDataShouldBeValidAnalyzerTests.cs | 135 ++++++++++++++++++ .../Properties/launchSettings.json | 2 +- 6 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs create mode 100644 test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs diff --git a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md index d9028fe812..7c3d25b72b 100644 --- a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md +++ b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md @@ -4,4 +4,5 @@ Rule ID | Category | Severity | Notes --------|----------|----------|------- +MSTEST0018 | Usage | Warning | DynamicDataShouldBeValidAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0018) MSTEST0034 | Usage | Info | UseClassCleanupBehaviorEndOfClassAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0034) diff --git a/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs new file mode 100644 index 0000000000..ca17286387 --- /dev/null +++ b/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Immutable; + +using Analyzer.Utilities.Extensions; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +using MSTest.Analyzers.Helpers; + +namespace MSTest.Analyzers; + +[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] +public sealed class DynamicDataShouldBeValidAnalyzer : DiagnosticAnalyzer +{ + private static readonly LocalizableResourceString Title = new(nameof(Resources.DataRowShouldBeValidTitle), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString Description = new(nameof(Resources.DataRowShouldBeValidDescription), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString MessageFormat = new(nameof(Resources.DataRowShouldBeValidMessageFormat_OnTestMethod), Resources.ResourceManager, typeof(Resources)); + + internal static readonly DiagnosticDescriptor NotTestMethodRule = DiagnosticDescriptorHelper.Create( + DiagnosticIds.DynamicDataShouldBeValidRuleId, + Title, + MessageFormat, + Description, + Category.Usage, + DiagnosticSeverity.Warning, + isEnabledByDefault: true); + + public override ImmutableArray SupportedDiagnostics { get; } + = ImmutableArray.Create(NotTestMethodRule); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + + context.RegisterCompilationStartAction(context => + { + if (context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingTestMethodAttribute, out var testMethodAttributeSymbol) + && context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingDynamicDataAttribute, out var dynamicDataAttributeSymbol)) + { + context.RegisterSymbolAction( + context => AnalyzeSymbol(context, testMethodAttributeSymbol, dynamicDataAttributeSymbol), + SymbolKind.Method); + } + }); + } + + private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol testMethodAttributeSymbol, INamedTypeSymbol dynamicDataAttributeSymbol) + { + IMethodSymbol methodSymbol = (IMethodSymbol)context.Symbol; + + bool isTestMethod = false; + List dynamicDataAttributes = new(); + foreach (var methodAttribute in methodSymbol.GetAttributes()) + { + // Current method should be a test method or should inherit from the TestMethod attribute. + // If it is, the current analyzer will trigger no diagnostic so it exits. + if (methodAttribute.AttributeClass.Inherits(testMethodAttributeSymbol)) + { + isTestMethod = true; + } + + if (SymbolEqualityComparer.Default.Equals(methodAttribute.AttributeClass, dynamicDataAttributeSymbol)) + { + dynamicDataAttributes.Add(methodAttribute); + } + } + + // Check if attribute is set on a test method. + if (!isTestMethod) + { + if (dynamicDataAttributes.Count > 0) + { + context.ReportDiagnostic(methodSymbol.CreateDiagnostic(NotTestMethodRule)); + } + + return; + } + + // Check each data row attribute. + foreach (var attribute in dynamicDataAttributes) + { + AnalyzeAttribute(context, attribute, methodSymbol); + } + } + + private static void AnalyzeAttribute(SymbolAnalysisContext context, AttributeData attributeData, IMethodSymbol methodSymbol) + { + } +} diff --git a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs index ec72320187..518be8b6ec 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs @@ -20,8 +20,9 @@ internal static class DiagnosticIds public const string AssemblyCleanupShouldBeValidRuleId = "MSTEST0013"; public const string DataRowShouldBeValidRuleId = "MSTEST0014"; public const string TestMethodShouldNotBeIgnoredRuleId = "MSTEST0015"; - public const string TestClassShouldHaveTestMethodRuleId = "MSTEST0016"; + public const string TestClassShouldHaveTestMethodRuleId = "MSTEST0016"; public const string AssertionArgsShouldBePassedInCorrectOrderRuleId = "MSTEST0017"; + public const string DynamicDataShouldBeValidRuleId = "MSTEST0018"; public const string PreferTestInitializeOverConstructorRuleId = "MSTEST0019"; public const string PreferConstructorOverTestInitializeRuleId = "MSTEST0020"; public const string PreferDisposeOverTestCleanupRuleId = "MSTEST0021"; diff --git a/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs b/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs index 2adb4ee34c..0c22df2816 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs @@ -19,6 +19,7 @@ internal static class WellKnownTypeNames public const string MicrosoftVisualStudioTestToolsUnitTestingDescriptionAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingDiscoverInternalsAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.DiscoverInternalsAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingDoNotParallelizeAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.DoNotParallelizeAttribute"; + public const string MicrosoftVisualStudioTestToolsUnitTestingDynamicDataAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingExpectedExceptionAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.ExpectedExceptionAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingIgnoreAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.IgnoreAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingInheritanceBehavior = "Microsoft.VisualStudio.TestTools.UnitTesting.InheritanceBehavior"; diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs b/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs new file mode 100644 index 0000000000..f85c9ba226 --- /dev/null +++ b/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.Testing.Framework; +using Microsoft.Testing.TestInfrastructure; + +using VerifyCS = MSTest.Analyzers.Test.CSharpCodeFixVerifier< + MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer, + Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; + +namespace MSTest.Analyzers.Test; + +[TestGroup] +public sealed class DynamicDataShouldBeValidAnalyzerTests(ITestExecutionContext testExecutionContext) : TestBase(testExecutionContext) +{ + public async Task WhenDataSourceMemberDoesNotExist_Diagnostic() + { + var code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [DynamicData("MemberNotFound")] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [DynamicData("MemberNotFound", typeof(SomeClass))] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [DynamicData(dynamicDataSourceName: "MemberNotFound")] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "MemberNotFound")] + [TestMethod] + public void TestMethod4(object[] o) + { + } + } + + public class SomeClass + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync(code); + } + + public async Task WhenDataDisplayMemberDoesNotExist_Diagnostic() + { + var code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [DynamicData("SomeProperty")] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [DynamicData("SomeProperty", typeof(SomeClass))] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [DynamicData(dynamicDataSourceName: "SomeProperty")] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeProperty")] + [TestMethod] + public void TestMethod4(object[] o) + { + } + } + + public class SomeClass + { + public static IEnumerable SomeProperty { get; set; } + } + """; + + await VerifyCS.VerifyAnalyzerAsync(code); + } + + public async Task WhenAppliedToNonTestMethod_Diagnostic() + { + var code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [DynamicData("SomeProperty")] + public void TestMethod1(object[] o) + { + } + + [DynamicData("SomeProperty", typeof(SomeClass))] + public void TestMethod2(object[] o) + { + } + + [DynamicData(dynamicDataSourceName: "SomeProperty")] + public void TestMethod3(object[] o) + { + } + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeProperty")] + public void TestMethod4(object[] o) + { + } + } + + public class SomeClass + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync(code); + } +} diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/Properties/launchSettings.json b/test/UnitTests/MSTest.Analyzers.UnitTests/Properties/launchSettings.json index d7b9c2736a..9d3c5b5324 100644 --- a/test/UnitTests/MSTest.Analyzers.UnitTests/Properties/launchSettings.json +++ b/test/UnitTests/MSTest.Analyzers.UnitTests/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "MSTest.Analyzers.UnitTests": { "commandName": "Project", - "commandLineArgs": "--treenode-filter /*/*/*/**" + "commandLineArgs": "--treenode-filter /*/*/DynamicDataShouldBeValidAnalyzerTests/**" } } } From 8aee8d430f49deb9d07e7fb1a8af5878e9c7f016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Tue, 30 Jul 2024 16:59:00 +0200 Subject: [PATCH 2/3] WIP --- .../DynamicDataShouldBeValidAnalyzer.cs | 100 +++- .../MSTest.Analyzers/Helpers/DiagnosticIds.cs | 2 +- .../Helpers/WellKnownTypeNames.cs | 2 + .../MSTest.Analyzers/PublicAPI.Unshipped.txt | 4 + .../MSTest.Analyzers/Resources.Designer.cs | 66 +++ src/Analyzers/MSTest.Analyzers/Resources.resx | 24 + .../MSTest.Analyzers/xlf/Resources.cs.xlf | 41 ++ .../MSTest.Analyzers/xlf/Resources.de.xlf | 41 ++ .../MSTest.Analyzers/xlf/Resources.es.xlf | 41 ++ .../MSTest.Analyzers/xlf/Resources.fr.xlf | 41 ++ .../MSTest.Analyzers/xlf/Resources.it.xlf | 41 ++ .../MSTest.Analyzers/xlf/Resources.ja.xlf | 41 ++ .../MSTest.Analyzers/xlf/Resources.ko.xlf | 41 ++ .../MSTest.Analyzers/xlf/Resources.pl.xlf | 41 ++ .../MSTest.Analyzers/xlf/Resources.pt-BR.xlf | 41 ++ .../MSTest.Analyzers/xlf/Resources.ru.xlf | 41 ++ .../MSTest.Analyzers/xlf/Resources.tr.xlf | 41 ++ .../xlf/Resources.zh-Hans.xlf | 41 ++ .../xlf/Resources.zh-Hant.xlf | 41 ++ .../DynamicDataShouldBeValidAnalyzerTests.cs | 471 +++++++++++++++++- 20 files changed, 1166 insertions(+), 36 deletions(-) diff --git a/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs index ca17286387..ec82a88a55 100644 --- a/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs +++ b/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs @@ -15,9 +15,9 @@ namespace MSTest.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] public sealed class DynamicDataShouldBeValidAnalyzer : DiagnosticAnalyzer { - private static readonly LocalizableResourceString Title = new(nameof(Resources.DataRowShouldBeValidTitle), Resources.ResourceManager, typeof(Resources)); - private static readonly LocalizableResourceString Description = new(nameof(Resources.DataRowShouldBeValidDescription), Resources.ResourceManager, typeof(Resources)); - private static readonly LocalizableResourceString MessageFormat = new(nameof(Resources.DataRowShouldBeValidMessageFormat_OnTestMethod), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString Title = new(nameof(Resources.DynamicDataShouldBeValidTitle), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString Description = new(nameof(Resources.DynamicDataShouldBeValidDescription), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString MessageFormat = new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_OnTestMethod), Resources.ResourceManager, typeof(Resources)); internal static readonly DiagnosticDescriptor NotTestMethodRule = DiagnosticDescriptorHelper.Create( DiagnosticIds.DynamicDataShouldBeValidRuleId, @@ -28,6 +28,18 @@ public sealed class DynamicDataShouldBeValidAnalyzer : DiagnosticAnalyzer DiagnosticSeverity.Warning, isEnabledByDefault: true); + internal static readonly DiagnosticDescriptor MemberNotFoundRule = NotTestMethodRule + .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_MemberNotFound), Resources.ResourceManager, typeof(Resources))); + + internal static readonly DiagnosticDescriptor FoundTooManyMembersRule = NotTestMethodRule + .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_TooManyMembers), Resources.ResourceManager, typeof(Resources))); + + internal static readonly DiagnosticDescriptor MemberPropertyRule = NotTestMethodRule + .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_MemberProperty), Resources.ResourceManager, typeof(Resources))); + + internal static readonly DiagnosticDescriptor MemberMethodRule = NotTestMethodRule + .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_MemberMethod), Resources.ResourceManager, typeof(Resources))); + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(NotTestMethodRule); @@ -38,23 +50,24 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(context => { - if (context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingTestMethodAttribute, out var testMethodAttributeSymbol) - && context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingDynamicDataAttribute, out var dynamicDataAttributeSymbol)) + if (context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingTestMethodAttribute, out INamedTypeSymbol? testMethodAttributeSymbol) + && context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingDynamicDataAttribute, out INamedTypeSymbol? dynamicDataAttributeSymbol) + && context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingDynamicDataSourceType, out INamedTypeSymbol? dynamicDataSourceTypeSymbol)) { context.RegisterSymbolAction( - context => AnalyzeSymbol(context, testMethodAttributeSymbol, dynamicDataAttributeSymbol), + context => AnalyzeSymbol(context, testMethodAttributeSymbol, dynamicDataAttributeSymbol, dynamicDataSourceTypeSymbol), SymbolKind.Method); } }); } - private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol testMethodAttributeSymbol, INamedTypeSymbol dynamicDataAttributeSymbol) + private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol testMethodAttributeSymbol, INamedTypeSymbol dynamicDataAttributeSymbol, INamedTypeSymbol dynamicDataSourceTypeSymbol) { - IMethodSymbol methodSymbol = (IMethodSymbol)context.Symbol; + var methodSymbol = (IMethodSymbol)context.Symbol; bool isTestMethod = false; List dynamicDataAttributes = new(); - foreach (var methodAttribute in methodSymbol.GetAttributes()) + foreach (AttributeData methodAttribute in methodSymbol.GetAttributes()) { // Current method should be a test method or should inherit from the TestMethod attribute. // If it is, the current analyzer will trigger no diagnostic so it exits. @@ -81,13 +94,76 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo } // Check each data row attribute. - foreach (var attribute in dynamicDataAttributes) + foreach (AttributeData attribute in dynamicDataAttributes) { - AnalyzeAttribute(context, attribute, methodSymbol); + AnalyzeAttribute(context, attribute, methodSymbol, dynamicDataSourceTypeSymbol); } } - private static void AnalyzeAttribute(SymbolAnalysisContext context, AttributeData attributeData, IMethodSymbol methodSymbol) + private static void AnalyzeAttribute(SymbolAnalysisContext context, AttributeData attributeData, IMethodSymbol methodSymbol, INamedTypeSymbol dynamicDataSourceTypeSymbol) { + string? memberName = null; + int dataSourceType = 0; + INamedTypeSymbol declaringType = methodSymbol.ContainingType; + foreach (TypedConstant argument in attributeData.ConstructorArguments) + { + if (argument.Type is null) + { + continue; + } + + if (argument.Type.SpecialType == SpecialType.System_String + && argument.Value is string name) + { + memberName = name; + } + else if (SymbolEqualityComparer.Default.Equals(argument.Type, dynamicDataSourceTypeSymbol) + && argument.Value is int dataType) + { + dataSourceType = dataType; + } + else if (argument.Value is INamedTypeSymbol type) + { + declaringType = type; + } + } + + // If the member name is not available, bail out. + if (memberName is null + || attributeData.ApplicationSyntaxReference?.GetSyntax() is not { } attributeSyntax) + { + return; + } + + // If we cannot find the member on the given type, report a diagnostic. + if (declaringType.GetMembers(memberName) is { Length: 0 } potentialMembers) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberNotFoundRule, declaringType.Name, memberName)); + return; + } + + // If there are multiple members with the same name, report a diagnostic. This is not a supported scenario. + if (potentialMembers.Length > 1) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(FoundTooManyMembersRule, declaringType.Name, memberName)); + return; + } + + // If the member is a property and the data source type is not set to property, report a diagnostic. + if (potentialMembers[0].Kind == SymbolKind.Property && dataSourceType is not 0) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberPropertyRule, declaringType.Name, memberName)); + return; + } + + // If the member is a method and the data source type is not set to method, report a diagnostic. + if (potentialMembers[0].Kind == SymbolKind.Method && dataSourceType is not 1) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberMethodRule, declaringType.Name, memberName)); + return; + } + + // Validate member return type. + var a = 1; } } diff --git a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs index 518be8b6ec..27a2100a2f 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs @@ -20,7 +20,7 @@ internal static class DiagnosticIds public const string AssemblyCleanupShouldBeValidRuleId = "MSTEST0013"; public const string DataRowShouldBeValidRuleId = "MSTEST0014"; public const string TestMethodShouldNotBeIgnoredRuleId = "MSTEST0015"; - public const string TestClassShouldHaveTestMethodRuleId = "MSTEST0016"; + public const string TestClassShouldHaveTestMethodRuleId = "MSTEST0016"; public const string AssertionArgsShouldBePassedInCorrectOrderRuleId = "MSTEST0017"; public const string DynamicDataShouldBeValidRuleId = "MSTEST0018"; public const string PreferTestInitializeOverConstructorRuleId = "MSTEST0019"; diff --git a/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs b/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs index 0c22df2816..33d6339125 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs @@ -20,6 +20,7 @@ internal static class WellKnownTypeNames public const string MicrosoftVisualStudioTestToolsUnitTestingDiscoverInternalsAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.DiscoverInternalsAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingDoNotParallelizeAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.DoNotParallelizeAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingDynamicDataAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataAttribute"; + public const string MicrosoftVisualStudioTestToolsUnitTestingDynamicDataSourceType = "Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataSourceType"; public const string MicrosoftVisualStudioTestToolsUnitTestingExpectedExceptionAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.ExpectedExceptionAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingIgnoreAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.IgnoreAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingInheritanceBehavior = "Microsoft.VisualStudio.TestTools.UnitTesting.InheritanceBehavior"; @@ -43,4 +44,5 @@ internal static class WellKnownTypeNames public const string SystemThreadingTasksTask1 = "System.Threading.Tasks.Task`1"; public const string SystemThreadingTasksValueTask = "System.Threading.Tasks.ValueTask"; public const string SystemThreadingTasksValueTask1 = "System.Threading.Tasks.ValueTask`1"; + public const string SystemType = "System.Type"; } diff --git a/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt b/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt index d885d61e54..b2b161739e 100644 --- a/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt +++ b/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt @@ -1,8 +1,12 @@ #nullable enable +MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer +MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer.DynamicDataShouldBeValidAnalyzer() -> void MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor.NonNullableReferenceNotInitializedSuppressor() -> void MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer.UseClassCleanupBehaviorEndOfClassAnalyzer() -> void +override MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void +override MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray override MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor.ReportSuppressions(Microsoft.CodeAnalysis.Diagnostics.SuppressionAnalysisContext context) -> void override MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor.SupportedSuppressions.get -> System.Collections.Immutable.ImmutableArray override MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void diff --git a/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs b/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs index 35b1a70410..ef35e9dde3 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs +++ b/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs @@ -383,6 +383,72 @@ internal static string DoNotUseSystemDescriptionAttributeTitle { } } + /// + /// Looks up a localized string similar to 'DynamicData' entry should have the following layout to be valid: + ///- should only be set on a test method; + ///- member should be defined on the type specified; + ///- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise.. + /// + internal static string DynamicDataShouldBeValidDescription { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Member '{0}' should be a method. + /// + internal static string DynamicDataShouldBeValidMessageFormat_MemberMethod { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_MemberMethod", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot find member '{0}.{1}'. + /// + internal static string DynamicDataShouldBeValidMessageFormat_MemberNotFound { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_MemberNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Member '{0}' should be a property. + /// + internal static string DynamicDataShouldBeValidMessageFormat_MemberProperty { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_MemberProperty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '[DynamicData]' should only be set on a test method. + /// + internal static string DynamicDataShouldBeValidMessageFormat_OnTestMethod { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_OnTestMethod", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Found more than one member with name '{0}'. + /// + internal static string DynamicDataShouldBeValidMessageFormat_TooManyMembers { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_TooManyMembers", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to DynamicData should be valid. + /// + internal static string DynamicDataShouldBeValidTitle { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidTitle", resourceCulture); + } + } + /// /// Looks up a localized string similar to Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert. /// diff --git a/src/Analyzers/MSTest.Analyzers/Resources.resx b/src/Analyzers/MSTest.Analyzers/Resources.resx index 616d1f480d..ed91a4f515 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.resx +++ b/src/Analyzers/MSTest.Analyzers/Resources.resx @@ -473,4 +473,28 @@ Use 'ClassCleanupBehavior.EndOfClass' with the '[ClassCleanup]' + + DynamicData should be valid + + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + '[DynamicData]' should only be set on a test method + + + Cannot find member '{0}.{1}' + + + Found more than one member with name '{0}' + + + Member '{0}' should be a property + + + Member '{0}' should be a method + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf index 6e4fcc1645..8c6d1cba0d 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf @@ -233,6 +233,47 @@ System.ComponentModel.DescriptionAttribute nemá žádný vliv na testovací metody + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert Místo trvalého neúspěšného vyhodnocovacího výrazu „Assert.{0}“ použijte „Assert.Fail“. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf index 325a0a2f7e..8f25677d90 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf @@ -232,6 +232,47 @@ "System.ComponentModel.DescriptionAttribute" hat keine Auswirkungen auf Testmethoden. + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert Verwenden Sie „Assert.Fail“ anstelle einer Assert-Anweisung „Assert.{0}“, bei der immer ein Fehler auftritt. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf index 17c6fd8f10..6e6b3a7c2a 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf @@ -232,6 +232,47 @@ "System.ComponentModel.DescriptionAttribute" no tiene ningún efecto en los métodos de prueba + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert Usar "Assert.Fail" en lugar de una aserción 'Assert.{0}' que siempre tiene errores diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf index df3c4390fe..172150c07b 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf @@ -232,6 +232,47 @@ « System.ComponentModel.DescriptionAttribute » n’a aucun effet sur les méthodes de test + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert Utilisez « Assert.Fail » à la place d’une assertion « Assert.{0} » toujours en échec diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf index 8617405ea9..1505d41ad6 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf @@ -232,6 +232,47 @@ 'System.ComponentModel.DescriptionAttribute' non ha alcun effetto sui metodi di test. + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert Usare 'Assert.Fail' invece di un'asserzione 'Assert.{0}' che ha sempre esito negativo. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf index 9faf1c9c70..bc7d21bac0 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf @@ -232,6 +232,47 @@ 'System.ComponentModel.DescriptionAttribute' はテスト メソッドに影響しません + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert 常に失敗している 'Assert.{0}' アサートの代わりに 'Assert.Fail' を使用する。 diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf index 9bd270b306..e16a50d0b0 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf @@ -232,6 +232,47 @@ 'System.ComponentModel.DescriptionAttribute'는 테스트 메서드에 영향을 주지 않습니다. + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert 항상 실패하는 'Assert.{0}' 어설션 대신 'Assert.Fail'을 사용합니다. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf index c41173b38e..07a83f1d1a 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf @@ -232,6 +232,47 @@ Element „System.ComponentModel.DescriptionAttribute” nie ma wpływu na metody testowe + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert Użyj trybu „Assert.Fail” zamiast kończącej się zawsze niepowodzeniem instrukcji „Assert.{0}” diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf index 58ec252148..9daba1f517 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf @@ -232,6 +232,47 @@ 'System.ComponentModel.DescriptionAttribute' não tem efeito sobre métodos de teste + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert Use "Assert.Fail" em vez de uma asserção "Assert.{0}" sempre com falha diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf index f60fe00468..5e6d1df9a5 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf @@ -232,6 +232,47 @@ "System.ComponentModel.DescriptionAttribute" не действует на методы тестирования + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert Используйте "Assert.Fail" вместо утверждения с постоянным сбоем "Assert.{0}" diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf index 99b4a5dced..6f74516b11 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf @@ -232,6 +232,47 @@ 'System.ComponentModel.DescriptionAttribute' test yöntemlerini etkilemez + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert Her zaman başarısız olan 'Assert.{0}' onaylaması yerine 'Assert.Fail' seçeneğini kullanın diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf index 6abb53afef..cfe6357b3f 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf @@ -232,6 +232,47 @@ “System.ComponentModel.DescriptionAttribute” 对测试方法没有影响 + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert 使用 “Assert.Fail” 而不是始终失败的 “Assert.{0}” 断言 diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf index 9e7984f1da..130486c480 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf @@ -232,6 +232,47 @@ 'System.ComponentModel.DescriptionAttribute' 對測試方法無影響 + + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + 'DynamicData' entry should have the following layout to be valid: +- should only be set on a test method; +- member should be defined on the type specified; +- member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + + + Member '{0}' should be a method + Member '{0}' should be a method + + + + Cannot find member '{0}.{1}' + Cannot find member '{0}.{1}' + + + + Member '{0}' should be a property + Member '{0}' should be a property + + + + '[DynamicData]' should only be set on a test method + '[DynamicData]' should only be set on a test method + + + + Found more than one member with name '{0}' + Found more than one member with name '{0}' + + + + DynamicData should be valid + DynamicData should be valid + + Use 'Assert.Fail' instead of an always-failing 'Assert.{0}' assert 使用 'Assert.Fail',而不是一直失敗的 'Assert.{0}' 聲明 diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs b/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs index f85c9ba226..9fb85ef9bc 100644 --- a/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs +++ b/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs @@ -1,9 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using Microsoft.Testing.Framework; -using Microsoft.Testing.TestInfrastructure; - using VerifyCS = MSTest.Analyzers.Test.CSharpCodeFixVerifier< MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer, Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; @@ -13,50 +10,260 @@ namespace MSTest.Analyzers.Test; [TestGroup] public sealed class DynamicDataShouldBeValidAnalyzerTests(ITestExecutionContext testExecutionContext) : TestBase(testExecutionContext) { - public async Task WhenDataSourceMemberDoesNotExist_Diagnostic() + public async Task ValidUsages_NoDiagnostic() { - var code = """ + string code = """ + using System; + using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class MyTestClass { - [DynamicData("MemberNotFound")] + [DynamicData("Data")] [TestMethod] public void TestMethod1(object[] o) { } - [DynamicData("MemberNotFound", typeof(SomeClass))] + [DynamicData("SomeData", typeof(SomeClass))] [TestMethod] public void TestMethod2(object[] o) { } - [DynamicData(dynamicDataSourceName: "MemberNotFound")] + [DynamicData(dynamicDataSourceName: "Data")] [TestMethod] public void TestMethod3(object[] o) { } - - [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "MemberNotFound")] + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeData")] [TestMethod] public void TestMethod4(object[] o) { } + + [DynamicData("GetData", DynamicDataSourceType.Method)] + [TestMethod] + public void TestMethod11(object[] o) + { + } + + [DynamicData("GetSomeData", typeof(SomeClass), DynamicDataSourceType.Method)] + [TestMethod] + public void TestMethod12(object[] o) + { + } + + [DynamicData(dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetData")] + [TestMethod] + public void TestMethod13(object[] o) + { + } + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetSomeData")] + [TestMethod] + public void TestMethod14(object[] o) + { + } + + [DynamicData("DataTuple")] + [TestMethod] + public void TestMethod101(int i, string s) + { + } + + [DynamicData("SomeDataTuple", typeof(SomeClass))] + [TestMethod] + public void TestMethod102(int i, string s) + { + } + + [DynamicData(dynamicDataSourceName: "DataTuple")] + [TestMethod] + public void TestMethod103(int i, string s) + { + } + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeDataTuple")] + [TestMethod] + public void TestMethod104(int i, string s) + { + } + + [DynamicData("GetDataTuple", DynamicDataSourceType.Method)] + [TestMethod] + public void TestMethod111(int i, string s) + { + } + + [DynamicData("GetSomeDataTuple", typeof(SomeClass), DynamicDataSourceType.Method)] + [TestMethod] + public void TestMethod112(int i, string s) + { + } + + [DynamicData(dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetDataTuple")] + [TestMethod] + public void TestMethod113(int i, string s) + { + } + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetSomeDataTuple")] + [TestMethod] + public void TestMethod114(int i, string s) + { + } + + [DynamicData("DataValueTuple")] + [TestMethod] + public void TestMethod201(int i, string s) + { + } + + [DynamicData("SomeDataValueTuple", typeof(SomeClass))] + [TestMethod] + public void TestMethod202(int i, string s) + { + } + + [DynamicData(dynamicDataSourceName: "DataValueTuple")] + [TestMethod] + public void TestMethod203(int i, string s) + { + } + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeDataValueTuple")] + [TestMethod] + public void TestMethod204(int i, string s) + { + } + + [DynamicData("GetDataValueTuple", DynamicDataSourceType.Method)] + [TestMethod] + public void TestMethod211(int i, string s) + { + } + + [DynamicData("GetSomeDataValueTuple", typeof(SomeClass), DynamicDataSourceType.Method)] + [TestMethod] + public void TestMethod212(int i, string s) + { + } + + [DynamicData(dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetDataValueTuple")] + [TestMethod] + public void TestMethod213(int i, string s) + { + } + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetSomeDataValueTuple")] + [TestMethod] + public void TestMethod214(int i, string s) + { + } + + public static IEnumerable Data => new List(); + public static IEnumerable> DataTuple => new List>(); + public static IEnumerable<(int, string)> DataValueTuple => new List<(int, string)>(); + public static IEnumerable GetData() => new List(); + public static IEnumerable> GetDataTuple() => new List>(); + public static IEnumerable<(int, string)> GetDataValueTuple() => new List<(int, string)>(); } public class SomeClass { + public static IEnumerable SomeData => new List(); + public static IEnumerable> SomeDataTuple => new List>(); + public static IEnumerable<(int, string)> SomeDataValueTuple => new List<(int, string)>(); + public static IEnumerable GetSomeData() => new List(); + public static IEnumerable> GetSomeDataTuple() => new List>(); + public static IEnumerable<(int, string)> GetSomeDataValueTuple() => new List<(int, string)>(); } """; await VerifyCS.VerifyAnalyzerAsync(code); } + public async Task WhenDataSourceMemberDoesNotExist_Diagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("MemberNotFound")|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("MemberNotFound", typeof(SomeClass))|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [{|#2:DynamicData(dynamicDataSourceName: "MemberNotFound")|}] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [{|#3:DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "MemberNotFound")|}] + [TestMethod] + public void TestMethod4(object[] o) + { + } + + [{|#4:DynamicData("MemberNotFound", DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod11(object[] o) + { + } + + [{|#5:DynamicData("MemberNotFound", typeof(SomeClass), DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod12(object[] o) + { + } + + [{|#6:DynamicData(dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "MemberNotFound")|}] + [TestMethod] + public void TestMethod13(object[] o) + { + } + + [{|#7:DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "MemberNotFound")|}] + [TestMethod] + public void TestMethod14(object[] o) + { + } + } + + public class SomeClass + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(0).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(1).WithArguments("SomeClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(2).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(3).WithArguments("SomeClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(4).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(5).WithArguments("SomeClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(6).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(7).WithArguments("SomeClass", "MemberNotFound")); + } + + /* public async Task WhenDataDisplayMemberDoesNotExist_Diagnostic() { - var code = """ + string code = """ using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] @@ -67,26 +274,26 @@ public class MyTestClass public void TestMethod1(object[] o) { } - + [DynamicData("SomeProperty", typeof(SomeClass))] [TestMethod] public void TestMethod2(object[] o) { } - + [DynamicData(dynamicDataSourceName: "SomeProperty")] [TestMethod] public void TestMethod3(object[] o) { } - + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeProperty")] [TestMethod] public void TestMethod4(object[] o) { } } - + public class SomeClass { public static IEnumerable SomeProperty { get; set; } @@ -95,41 +302,259 @@ public class SomeClass await VerifyCS.VerifyAnalyzerAsync(code); } + */ public async Task WhenAppliedToNonTestMethod_Diagnostic() { - var code = """ + string code = """ using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class MyTestClass { [DynamicData("SomeProperty")] - public void TestMethod1(object[] o) + public void {|#0:TestMethod1|}(object[] o) { } - + [DynamicData("SomeProperty", typeof(SomeClass))] - public void TestMethod2(object[] o) + public void {|#1:TestMethod2|}(object[] o) { } - + [DynamicData(dynamicDataSourceName: "SomeProperty")] - public void TestMethod3(object[] o) + public void {|#2:TestMethod3|}(object[] o) { } - + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeProperty")] + public void {|#3:TestMethod4|}(object[] o) + { + } + } + + public class SomeClass + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.NotTestMethodRule).WithLocation(0), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.NotTestMethodRule).WithLocation(1), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.NotTestMethodRule).WithLocation(2), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.NotTestMethodRule).WithLocation(3)); + } + + public async Task WhenDataSourceMemberFoundMultipleTimes_Diagnostic() + { + string code = """ + using System.Collections.Generic; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("GetData", DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("GetSomeData", typeof(SomeClass), DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [{|#2:DynamicData(dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetData")|}] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [{|#3:DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetSomeData")|}] + [TestMethod] public void TestMethod4(object[] o) { } + + public static IEnumerable GetData() => new List(); + public static IEnumerable GetData(int i) => new List(); } public class SomeClass { + public static IEnumerable GetSomeData() => new List(); + public static IEnumerable GetSomeData(int i) => new List(); } """; - await VerifyCS.VerifyAnalyzerAsync(code); + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.FoundTooManyMembersRule).WithLocation(0).WithArguments("MyTestClass", "GetData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.FoundTooManyMembersRule).WithLocation(1).WithArguments("SomeClass", "GetSomeData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.FoundTooManyMembersRule).WithLocation(2).WithArguments("MyTestClass", "GetData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.FoundTooManyMembersRule).WithLocation(3).WithArguments("SomeClass", "GetSomeData")); + } + + public async Task WhenMemberKindIsMixedUp_Diagnostic() + { + string code = """ + using System.Collections.Generic; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("GetData")|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("GetSomeData", typeof(SomeClass))|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [{|#2:DynamicData(dynamicDataSourceName: "GetData")|}] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [{|#3:DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "GetSomeData")|}] + [TestMethod] + public void TestMethod4(object[] o) + { + } + + [{|#4:DynamicData("Data", DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod11(object[] o) + { + } + + [{|#5:DynamicData("SomeData", typeof(SomeClass), DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod12(object[] o) + { + } + + [{|#6:DynamicData(dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "Data")|}] + [TestMethod] + public void TestMethod13(object[] o) + { + } + + [{|#7:DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "SomeData")|}] + [TestMethod] + public void TestMethod14(object[] o) + { + } + + public static IEnumerable Data => new List(); + public static IEnumerable GetData() => new List(); + } + + public class SomeClass + { + public static IEnumerable SomeData => new List(); + public static IEnumerable GetSomeData() => new List(); + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(0).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(1).WithArguments("SomeClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(2).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(3).WithArguments("SomeClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(4).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(5).WithArguments("SomeClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(6).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(7).WithArguments("SomeClass", "MemberNotFound")); + } + + public async Task WhenDataSourceReturnTypeIsInvalid_Diagnostic() + { + string code = """ + using System.Collections.Generic; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("Data")|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("SomeData", typeof(SomeClass))|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [{|#2:DynamicData(dynamicDataSourceName: "Data")|}] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [{|#3:DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeData")|}] + [TestMethod] + public void TestMethod4(object[] o) + { + } + + [{|#4:DynamicData("GetData", DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod11(object[] o) + { + } + + [{|#5:DynamicData("GetSomeData", typeof(SomeClass), DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod12(object[] o) + { + } + + [{|#6:DynamicData(dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetData")|}] + [TestMethod] + public void TestMethod13(object[] o) + { + } + + [{|#7:DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetSomeData")|}] + [TestMethod] + public void TestMethod14(object[] o) + { + } + + public static IEnumerable Data => new List(); + public static IEnumerable GetData() => new List(); + } + + public class SomeClass + { + public static IEnumerable SomeData => new List(); + public static IEnumerable GetSomeData() => new List(); + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(0).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(1).WithArguments("SomeClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(2).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(3).WithArguments("SomeClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(4).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(5).WithArguments("SomeClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(6).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(7).WithArguments("SomeClass", "MemberNotFound")); } } From cdb74627bda50ff5b57140858c14a158b3374d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Wed, 31 Jul 2024 15:03:50 +0200 Subject: [PATCH 3/3] Finish analyzer --- .../Resources/Resource.Designer.cs | 9 + .../Resources/Resource.resx | 3 + .../Resources/xlf/Resource.cs.xlf | 5 + .../Resources/xlf/Resource.de.xlf | 5 + .../Resources/xlf/Resource.es.xlf | 5 + .../Resources/xlf/Resource.fr.xlf | 5 + .../Resources/xlf/Resource.it.xlf | 5 + .../Resources/xlf/Resource.ja.xlf | 5 + .../Resources/xlf/Resource.ko.xlf | 5 + .../Resources/xlf/Resource.pl.xlf | 5 + .../Resources/xlf/Resource.pt-BR.xlf | 5 + .../Resources/xlf/Resource.ru.xlf | 5 + .../Resources/xlf/Resource.tr.xlf | 5 + .../Resources/xlf/Resource.zh-Hans.xlf | 5 + .../Resources/xlf/Resource.zh-Hant.xlf | 5 + .../DynamicDataShouldBeValidAnalyzer.cs | 165 ++++- .../Helpers/WellKnownTypeNames.cs | 3 + .../MSTest.Analyzers/Resources.Designer.cs | 48 +- src/Analyzers/MSTest.Analyzers/Resources.resx | 22 +- .../ISymbolExtensions.cs | 10 + .../MSTest.Analyzers/xlf/Resources.cs.xlf | 38 +- .../MSTest.Analyzers/xlf/Resources.de.xlf | 38 +- .../MSTest.Analyzers/xlf/Resources.es.xlf | 38 +- .../MSTest.Analyzers/xlf/Resources.fr.xlf | 38 +- .../MSTest.Analyzers/xlf/Resources.it.xlf | 38 +- .../MSTest.Analyzers/xlf/Resources.ja.xlf | 38 +- .../MSTest.Analyzers/xlf/Resources.ko.xlf | 38 +- .../MSTest.Analyzers/xlf/Resources.pl.xlf | 38 +- .../MSTest.Analyzers/xlf/Resources.pt-BR.xlf | 38 +- .../MSTest.Analyzers/xlf/Resources.ru.xlf | 38 +- .../MSTest.Analyzers/xlf/Resources.tr.xlf | 38 +- .../xlf/Resources.zh-Hans.xlf | 38 +- .../xlf/Resources.zh-Hant.xlf | 38 +- .../DynamicDataShouldBeValidAnalyzerTests.cs | 605 ++++++++++++++++-- .../Properties/launchSettings.json | 2 +- 35 files changed, 1223 insertions(+), 203 deletions(-) diff --git a/src/Adapter/MSTest.TestAdapter/Resources/Resource.Designer.cs b/src/Adapter/MSTest.TestAdapter/Resources/Resource.Designer.cs index 5e11ba0cd9..56747b3a70 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/Resource.Designer.cs +++ b/src/Adapter/MSTest.TestAdapter/Resources/Resource.Designer.cs @@ -233,6 +233,15 @@ internal static string DiscoveryWarning { } } + /// + /// Looks up a localized string similar to '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'. + /// + internal static string DynamicDataShouldBeValidMessageFormat_MemberType { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_MemberType", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0}: {1}. /// diff --git a/src/Adapter/MSTest.TestAdapter/Resources/Resource.resx b/src/Adapter/MSTest.TestAdapter/Resources/Resource.resx index 853a61ef72..45c9e6fccd 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/Resource.resx +++ b/src/Adapter/MSTest.TestAdapter/Resources/Resource.resx @@ -410,4 +410,7 @@ but received {4} argument(s), with types '{5}'. Invalid value '{0}' for runsettings entry '{1}', setting will be ignored. + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + \ No newline at end of file diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.cs.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.cs.xlf index 8fb9527977..3851b7b9e4 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.cs.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.cs.xlf @@ -56,6 +56,11 @@ byl však přijat tento počet argumentů: {4} s typy {5}. Metoda inicializace třídy {0}.{1} byla zrušena. + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. Test {0} překročil časový limit spuštění. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.de.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.de.xlf index acde5e650d..969028d7aa 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.de.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.de.xlf @@ -56,6 +56,11 @@ aber empfing {4} Argument(e) mit den Typen „{5}“. Die Initialisierungsmethode "{0}.{1}" der Klasse wurde abgebrochen + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. Der Test "{0}" hat das Ausführungstimeout überschritten. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.es.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.es.xlf index 44828f4b3a..241ecfdbac 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.es.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.es.xlf @@ -56,6 +56,11 @@ pero recibió {4} argumento(s), con los tipos "{5}". Método de inicialización de clase "{0}.{1}" se canceló + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. La prueba '{0}' superó el tiempo de espera de ejecución. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.fr.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.fr.xlf index 08502ecd1e..2aac86439b 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.fr.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.fr.xlf @@ -56,6 +56,11 @@ mais a reçu {4} argument(s), avec les types « {5} ». La méthode d’initialisation de la classe « {0}.{1} » a été annulée + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. Le test '{0}' a dépassé le délai d'attente de l'exécution. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.it.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.it.xlf index 6ac071f098..027721cf2e 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.it.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.it.xlf @@ -56,6 +56,11 @@ ma ha ricevuto {4} argomenti, con tipi "{5}". Il metodo di inizializzazione della classe "{0}.{1}" è stato annullato + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. È stato superato il periodo di timeout per l'esecuzione del test '{0}'. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ja.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ja.xlf index fe13028429..fbf42a14e5 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ja.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ja.xlf @@ -57,6 +57,11 @@ but received {4} argument(s), with types '{5}'. クラス初期化メソッド '{0}.{1}' が取り消されました + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. テスト '{0}' は実行タイムアウトを超えました。 diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ko.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ko.xlf index c965962d23..1699ee8195 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ko.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ko.xlf @@ -56,6 +56,11 @@ but received {4} argument(s), with types '{5}'. '클래스 초기화 메서드 '{0}.{1}'이(가) 취소되었습니다. + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. '{0}' 테스트가 실행 시간 제한을 초과했습니다. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pl.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pl.xlf index 8320bc8b02..aeafac2cc1 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pl.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pl.xlf @@ -56,6 +56,11 @@ ale liczba odebranych argumentów to {4} z typami „{5}”. Anulowano metodę inicjowania klasy „{0}.{1}” + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. Test „{0}” przekroczył okres limitu czasu na wykonanie. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pt-BR.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pt-BR.xlf index 3f55f129c1..16620cf870 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pt-BR.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pt-BR.xlf @@ -56,6 +56,11 @@ mas {4} argumentos recebidos, com tipos '{5}'. O método de inicialização de classe "{0}.{1}" foi cancelado + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. Teste '{0}' ultrapassou o período de tempo limite de execução. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ru.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ru.xlf index 9fcf17b436..d62597b66f 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ru.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ru.xlf @@ -56,6 +56,11 @@ but received {4} argument(s), with types '{5}'. Метод инициализации класса "{0}.{1}" отменен + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. Превышено время ожидания выполнения теста "{0}". diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.tr.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.tr.xlf index 4d31497323..4f9172d26e 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.tr.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.tr.xlf @@ -56,6 +56,11 @@ ancak, '{5}' türüyle {4} argüman aldı. '{0}.{1}' sınıf başlatma yöntemi iptal edildi + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. '{0}' testi yürütme zaman aşımı süresini aştı. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hans.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hans.xlf index d698e894d1..31e2e657af 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hans.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hans.xlf @@ -56,6 +56,11 @@ but received {4} argument(s), with types '{5}'. 已取消类初始化方法“{0}.{1}” + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. 测试“{0}”的执行超时。 diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hant.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hant.xlf index fa47f710de..11605fc573 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hant.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hant.xlf @@ -56,6 +56,11 @@ but received {4} argument(s), with types '{5}'. 已取消類別初始化方法 '{0}.{1}' + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + Test '{0}' exceeded execution timeout period. 測試 '{0}' 超過執行逾時期限。 diff --git a/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs index ec82a88a55..ec3599737a 100644 --- a/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs +++ b/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs @@ -15,6 +15,9 @@ namespace MSTest.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] public sealed class DynamicDataShouldBeValidAnalyzer : DiagnosticAnalyzer { + private const int DynamicDataSourceTypeProperty = 0; + private const int DynamicDataSourceTypeMethod = 1; + private static readonly LocalizableResourceString Title = new(nameof(Resources.DynamicDataShouldBeValidTitle), Resources.ResourceManager, typeof(Resources)); private static readonly LocalizableResourceString Description = new(nameof(Resources.DynamicDataShouldBeValidDescription), Resources.ResourceManager, typeof(Resources)); private static readonly LocalizableResourceString MessageFormat = new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_OnTestMethod), Resources.ResourceManager, typeof(Resources)); @@ -34,12 +37,24 @@ public sealed class DynamicDataShouldBeValidAnalyzer : DiagnosticAnalyzer internal static readonly DiagnosticDescriptor FoundTooManyMembersRule = NotTestMethodRule .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_TooManyMembers), Resources.ResourceManager, typeof(Resources))); - internal static readonly DiagnosticDescriptor MemberPropertyRule = NotTestMethodRule - .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_MemberProperty), Resources.ResourceManager, typeof(Resources))); + internal static readonly DiagnosticDescriptor SourceTypePropertyRule = NotTestMethodRule + .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_SourceTypeProperty), Resources.ResourceManager, typeof(Resources))); + + internal static readonly DiagnosticDescriptor SourceTypeMethodRule = NotTestMethodRule + .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_SourceTypeMethod), Resources.ResourceManager, typeof(Resources))); internal static readonly DiagnosticDescriptor MemberMethodRule = NotTestMethodRule .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_MemberMethod), Resources.ResourceManager, typeof(Resources))); + internal static readonly DiagnosticDescriptor MemberTypeRule = NotTestMethodRule + .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_MemberType), Resources.ResourceManager, typeof(Resources))); + + internal static readonly DiagnosticDescriptor DataMemberSignatureRule = NotTestMethodRule + .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_DataMemberSignature), Resources.ResourceManager, typeof(Resources))); + + internal static readonly DiagnosticDescriptor DisplayMethodSignatureRule = NotTestMethodRule + .WithMessage(new(nameof(Resources.DynamicDataShouldBeValidMessageFormat_DisplayMethodSignature), Resources.ResourceManager, typeof(Resources))); + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(NotTestMethodRule); @@ -52,16 +67,22 @@ public override void Initialize(AnalysisContext context) { if (context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingTestMethodAttribute, out INamedTypeSymbol? testMethodAttributeSymbol) && context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingDynamicDataAttribute, out INamedTypeSymbol? dynamicDataAttributeSymbol) - && context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingDynamicDataSourceType, out INamedTypeSymbol? dynamicDataSourceTypeSymbol)) + && context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingDynamicDataSourceType, out INamedTypeSymbol? dynamicDataSourceTypeSymbol) + && context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIEnumerable1, out INamedTypeSymbol? ienumerableTypeSymbol) + && context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeCompilerServicesITuple, out INamedTypeSymbol? itupleTypeSymbol) + && context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemReflectionMethodInfo, out INamedTypeSymbol? methodInfoTypeSymbol)) { context.RegisterSymbolAction( - context => AnalyzeSymbol(context, testMethodAttributeSymbol, dynamicDataAttributeSymbol, dynamicDataSourceTypeSymbol), + context => AnalyzeSymbol(context, testMethodAttributeSymbol, dynamicDataAttributeSymbol, dynamicDataSourceTypeSymbol, + ienumerableTypeSymbol, itupleTypeSymbol, methodInfoTypeSymbol), SymbolKind.Method); } }); } - private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol testMethodAttributeSymbol, INamedTypeSymbol dynamicDataAttributeSymbol, INamedTypeSymbol dynamicDataSourceTypeSymbol) + private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol testMethodAttributeSymbol, + INamedTypeSymbol dynamicDataAttributeSymbol, INamedTypeSymbol dynamicDataSourceTypeSymbol, INamedTypeSymbol ienumerableTypeSymbol, + INamedTypeSymbol itupleTypeSymbol, INamedTypeSymbol methodInfoTypeSymbol) { var methodSymbol = (IMethodSymbol)context.Symbol; @@ -96,11 +117,28 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo // Check each data row attribute. foreach (AttributeData attribute in dynamicDataAttributes) { - AnalyzeAttribute(context, attribute, methodSymbol, dynamicDataSourceTypeSymbol); + AnalyzeAttribute(context, attribute, methodSymbol, dynamicDataSourceTypeSymbol, ienumerableTypeSymbol, itupleTypeSymbol, + methodInfoTypeSymbol); + } + } + + private static void AnalyzeAttribute(SymbolAnalysisContext context, AttributeData attributeData, IMethodSymbol methodSymbol, + INamedTypeSymbol dynamicDataSourceTypeSymbol, INamedTypeSymbol ienumerableTypeSymbol, INamedTypeSymbol itupleTypeSymbol, + INamedTypeSymbol methodInfoTypeSymbol) + { + if (attributeData.ApplicationSyntaxReference?.GetSyntax() is not { } attributeSyntax) + { + return; } + + AnalyzeDataSource(context, attributeData, attributeSyntax, methodSymbol, dynamicDataSourceTypeSymbol, ienumerableTypeSymbol, + itupleTypeSymbol); + AnalyzeDisplayNameSource(context, attributeData, attributeSyntax, methodSymbol, methodInfoTypeSymbol); } - private static void AnalyzeAttribute(SymbolAnalysisContext context, AttributeData attributeData, IMethodSymbol methodSymbol, INamedTypeSymbol dynamicDataSourceTypeSymbol) + private static void AnalyzeDataSource(SymbolAnalysisContext context, AttributeData attributeData, SyntaxNode attributeSyntax, + IMethodSymbol methodSymbol, INamedTypeSymbol dynamicDataSourceTypeSymbol, INamedTypeSymbol ienumerableTypeSymbol, + INamedTypeSymbol itupleTypeSymbol) { string? memberName = null; int dataSourceType = 0; @@ -129,8 +167,7 @@ private static void AnalyzeAttribute(SymbolAnalysisContext context, AttributeDat } // If the member name is not available, bail out. - if (memberName is null - || attributeData.ApplicationSyntaxReference?.GetSyntax() is not { } attributeSyntax) + if (memberName is null) { return; } @@ -149,21 +186,121 @@ private static void AnalyzeAttribute(SymbolAnalysisContext context, AttributeDat return; } + ISymbol member = potentialMembers[0]; + // If the member is a property and the data source type is not set to property, report a diagnostic. - if (potentialMembers[0].Kind == SymbolKind.Property && dataSourceType is not 0) + if (member.Kind == SymbolKind.Property && dataSourceType is not DynamicDataSourceTypeProperty) { - context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberPropertyRule, declaringType.Name, memberName)); + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(SourceTypePropertyRule, declaringType.Name, memberName)); return; } // If the member is a method and the data source type is not set to method, report a diagnostic. - if (potentialMembers[0].Kind == SymbolKind.Method && dataSourceType is not 1) + if (member.Kind == SymbolKind.Method && dataSourceType is not DynamicDataSourceTypeMethod) { - context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberMethodRule, declaringType.Name, memberName)); + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(SourceTypeMethodRule, declaringType.Name, memberName)); + return; + } + + if (!member.IsStatic + || member.DeclaredAccessibility != Accessibility.Public) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(DataMemberSignatureRule, declaringType.Name, memberName)); + return; + } + + if (member.Kind == SymbolKind.Method + && member is IMethodSymbol method + && (method.IsGenericMethod || method.Parameters.Length != 0)) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(DataMemberSignatureRule, declaringType.Name, memberName)); return; } // Validate member return type. - var a = 1; + if (member.GetMemberType() is not INamedTypeSymbol memberType) + { + return; + } + + if (!SymbolEqualityComparer.Default.Equals(memberType.ConstructedFrom, ienumerableTypeSymbol) + || memberType.TypeArguments.Length != 1) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberTypeRule, declaringType.Name, memberName)); + return; + } + + ITypeSymbol collectionBoundType = memberType.TypeArguments[0]; + if (!collectionBoundType.Inherits(itupleTypeSymbol) + && (collectionBoundType is not IArrayTypeSymbol arrayTypeSymbol || arrayTypeSymbol.ElementType.SpecialType != SpecialType.System_Object)) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberTypeRule, declaringType.Name, memberName)); + } + } + + private static void AnalyzeDisplayNameSource(SymbolAnalysisContext context, AttributeData attributeData, SyntaxNode attributeSyntax, + IMethodSymbol methodSymbol, INamedTypeSymbol methodInfoTypeSymbol) + { + string? memberName = null; + INamedTypeSymbol declaringType = methodSymbol.ContainingType; + foreach (KeyValuePair namedArgument in attributeData.NamedArguments) + { + if (namedArgument.Value.Type is null) + { + continue; + } + + if (namedArgument.Key == "DynamicDataDisplayName" + && namedArgument.Value.Value is string name) + { + memberName = name; + } + else if (namedArgument.Key == "DynamicDataDisplayNameDeclaringType" + && namedArgument.Value.Value is INamedTypeSymbol type) + { + declaringType = type; + } + } + + // If the member name is not available, bail out. + if (memberName is null) + { + return; + } + + // If we cannot find the member on the given type, report a diagnostic. + if (declaringType.GetMembers(memberName) is { Length: 0 } potentialMembers) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberNotFoundRule, declaringType.Name, memberName)); + return; + } + + // If there are multiple members with the same name, report a diagnostic. This is not a supported scenario. + if (potentialMembers.Length > 1) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(FoundTooManyMembersRule, declaringType.Name, memberName)); + return; + } + + ISymbol member = potentialMembers[0]; + + if (member is not IMethodSymbol displayNameMethod) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberMethodRule, declaringType.Name, memberName)); + return; + } + + // Validate signature + if (!displayNameMethod.IsStatic + || displayNameMethod.DeclaredAccessibility != Accessibility.Public + || displayNameMethod.ReturnType.SpecialType != SpecialType.System_String + || displayNameMethod.Parameters.Length != 2 + || !SymbolEqualityComparer.Default.Equals(displayNameMethod.Parameters[0].Type, methodInfoTypeSymbol) + || displayNameMethod.Parameters[1].Type is not IArrayTypeSymbol arrayTypeSymbol + || arrayTypeSymbol.ElementType.SpecialType != SpecialType.System_Object) + { + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(DisplayMethodSignatureRule, declaringType.Name, memberName)); + return; + } } } diff --git a/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs b/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs index 33d6339125..93405b75eb 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs @@ -36,10 +36,13 @@ internal static class WellKnownTypeNames public const string MicrosoftVisualStudioTestToolsUnitTestingTestPropertyAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingWorkItemAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.WorkItemAttribute"; + public const string SystemCollectionsGenericIEnumerable1 = "System.Collections.Generic.IEnumerable`1"; public const string SystemDescriptionAttribute = "System.ComponentModel.DescriptionAttribute"; public const string SystemIAsyncDisposable = "System.IAsyncDisposable"; public const string SystemIDisposable = "System.IDisposable"; public const string SystemNullable = "System.Nullable`1"; + public const string SystemReflectionMethodInfo = "System.Reflection.MethodInfo"; + public const string SystemRuntimeCompilerServicesITuple = "System.Runtime.CompilerServices.ITuple"; public const string SystemThreadingTasksTask = "System.Threading.Tasks.Task"; public const string SystemThreadingTasksTask1 = "System.Threading.Tasks.Task`1"; public const string SystemThreadingTasksValueTask = "System.Threading.Tasks.ValueTask"; diff --git a/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs b/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs index ef35e9dde3..7cc307b2d9 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs +++ b/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs @@ -396,7 +396,25 @@ internal static string DynamicDataShouldBeValidDescription { } /// - /// Looks up a localized string similar to Member '{0}' should be a method. + /// Looks up a localized string similar to '[DynamicData]' data member '{0}.{1}' signature is invalid. + /// + internal static string DynamicDataShouldBeValidMessageFormat_DataMemberSignature { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_DataMemberSignature", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '[DynamicData]' display name method '{0}.{1}' signature is invalid. + /// + internal static string DynamicDataShouldBeValidMessageFormat_DisplayMethodSignature { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_DisplayMethodSignature", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '[DynamicData]' member '{0}.{1}' should be a method. /// internal static string DynamicDataShouldBeValidMessageFormat_MemberMethod { get { @@ -405,7 +423,7 @@ internal static string DynamicDataShouldBeValidMessageFormat_MemberMethod { } /// - /// Looks up a localized string similar to Cannot find member '{0}.{1}'. + /// Looks up a localized string similar to '[DynamicData]' member '{0}.{1}' cannot be found. /// internal static string DynamicDataShouldBeValidMessageFormat_MemberNotFound { get { @@ -414,11 +432,11 @@ internal static string DynamicDataShouldBeValidMessageFormat_MemberNotFound { } /// - /// Looks up a localized string similar to Member '{0}' should be a property. + /// Looks up a localized string similar to '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'. /// - internal static string DynamicDataShouldBeValidMessageFormat_MemberProperty { + internal static string DynamicDataShouldBeValidMessageFormat_MemberType { get { - return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_MemberProperty", resourceCulture); + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_MemberType", resourceCulture); } } @@ -432,7 +450,25 @@ internal static string DynamicDataShouldBeValidMessageFormat_OnTestMethod { } /// - /// Looks up a localized string similar to Found more than one member with name '{0}'. + /// Looks up a localized string similar to '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method'. + /// + internal static string DynamicDataShouldBeValidMessageFormat_SourceTypeMethod { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_SourceTypeMethod", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property'. + /// + internal static string DynamicDataShouldBeValidMessageFormat_SourceTypeProperty { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_SourceTypeProperty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '[DynamicDta]' member '{0}.{1}' is found more than once. /// internal static string DynamicDataShouldBeValidMessageFormat_TooManyMembers { get { diff --git a/src/Analyzers/MSTest.Analyzers/Resources.resx b/src/Analyzers/MSTest.Analyzers/Resources.resx index ed91a4f515..46bd6d16e8 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.resx +++ b/src/Analyzers/MSTest.Analyzers/Resources.resx @@ -486,15 +486,27 @@ '[DynamicData]' should only be set on a test method - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once - - Member '{0}' should be a property + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + + '[DynamicData]' data member '{0}.{1}' signature is invalid \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/RoslynAnalyzerHelpers/ISymbolExtensions.cs b/src/Analyzers/MSTest.Analyzers/RoslynAnalyzerHelpers/ISymbolExtensions.cs index b9c3726558..312037e727 100644 --- a/src/Analyzers/MSTest.Analyzers/RoslynAnalyzerHelpers/ISymbolExtensions.cs +++ b/src/Analyzers/MSTest.Analyzers/RoslynAnalyzerHelpers/ISymbolExtensions.cs @@ -54,5 +54,15 @@ public static SymbolVisibility GetResultantVisibility(this ISymbol symbol) return visibility; } + + public static ITypeSymbol? GetMemberType(this ISymbol? symbol) + => symbol switch + { + IEventSymbol eventSymbol => eventSymbol.Type, + IFieldSymbol fieldSymbol => fieldSymbol.Type, + IMethodSymbol methodSymbol => methodSymbol.ReturnType, + IPropertySymbol propertySymbol => propertySymbol.Type, + _ => null, + }; } } diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf index 8c6d1cba0d..c6cf16cf8c 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf @@ -244,19 +244,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -264,9 +274,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf index 8f25677d90..09201361db 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf index 6e6b3a7c2a..a02c006027 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf index 172150c07b..ffe525bf1e 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf index 1505d41ad6..7dca58d511 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf index bc7d21bac0..ac52808443 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf index e16a50d0b0..fced30e24e 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf index 07a83f1d1a..57dd847f80 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf index 9daba1f517..d02a257851 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf index 5e6d1df9a5..b8e2c57648 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf index 6f74516b11..b11ad682f7 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf index cfe6357b3f..9eaf90412b 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf index 130486c480..41cf4d6906 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf @@ -243,19 +243,29 @@ - member should be a method if DynamicDataSourceType.Method is specified or a property otherwise. + + '[DynamicData]' data member '{0}.{1}' signature is invalid + '[DynamicData]' data member '{0}.{1}' signature is invalid + + + + '[DynamicData]' display name method '{0}.{1}' signature is invalid + '[DynamicData]' display name method '{0}.{1}' signature is invalid + + - Member '{0}' should be a method - Member '{0}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method - Cannot find member '{0}.{1}' - Cannot find member '{0}.{1}' + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found - - Member '{0}' should be a property - Member '{0}' should be a property + + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' + '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>' @@ -263,9 +273,19 @@ '[DynamicData]' should only be set on a test method + + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + '[DynamicData]' member '{0}.{1}' is a method so you should set 'DynamicDataSourceType.Method' + + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + - Found more than one member with name '{0}' - Found more than one member with name '{0}' + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs b/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs index 9fb85ef9bc..c5967776f1 100644 --- a/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs +++ b/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs @@ -260,50 +260,6 @@ await VerifyCS.VerifyAnalyzerAsync( VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(7).WithArguments("SomeClass", "MemberNotFound")); } - /* - public async Task WhenDataDisplayMemberDoesNotExist_Diagnostic() - { - string code = """ - using Microsoft.VisualStudio.TestTools.UnitTesting; - - [TestClass] - public class MyTestClass - { - [DynamicData("SomeProperty")] - [TestMethod] - public void TestMethod1(object[] o) - { - } - - [DynamicData("SomeProperty", typeof(SomeClass))] - [TestMethod] - public void TestMethod2(object[] o) - { - } - - [DynamicData(dynamicDataSourceName: "SomeProperty")] - [TestMethod] - public void TestMethod3(object[] o) - { - } - - [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeProperty")] - [TestMethod] - public void TestMethod4(object[] o) - { - } - } - - public class SomeClass - { - public static IEnumerable SomeProperty { get; set; } - } - """; - - await VerifyCS.VerifyAnalyzerAsync(code); - } - */ - public async Task WhenAppliedToNonTestMethod_Diagnostic() { string code = """ @@ -468,14 +424,14 @@ public class SomeClass await VerifyCS.VerifyAnalyzerAsync( code, - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(0).WithArguments("MyTestClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(1).WithArguments("SomeClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(2).WithArguments("MyTestClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(3).WithArguments("SomeClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(4).WithArguments("MyTestClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(5).WithArguments("SomeClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(6).WithArguments("MyTestClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(7).WithArguments("SomeClass", "MemberNotFound")); + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.SourceTypeMethodRule).WithLocation(0).WithArguments("MyTestClass", "GetData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.SourceTypeMethodRule).WithLocation(1).WithArguments("SomeClass", "GetSomeData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.SourceTypeMethodRule).WithLocation(2).WithArguments("MyTestClass", "GetData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.SourceTypeMethodRule).WithLocation(3).WithArguments("SomeClass", "GetSomeData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.SourceTypePropertyRule).WithLocation(4).WithArguments("MyTestClass", "Data"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.SourceTypePropertyRule).WithLocation(5).WithArguments("SomeClass", "SomeData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.SourceTypePropertyRule).WithLocation(6).WithArguments("MyTestClass", "Data"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.SourceTypePropertyRule).WithLocation(7).WithArguments("SomeClass", "SomeData")); } public async Task WhenDataSourceReturnTypeIsInvalid_Diagnostic() @@ -548,13 +504,542 @@ public class SomeClass await VerifyCS.VerifyAnalyzerAsync( code, - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(0).WithArguments("MyTestClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(1).WithArguments("SomeClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(2).WithArguments("MyTestClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberMethodRule).WithLocation(3).WithArguments("SomeClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(4).WithArguments("MyTestClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(5).WithArguments("SomeClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(6).WithArguments("MyTestClass", "MemberNotFound"), - VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberPropertyRule).WithLocation(7).WithArguments("SomeClass", "MemberNotFound")); + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberTypeRule).WithLocation(0).WithArguments("MyTestClass", "Data"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberTypeRule).WithLocation(1).WithArguments("SomeClass", "SomeData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberTypeRule).WithLocation(2).WithArguments("MyTestClass", "Data"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberTypeRule).WithLocation(3).WithArguments("SomeClass", "SomeData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberTypeRule).WithLocation(4).WithArguments("MyTestClass", "GetData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberTypeRule).WithLocation(5).WithArguments("SomeClass", "GetSomeData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberTypeRule).WithLocation(6).WithArguments("MyTestClass", "GetData"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberTypeRule).WithLocation(7).WithArguments("SomeClass", "GetSomeData")); + } + + public async Task MemberIsNotStatic_Diagnostic() + { + string code = """ + using System; + using System.Collections.Generic; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("Data")|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("GetData", DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + public IEnumerable Data => new List(); + public IEnumerable GetData() => new List(); + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DataMemberSignatureRule).WithLocation(0).WithArguments("MyTestClass", "Data"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DataMemberSignatureRule).WithLocation(1).WithArguments("MyTestClass", "GetData")); + } + + public async Task MemberIsNotPublic_Diagnostic() + { + string code = """ + using System; + using System.Collections.Generic; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("Data")|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("GetData", DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + private static IEnumerable Data => new List(); + private static IEnumerable GetData() => new List(); + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DataMemberSignatureRule).WithLocation(0).WithArguments("MyTestClass", "Data"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DataMemberSignatureRule).WithLocation(1).WithArguments("MyTestClass", "GetData")); + } + + public async Task MethodHasParameters_Diagnostic() + { + string code = """ + using System; + using System.Collections.Generic; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("GetData1", DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("GetData2", DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + public static IEnumerable GetData1(int i) => new List(); + public static IEnumerable GetData2(string s) => new List(); + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DataMemberSignatureRule).WithLocation(0).WithArguments("MyTestClass", "GetData1"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DataMemberSignatureRule).WithLocation(1).WithArguments("MyTestClass", "GetData2")); + } + + public async Task MethodIsGeneric_Diagnostic() + { + string code = """ + using System; + using System.Collections.Generic; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("GetData", DynamicDataSourceType.Method)|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + public static IEnumerable GetData() => new List(); + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DataMemberSignatureRule).WithLocation(0).WithArguments("MyTestClass", "GetData")); + } + + public async Task WhenDisplayMemberIsValid_NoDiagnostic() + { + string code = """ + using System.Collections.Generic; + using System.Reflection; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [DynamicData("Property", DynamicDataDisplayName = "GetDisplayName")] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetDisplayName")] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [DynamicData("Property", DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))] + [TestMethod] + public void TestMethod4(object[] o) + { + } + + [DynamicData(dynamicDataSourceName: "Property", DynamicDataDisplayName = "GetDisplayName")] + [TestMethod] + public void TestMethod5(object[] o) + { + } + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeProperty", DynamicDataDisplayName = "GetDisplayName")] + [TestMethod] + public void TestMethod6(object[] o) + { + } + + [DynamicData(dynamicDataSourceName: "Property", DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))] + [TestMethod] + public void TestMethod7(object[] o) + { + } + + [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeProperty", DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))] + [TestMethod] + public void TestMethod8(object[] o) + { + } + + public static IEnumerable Property => new List(); + + public static string GetDisplayName(MethodInfo methodInfo, object[] data) => null; + } + + public class SomeClass + { + public static IEnumerable SomeProperty => new List(); + + public static string GetSomeDisplayName(MethodInfo methodInfo, object[] data) => null; + } + """; + + await VerifyCS.VerifyAnalyzerAsync(code); + } + + public async Task WhenDisplayMemberIsNotFound_Diagnostic() + { + string code = """ + using System.Collections.Generic; + using System.Reflection; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("Property", DynamicDataDisplayName = "MemberNotFound")|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "MemberNotFound")|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [{|#2:DynamicData("Property", DynamicDataDisplayName = "MemberNotFound", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [{|#3:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "MemberNotFound", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod4(object[] o) + { + } + + public static IEnumerable Property => new List(); + } + + public class SomeClass + { + public static IEnumerable SomeProperty => new List(); + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(0).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(1).WithArguments("MyTestClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(2).WithArguments("SomeClass", "MemberNotFound"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.MemberNotFoundRule).WithLocation(3).WithArguments("SomeClass", "MemberNotFound")); + } + + public async Task WhenDisplayMemberIsNotPublic_Diagnostic() + { + string code = """ + using System.Collections.Generic; + using System.Reflection; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("Property", DynamicDataDisplayName = "GetDisplayName")|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetDisplayName")|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [{|#2:DynamicData("Property", DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [{|#3:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod4(object[] o) + { + } + + public static IEnumerable Property => new List(); + + private static string GetDisplayName(MethodInfo methodInfo, object[] data) => null; + } + + public class SomeClass + { + public static IEnumerable SomeProperty => new List(); + + private static string GetSomeDisplayName(MethodInfo methodInfo, object[] data) => null; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(0).WithArguments("MyTestClass", "GetDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(1).WithArguments("MyTestClass", "GetDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(2).WithArguments("SomeClass", "GetSomeDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(3).WithArguments("SomeClass", "GetSomeDisplayName")); + } + + public async Task WhenDisplayMemberIsNotStatic_Diagnostic() + { + string code = """ + using System.Collections.Generic; + using System.Reflection; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("Property", DynamicDataDisplayName = "GetDisplayName")|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetDisplayName")|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [{|#2:DynamicData("Property", DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [{|#3:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod4(object[] o) + { + } + + public static IEnumerable Property => new List(); + + public string GetDisplayName(MethodInfo methodInfo, object[] data) => null; + } + + public class SomeClass + { + public static IEnumerable SomeProperty => new List(); + + public string GetSomeDisplayName(MethodInfo methodInfo, object[] data) => null; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(0).WithArguments("MyTestClass", "GetDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(1).WithArguments("MyTestClass", "GetDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(2).WithArguments("SomeClass", "GetSomeDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(3).WithArguments("SomeClass", "GetSomeDisplayName")); + } + + public async Task WhenDisplayMemberDoesNotReturnString_Diagnostic() + { + string code = """ + using System.Collections.Generic; + using System.Reflection; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("Property", DynamicDataDisplayName = "GetDisplayName")|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetDisplayName")|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [{|#2:DynamicData("Property", DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [{|#3:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod4(object[] o) + { + } + + public static IEnumerable Property => new List(); + + public static int GetDisplayName(MethodInfo methodInfo, object[] data) => default; + } + + public class SomeClass + { + public static IEnumerable SomeProperty => new List(); + + public static int GetSomeDisplayName(MethodInfo methodInfo, object[] data) => default; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(0).WithArguments("MyTestClass", "GetDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(1).WithArguments("MyTestClass", "GetDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(2).WithArguments("SomeClass", "GetSomeDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(3).WithArguments("SomeClass", "GetSomeDisplayName")); + } + + public async Task WhenDisplayMemberInvalidParameters_Diagnostic() + { + string code = """ + using System.Collections.Generic; + using System.Reflection; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [{|#0:DynamicData("Property", DynamicDataDisplayName = "GetDisplayName")|}] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [{|#1:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetDisplayName")|}] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [{|#2:DynamicData("Property", DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [{|#3:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetSomeDisplayName", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod4(object[] o) + { + } + + [{|#4:DynamicData("Property", DynamicDataDisplayName = "GetDisplayName2")|}] + [TestMethod] + public void TestMethod11(object[] o) + { + } + + [{|#5:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetDisplayName2")|}] + [TestMethod] + public void TestMethod12(object[] o) + { + } + + [{|#6:DynamicData("Property", DynamicDataDisplayName = "GetSomeDisplayName2", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod13(object[] o) + { + } + + [{|#7:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetSomeDisplayName2", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod14(object[] o) + { + } + + [{|#8:DynamicData("Property", DynamicDataDisplayName = "GetDisplayName3")|}] + [TestMethod] + public void TestMethod21(object[] o) + { + } + + [{|#9:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetDisplayName3")|}] + [TestMethod] + public void TestMethod22(object[] o) + { + } + + [{|#10:DynamicData("Property", DynamicDataDisplayName = "GetSomeDisplayName3", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod23(object[] o) + { + } + + [{|#11:DynamicData("SomeProperty", typeof(SomeClass), DynamicDataDisplayName = "GetSomeDisplayName3", DynamicDataDisplayNameDeclaringType = typeof(SomeClass))|}] + [TestMethod] + public void TestMethod24(object[] o) + { + } + + public static IEnumerable Property => new List(); + + public static string GetDisplayName() => null; + public static string GetDisplayName2(MethodInfo methodInfo) => null; + public static string GetDisplayName3(MethodInfo methodInfo, string[] args) => null; + } + + public class SomeClass + { + public static IEnumerable SomeProperty => new List(); + + public static string GetSomeDisplayName() => null; + public static string GetSomeDisplayName2(MethodInfo methodInfo) => null; + public static string GetSomeDisplayName3(MethodInfo methodInfo, string[] args) => null; + } + """; + + await VerifyCS.VerifyAnalyzerAsync( + code, + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(0).WithArguments("MyTestClass", "GetDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(1).WithArguments("MyTestClass", "GetDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(2).WithArguments("SomeClass", "GetSomeDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(3).WithArguments("SomeClass", "GetSomeDisplayName"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(4).WithArguments("MyTestClass", "GetDisplayName2"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(5).WithArguments("MyTestClass", "GetDisplayName2"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(6).WithArguments("SomeClass", "GetSomeDisplayName2"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(7).WithArguments("SomeClass", "GetSomeDisplayName2"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(8).WithArguments("MyTestClass", "GetDisplayName3"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(9).WithArguments("MyTestClass", "GetDisplayName3"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(10).WithArguments("SomeClass", "GetSomeDisplayName3"), + VerifyCS.Diagnostic(DynamicDataShouldBeValidAnalyzer.DisplayMethodSignatureRule).WithLocation(11).WithArguments("SomeClass", "GetSomeDisplayName3")); } } diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/Properties/launchSettings.json b/test/UnitTests/MSTest.Analyzers.UnitTests/Properties/launchSettings.json index 9d3c5b5324..d7b9c2736a 100644 --- a/test/UnitTests/MSTest.Analyzers.UnitTests/Properties/launchSettings.json +++ b/test/UnitTests/MSTest.Analyzers.UnitTests/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "MSTest.Analyzers.UnitTests": { "commandName": "Project", - "commandLineArgs": "--treenode-filter /*/*/DynamicDataShouldBeValidAnalyzerTests/**" + "commandLineArgs": "--treenode-filter /*/*/*/**" } } }