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/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..ec3599737a --- /dev/null +++ b/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs @@ -0,0 +1,306 @@ +// 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 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)); + + internal static readonly DiagnosticDescriptor NotTestMethodRule = DiagnosticDescriptorHelper.Create( + DiagnosticIds.DynamicDataShouldBeValidRuleId, + Title, + MessageFormat, + Description, + Category.Usage, + 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 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); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + + context.RegisterCompilationStartAction(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.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, + ienumerableTypeSymbol, itupleTypeSymbol, methodInfoTypeSymbol), + SymbolKind.Method); + } + }); + } + + private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol testMethodAttributeSymbol, + INamedTypeSymbol dynamicDataAttributeSymbol, INamedTypeSymbol dynamicDataSourceTypeSymbol, INamedTypeSymbol ienumerableTypeSymbol, + INamedTypeSymbol itupleTypeSymbol, INamedTypeSymbol methodInfoTypeSymbol) + { + var methodSymbol = (IMethodSymbol)context.Symbol; + + bool isTestMethod = false; + List dynamicDataAttributes = new(); + 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. + 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 (AttributeData attribute in dynamicDataAttributes) + { + 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 AnalyzeDataSource(SymbolAnalysisContext context, AttributeData attributeData, SyntaxNode attributeSyntax, + IMethodSymbol methodSymbol, INamedTypeSymbol dynamicDataSourceTypeSymbol, INamedTypeSymbol ienumerableTypeSymbol, + INamedTypeSymbol itupleTypeSymbol) + { + 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) + { + 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 the member is a property and the data source type is not set to property, report a diagnostic. + if (member.Kind == SymbolKind.Property && dataSourceType is not DynamicDataSourceTypeProperty) + { + 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 (member.Kind == SymbolKind.Method && dataSourceType is not DynamicDataSourceTypeMethod) + { + 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. + 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/DiagnosticIds.cs b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs index ec72320187..27a2100a2f 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs @@ -22,6 +22,7 @@ internal static class DiagnosticIds public const string TestMethodShouldNotBeIgnoredRuleId = "MSTEST0015"; 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..93405b75eb 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs @@ -19,6 +19,8 @@ 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 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"; @@ -34,12 +36,16 @@ 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"; 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..7cc307b2d9 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs +++ b/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs @@ -383,6 +383,108 @@ 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 '[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 { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_MemberMethod", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '[DynamicData]' member '{0}.{1}' cannot be found. + /// + internal static string DynamicDataShouldBeValidMessageFormat_MemberNotFound { + get { + return ResourceManager.GetString("DynamicDataShouldBeValidMessageFormat_MemberNotFound", resourceCulture); + } + } + + /// + /// 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 '[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 '[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 { + 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..46bd6d16e8 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.resx +++ b/src/Analyzers/MSTest.Analyzers/Resources.resx @@ -473,4 +473,40 @@ 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 + + + '[DynamicData]' member '{0}.{1}' cannot be found + + + '[DynamicDta]' member '{0}.{1}' is found more than once + + + '[DynamicData]' member '{0}.{1}' is a property so you should set 'DynamicDataSourceType.Property' + + + '[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 6e4fcc1645..c6cf16cf8c 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf @@ -233,6 +233,67 @@ 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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..09201361db 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf @@ -232,6 +232,67 @@ "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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..a02c006027 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf @@ -232,6 +232,67 @@ "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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..ffe525bf1e 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf @@ -232,6 +232,67 @@ « 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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..7dca58d511 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf @@ -232,6 +232,67 @@ '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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..ac52808443 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf @@ -232,6 +232,67 @@ '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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..fced30e24e 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf @@ -232,6 +232,67 @@ '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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..57dd847f80 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf @@ -232,6 +232,67 @@ 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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..d02a257851 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf @@ -232,6 +232,67 @@ '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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..b8e2c57648 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf @@ -232,6 +232,67 @@ "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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..b11ad682f7 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf @@ -232,6 +232,67 @@ '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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..9eaf90412b 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf @@ -232,6 +232,67 @@ “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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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..41cf4d6906 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf @@ -232,6 +232,67 @@ '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. + + + + '[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 + + + + '[DynamicData]' member '{0}.{1}' should be a method + '[DynamicData]' member '{0}.{1}' should be a method + + + + '[DynamicData]' member '{0}.{1}' cannot be found + '[DynamicData]' member '{0}.{1}' cannot be found + + + + '[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>' + + + + '[DynamicData]' should only be set on a test method + '[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' + + + + '[DynamicDta]' member '{0}.{1}' is found more than once + '[DynamicDta]' member '{0}.{1}' is found more than once + + + + 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 new file mode 100644 index 0000000000..c5967776f1 --- /dev/null +++ b/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs @@ -0,0 +1,1045 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +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 ValidUsages_NoDiagnostic() + { + string code = """ + using System; + using System.Collections.Generic; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [DynamicData("Data")] + [TestMethod] + public void TestMethod1(object[] o) + { + } + + [DynamicData("SomeData", typeof(SomeClass))] + [TestMethod] + public void TestMethod2(object[] o) + { + } + + [DynamicData(dynamicDataSourceName: "Data")] + [TestMethod] + public void TestMethod3(object[] o) + { + } + + [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 WhenAppliedToNonTestMethod_Diagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [DynamicData("SomeProperty")] + public void {|#0:TestMethod1|}(object[] o) + { + } + + [DynamicData("SomeProperty", typeof(SomeClass))] + public void {|#1:TestMethod2|}(object[] o) + { + } + + [DynamicData(dynamicDataSourceName: "SomeProperty")] + 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, + 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.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() + { + 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.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")); + } +}