diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/CodeFixResources.resx b/src/Analyzers/MSTest.Analyzers.CodeFixes/CodeFixResources.resx index c10b4c9d82..8f1411f2a8 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/CodeFixResources.resx +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/CodeFixResources.resx @@ -278,4 +278,8 @@ Add a placeholder justification to '[Ignore]' {Locked="[Ignore]"} + + Remove redundant 'DisplayName' + {Locked="DisplayName"} + diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/RedundantTestMethodDisplayNameFixer.cs b/src/Analyzers/MSTest.Analyzers.CodeFixes/RedundantTestMethodDisplayNameFixer.cs new file mode 100644 index 0000000000..8d515e3b2b --- /dev/null +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/RedundantTestMethodDisplayNameFixer.cs @@ -0,0 +1,85 @@ +// 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 System.Composition; + +using Analyzer.Utilities; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; + +using MSTest.Analyzers.Helpers; + +namespace MSTest.Analyzers; + +/// +/// Code fixer for . +/// +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(RedundantTestMethodDisplayNameFixer))] +[Shared] +public sealed class RedundantTestMethodDisplayNameFixer : CodeFixProvider +{ + /// + public override ImmutableArray FixableDiagnosticIds { get; } + = ImmutableArray.Create(DiagnosticIds.RedundantTestMethodDisplayNameRuleId); + + /// + public override FixAllProvider GetFixAllProvider() + // See https://github.com/dotnet/roslyn/blob/main/docs/analyzers/FixAllProvider.md for more information on Fix All Providers + => WellKnownFixAllProviders.BatchFixer; + + /// + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + SyntaxNode root = await context.Document.GetRequiredSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); + + Diagnostic diagnostic = context.Diagnostics[0]; + TextSpan diagnosticSpan = diagnostic.Location.SourceSpan; + + SyntaxNode node = root.FindNode(diagnosticSpan); + AttributeSyntax? attributeSyntax = node.FirstAncestorOrSelf(); + AttributeArgumentSyntax? displayNameArgument = attributeSyntax?.ArgumentList?.Arguments + .FirstOrDefault(argument => argument.NameEquals?.Name.Identifier.Text == "DisplayName"); + if (displayNameArgument is null) + { + return; + } + + context.RegisterCodeFix( + CodeAction.Create( + title: CodeFixResources.RemoveRedundantTestMethodDisplayNameFix, + createChangedDocument: c => RemoveDisplayNameArgumentAsync(context.Document, displayNameArgument, c), + equivalenceKey: nameof(RedundantTestMethodDisplayNameFixer)), + diagnostic); + } + + private static async Task RemoveDisplayNameArgumentAsync(Document document, AttributeArgumentSyntax displayNameArgument, CancellationToken cancellationToken) + { + SyntaxNode root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + + if (displayNameArgument.Parent is not AttributeArgumentListSyntax argumentList) + { + return document; + } + + // If 'DisplayName' is the only argument, remove the whole argument list so we don't leave empty parentheses. + if (argumentList.Arguments.Count == 1) + { + SyntaxNode newRoot = root.RemoveNode(argumentList, SyntaxRemoveOptions.KeepNoTrivia)!; + return document.WithSyntaxRoot(newRoot); + } + + AttributeArgumentListSyntax? newArgumentList = argumentList.RemoveNode(displayNameArgument, SyntaxRemoveOptions.KeepNoTrivia); + if (newArgumentList is not null) + { + SyntaxNode newRoot = root.ReplaceNode(argumentList, newArgumentList); + return document.WithSyntaxRoot(newRoot); + } + + return document; + } +} diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.cs.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.cs.xlf index 6084d73351..26e960e390 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.cs.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.cs.xlf @@ -107,6 +107,11 @@ Pokud chcete použít výchozí AutoDetect, odeberte parametr DynamicDataSourceType. {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' Nahradit DataTestMethod hodnotou TestMethod diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.de.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.de.xlf index dfbf913a8e..f9d281bf64 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.de.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.de.xlf @@ -107,6 +107,11 @@ Entfernen Sie den Parameter „DynamicDataSourceType“, um die Standardeinstellung „AutoDetect“ zu verwenden. {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' „DataTestMethod“ durch „TestMethod“ ersetzen diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.es.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.es.xlf index 5ab35d7064..2046fb2a4c 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.es.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.es.xlf @@ -107,6 +107,11 @@ Elimine el parámetro 'DynamicDataSourceType' para utilizar el valor predeterminado 'AutoDetect' {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' Reemplazar "DataTestMethod" por "TestMethod" diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.fr.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.fr.xlf index e51f486b90..997ae8eb7d 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.fr.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.fr.xlf @@ -107,6 +107,11 @@ Pour utiliser la valeur par défaut « AutoDetect », supprimez le paramètre « DynamicDataSourceType » {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' Remplacer « DataTestMethod » par « TestMethod » diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.it.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.it.xlf index 2dd7ec3d9c..7decf7e40e 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.it.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.it.xlf @@ -107,6 +107,11 @@ Rimuovi il parametro ''DynamicDataSourceType'' per utilizzare il valore predefinito ''AutoDetect'' {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' Sostituisci 'DataTestMethod' con 'TestMethod' diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ja.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ja.xlf index c3d3c831d9..adc3343d25 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ja.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ja.xlf @@ -107,6 +107,11 @@ 'DynamicDataSourceType' パラメーターを削除して、既定の 'AutoDetect' を使用します {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' 'DataTestMethod' を 'TestMethod' に置き換えます diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ko.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ko.xlf index 72f0cdd633..dd91602d7a 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ko.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ko.xlf @@ -107,6 +107,11 @@ 기본 'AutoDetect'를 사용하려면 'DynamicDataSourceType' 매개 변수를 제거합니다. {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' 'DataTestMethod'를 'TestMethod'로 바꾸기 diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.pl.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.pl.xlf index f14ce4b540..cecf6f34bc 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.pl.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.pl.xlf @@ -107,6 +107,11 @@ Usuń parametr „DynamicDataSourceType”, aby użyć domyślnego elementu „AutoDetect” {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' Zastąp element „DataTestMethod” elementem „TestMethod” diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.pt-BR.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.pt-BR.xlf index a50aa4d6e3..b63af6e2fb 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.pt-BR.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.pt-BR.xlf @@ -107,6 +107,11 @@ Remover o parâmetro "DynamicDataSourceType" para usar o padrão "AutoDetect" {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' Substitua 'DataTestMethod' por 'TestMethod' diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ru.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ru.xlf index 9b9388ea06..e641c0f928 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ru.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ru.xlf @@ -107,6 +107,11 @@ Удалите параметр "DynamicDataSourceType", чтобы использовать значение по умолчанию "AutoDetect" {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' Заменить "DataTestMethod" на "TestMethod" diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.tr.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.tr.xlf index 5fb46fb004..8501e21490 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.tr.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.tr.xlf @@ -107,6 +107,11 @@ Varsayılan ‘AutoDetect’ değerini kullanmak için ‘DynamicDataSourceType’ parametresini kaldırın {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' 'DataTestMethod' yöntemini 'TestMethod' ile değiştirin diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.zh-Hans.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.zh-Hans.xlf index 83caa8f780..83e8183097 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.zh-Hans.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.zh-Hans.xlf @@ -107,6 +107,11 @@ 移除 ‘DynamicDataSourceType’ 参数以使用默认的 ‘AutoDetect’ {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' 将 'DataTestMethod' 替换为 'TestMethod' diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.zh-Hant.xlf b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.zh-Hant.xlf index 8e53240458..94d5e2412a 100644 --- a/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.zh-Hant.xlf +++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.zh-Hant.xlf @@ -107,6 +107,11 @@ 移除 'DynamicDataSourceType' 參數,以使用預設的 'AutoDetect' {Locked="DynamicDataSourceType"}{Locked="AutoDetect"} + + Remove redundant 'DisplayName' + Remove redundant 'DisplayName' + {Locked="DisplayName"} + Replace 'DataTestMethod' with 'TestMethod' 將 'DataTestMethod' 取代為 'TestMethod' diff --git a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md index 60a1fce5b5..874f930a85 100644 --- a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md +++ b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md @@ -11,3 +11,4 @@ MSTEST0066 | Design | Info | IgnoreShouldHaveJustificationAnalyzer, [Documentati MSTEST0067 | Usage | Disabled | AvoidThreadSleepAndTaskWaitInTestsAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0067) MSTEST0068 | Usage | Info | CollectionAssertToAssertAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0068) MSTEST0070 | Usage | Warning | MemberConditionShouldBeValidAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0070) +MSTEST0071 | Usage | Info | RedundantTestMethodDisplayNameAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0071) diff --git a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs index 585c7b2398..e52be825e6 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs @@ -75,4 +75,5 @@ internal static class DiagnosticIds public const string CollectionAssertToAssertRuleId = "MSTEST0068"; // public const string InheritedTestClassAttributeWithSourceGeneratorRuleId = "MSTEST0069"; - // Reserved. Owned by MSTest.SourceGeneration analyzer; don't reuse this ID. public const string MemberConditionShouldBeValidRuleId = "MSTEST0070"; + public const string RedundantTestMethodDisplayNameRuleId = "MSTEST0071"; } diff --git a/src/Analyzers/MSTest.Analyzers/RedundantTestMethodDisplayNameAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/RedundantTestMethodDisplayNameAnalyzer.cs new file mode 100644 index 0000000000..b8f5bb5764 --- /dev/null +++ b/src/Analyzers/MSTest.Analyzers/RedundantTestMethodDisplayNameAnalyzer.cs @@ -0,0 +1,89 @@ +// 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; + +/// +/// MSTEST0071: . +/// +[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] +public sealed class RedundantTestMethodDisplayNameAnalyzer : DiagnosticAnalyzer +{ + private static readonly LocalizableResourceString Title = new(nameof(Resources.RedundantTestMethodDisplayNameTitle), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString MessageFormat = new(nameof(Resources.RedundantTestMethodDisplayNameMessageFormat), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString Description = new(nameof(Resources.RedundantTestMethodDisplayNameDescription), Resources.ResourceManager, typeof(Resources)); + + internal static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create( + DiagnosticIds.RedundantTestMethodDisplayNameRuleId, + Title, + MessageFormat, + Description, + Category.Usage, + DiagnosticSeverity.Info, + isEnabledByDefault: true); + + /// + public override ImmutableArray SupportedDiagnostics { get; } + = ImmutableArray.Create(Rule); + + /// + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + + context.RegisterCompilationStartAction(context => + { + if (!context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingTestMethodAttribute, out INamedTypeSymbol? testMethodAttributeSymbol)) + { + return; + } + + context.RegisterSymbolAction( + context => AnalyzeSymbol(context, testMethodAttributeSymbol), + SymbolKind.Method); + }); + } + + private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol testMethodAttributeSymbol) + { + var methodSymbol = (IMethodSymbol)context.Symbol; + + foreach (AttributeData attribute in methodSymbol.GetAttributes()) + { + // Only consider attributes that are (or derive from) '[TestMethod]'. + if (!attribute.AttributeClass.Inherits(testMethodAttributeSymbol)) + { + continue; + } + + foreach (KeyValuePair namedArgument in attribute.NamedArguments) + { + if (namedArgument.Key != "DisplayName" + || namedArgument.Value.Value is not string displayName + || !string.Equals(displayName, methodSymbol.Name, StringComparison.Ordinal)) + { + continue; + } + + if (attribute.ApplicationSyntaxReference is { } syntaxReference) + { + context.ReportDiagnostic(syntaxReference.CreateDiagnostic(Rule, context.CancellationToken, methodSymbol.Name)); + } + else + { + context.ReportDiagnostic(methodSymbol.CreateDiagnostic(Rule, methodSymbol.Name)); + } + } + } + } +} diff --git a/src/Analyzers/MSTest.Analyzers/Resources.resx b/src/Analyzers/MSTest.Analyzers/Resources.resx index af9597b960..747907518c 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.resx +++ b/src/Analyzers/MSTest.Analyzers/Resources.resx @@ -986,4 +986,15 @@ The type declaring these methods should also respect the following rules: '[MemberCondition]' referenced property '{0}.{1}' must have a getter {0} is the containing type name. {1} is the property name. {Locked="[MemberCondition]"} + + Test method should not specify a display name equal to its name + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf index 6c063cc26b..25d72ff702 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf @@ -662,6 +662,21 @@ Typ deklarující tyto metody by měl také respektovat následující pravidla: Preferovat TestMethod před DataTestMethod {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true Zkontrolujte nebo odeberte kontrolní výraz, protože jeho podmínka je vždy true. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf index 04f6896d04..ea98537635 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf @@ -663,6 +663,21 @@ Der Typ, der diese Methoden deklariert, sollte auch die folgenden Regeln beachte „TestMethod“ gegenüber „DataTestMethod“ bevorzugen {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true Überprüfen oder entfernen Sie die Assertion, weil ihre Bedingung bekanntermaßen immer true ist. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf index b20aa7743a..9acf875f39 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf @@ -662,6 +662,21 @@ El tipo que declara estos métodos también debe respetar las reglas siguientes: Preferir "TestMethod" a "DataTestMethod" {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true Revise o quite la aserción porque se sabe que su condición siempre es true diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf index 8cc29325f5..8465c0c4ff 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf @@ -662,6 +662,21 @@ Le type déclarant ces méthodes doit également respecter les règles suivantes Préférer « TestMethod » à « DataTestMethod » {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true Vérifier ou supprimer l’assertion, car sa condition est connue pour être toujours true diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf index 0422dbfe56..26afa7f617 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf @@ -662,6 +662,21 @@ Anche il tipo che dichiara questi metodi deve rispettare le regole seguenti: Preferisci 'TestMethod' a 'DataTestMethod' {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true Rivedere o rimuovere l'asserzione perché la relativa condizione è sempre true diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf index 3d0ad73440..cd74410cbc 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf @@ -662,6 +662,21 @@ The type declaring these methods should also respect the following rules: 'DataTestMethod' よりも 'TestMethod' を優先する {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true アサーションの条件が常に true であることが判明しているため、アサーションを確認または削除してください diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf index 89aae05ee3..f8b141b5c0 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf @@ -662,6 +662,21 @@ The type declaring these methods should also respect the following rules: 'DataTestMethod'보다 'TestMethod' 선호 {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true 조건이 항상 true인 것으로 알려진 어설션 검토 또는 제거 diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf index bc00905964..a357ed9d59 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf @@ -662,6 +662,21 @@ Typ deklarujący te metody powinien również przestrzegać następujących regu Wybieraj element „TestMethod”, anie „DataTestMethod” {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true Przejrzyj lub usuń asercję, ponieważ wiadomo, że jej warunek ma zawsze wartość true diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf index d2b8c17136..5a0d2f9f69 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf @@ -662,6 +662,21 @@ O tipo que declara esses métodos também deve respeitar as seguintes regras: Prefira 'TestMethod' a 'DataTestMethod' {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true Examine ou remova a asserção, pois a sua condição é conhecida por ser sempre true diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf index d46a07d2a3..316fa4bdd3 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf @@ -668,6 +668,21 @@ The type declaring these methods should also respect the following rules: Следует предпочитать метод "TestMethod" методу "DataTestMethod" {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true Проверьте или удалите утверждение, так как известно, что его условие всегда true diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf index a181dac9eb..cfb813866f 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf @@ -662,6 +662,21 @@ Bu metotları bildiren türün ayrıca aşağıdaki kurallara uyması gerekir: 'DataTestMethod' yerine 'TestMethod' yöntemini tercih edin {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true Koşulu her zaman true olarak bilinen onaylamayı gözden geçirin veya kaldırın diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf index 641d2efc0f..4ada69a47f 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf @@ -662,6 +662,21 @@ The type declaring these methods should also respect the following rules: 首选 'TestMethod' 而不是 'DataTestMethod' {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true 查看或移除断言,因为已知其条件始终为 true diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf index 79551bd5bb..b777275ccf 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf @@ -662,6 +662,21 @@ The type declaring these methods should also respect the following rules: 優先使用 'TestMethod' 而不是 'DataTestMethod' {Locked="DataTestMethod"}{Locked="TestMethod"} + + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + Setting a 'DisplayName' on a test method to a value that is identical to the method name is redundant because the method name is already used as the display name by default. The redundant 'DisplayName' can be removed without changing how the test is reported. + {Locked="DisplayName"} + + + The 'DisplayName' is the same as the test method name '{0}' and can be removed + The 'DisplayName' is the same as the test method name '{0}' and can be removed + {0} is the test method name. {Locked="DisplayName"} + + + Test method should not specify a display name equal to its name + Test method should not specify a display name equal to its name + + Review or remove the assertion as its condition is known to be always true 檢閱或移除判斷提示,因為已知其條件一律為 true diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/RedundantTestMethodDisplayNameAnalyzerTests.cs b/test/UnitTests/MSTest.Analyzers.UnitTests/RedundantTestMethodDisplayNameAnalyzerTests.cs new file mode 100644 index 0000000000..dc4f0cc564 --- /dev/null +++ b/test/UnitTests/MSTest.Analyzers.UnitTests/RedundantTestMethodDisplayNameAnalyzerTests.cs @@ -0,0 +1,167 @@ +// 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.RedundantTestMethodDisplayNameAnalyzer, + MSTest.Analyzers.RedundantTestMethodDisplayNameFixer>; + +namespace MSTest.Analyzers.Test; + +[TestClass] +public sealed class RedundantTestMethodDisplayNameAnalyzerTests +{ + [TestMethod] + public async Task WhenTestMethodHasNoDisplayName_NoDiagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [TestMethod] + public void MyTestMethod() + { + } + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, code); + } + + [TestMethod] + public async Task WhenDisplayNameIsDifferentFromMethodName_NoDiagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [TestMethod(DisplayName = "My friendly name")] + public void MyTestMethod() + { + } + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, code); + } + + [TestMethod] + public async Task WhenDisplayNameEqualsMethodName_Diagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [[|TestMethod(DisplayName = "MyTestMethod")|]] + public void MyTestMethod() + { + } + } + """; + + string fixedCode = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [TestMethod] + public void MyTestMethod() + { + } + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + + [TestMethod] + public async Task WhenDisplayNameEqualsMethodNameWithOtherArguments_Diagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [[|TestMethod(DisplayName = "MyTestMethod", UnfoldingStrategy = TestDataSourceUnfoldingStrategy.Auto)|]] + public void MyTestMethod() + { + } + } + """; + + string fixedCode = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [TestMethod(UnfoldingStrategy = TestDataSourceUnfoldingStrategy.Auto)] + public void MyTestMethod() + { + } + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + + [TestMethod] + public async Task WhenDataTestMethodDisplayNameEqualsMethodName_Diagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [[|DataTestMethod(DisplayName = "MyTestMethod")|]] + [DataRow(1)] + public void MyTestMethod(int value) + { + } + } + """; + + string fixedCode = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [DataTestMethod] + [DataRow(1)] + public void MyTestMethod(int value) + { + } + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + + [TestMethod] + public async Task WhenDisplayNameEqualsMethodNameWithDifferentCasing_NoDiagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class MyTestClass + { + [TestMethod(DisplayName = "mytestmethod")] + public void MyTestMethod() + { + } + } + """; + + await VerifyCS.VerifyCodeFixAsync(code, code); + } +}