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>'
+
+ 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>'
+
+ 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>'
+
+ 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>'
+
+ 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>'
+
+ È 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>'
+
+ テスト '{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>'
+
+ '{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>'
+
+ 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>'
+
+ 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>'
+
+ Превышено время ожидания выполнения теста "{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>'
+
+ '{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>'
+
+ 测试“{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>'
+
+ 測試 '{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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 常に失敗している '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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 항상 실패하는 '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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ Используйте "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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 使用 “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]' data member '{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}' cannot be found
+
+
+
+
+ '[DynamicData]' referenced member '{0}.{1}' should return 'IEnumerable<object[]>', 'IEnumerable<Tuple>` or 'IEnumerable<ValueTuple>'
+
+
+
+
+ '[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 property so you should set 'DynamicDataSourceType.Property'
+
+
+
+
+ '[DynamicDta]' member '{0}.{1}' is found more than once
+
+
+
+
+ DynamicData should be valid
+
+ 使用 '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