Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSTEST0019: Prefer TestInitialize over ctor #2580

Merged
merged 4 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
Rule ID | Category | Severity | Notes
--------|----------|----------|-------
MSTEST0017 | Usage | Info | AssertionArgsShouldBePassedInCorrectOrder, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0017)
MSTEST0019 | Design | Disabled | PreferTestInitializeOverConstructorAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0019)
MSTEST0020 | Design | Disabled | PreferConstructorOverTestInitializeAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0020)
1 change: 1 addition & 0 deletions src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ internal static class DiagnosticIds
public const string TestMethodShouldNotBeIgnoredRuleId = "MSTEST0015";
public const string TestClassShouldHaveTestMethodRuleId = "MSTEST0016";
public const string AssertionArgsShouldBePassedInCorrectOrderRuleId = "MSTEST0017";
public const string PreferTestInitializeOverConstructorRuleId = "MSTEST0019";
public const string PreferConstructorOverTestInitializeRuleId = "MSTEST0020";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// 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 PreferTestInitializeOverConstructorAnalyzer : DiagnosticAnalyzer
{
private static readonly LocalizableResourceString Title = new(nameof(Resources.PreferTestInitializeOverConstructorTitle), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableResourceString MessageFormat = new(nameof(Resources.PreferTestInitializeOverConstructorMessageFormat), Resources.ResourceManager, typeof(Resources));

internal static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create(
DiagnosticIds.PreferTestInitializeOverConstructorRuleId,
Title,
MessageFormat,
null,
Category.Design,
DiagnosticSeverity.Info,
isEnabledByDefault: false);

public override ImmutableArray<DiagnosticDescriptor> 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.MicrosoftVisualStudioTestToolsUnitTestingTestClassAttribute, out var testClassAttributeSymbol))
{
context.RegisterSymbolAction(context => AnalyzeSymbol(context, testClassAttributeSymbol), SymbolKind.NamedType);
}
});
}

private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol testClassAttributeSymbol)
{
INamedTypeSymbol namedTypeSymbol = (INamedTypeSymbol)context.Symbol;

if (namedTypeSymbol.GetAttributes().Any(attr => attr.AttributeClass.Inherits(testClassAttributeSymbol))
&& namedTypeSymbol.InstanceConstructors.FirstOrDefault(x => !x.IsImplicitlyDeclared && x.Parameters.Length == 0) is { } parameterlessExplicitCtor)
{
context.ReportDiagnostic(parameterlessExplicitCtor.CreateDiagnostic(Rule));
}
}
}
18 changes: 18 additions & 0 deletions src/Analyzers/MSTest.Analyzers/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/Analyzers/MSTest.Analyzers/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,12 @@
<data name="PreferConstructorOverTestInitializeTitle" xml:space="preserve">
<value>Prefer constructors over TestInitialize methods</value>
</data>
<data name="PreferTestInitializeOverConstructorMessageFormat" xml:space="preserve">
<value>Prefer TestInitialize methods over constructors</value>
</data>
<data name="PreferTestInitializeOverConstructorTitle" xml:space="preserve">
<value>Prefer TestInitialize methods over constructors</value>
</data>
<data name="PublicTypeShouldBeTestClassDescription" xml:space="preserve">
<value>It's considered a good practice to have only test classes marked public in a test project.</value>
</data>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">Osvědčeným postupem je označit jako veřejné v testovacím projektu jen testovací třídy.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">Es wird als bewährte Methode angesehen, nur Testklassen in einem Testprojekt als öffentlich gekennzeichnet zu lassen.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">Se considera una buena práctica tener solo clases de prueba marcadas como públicas en un proyecto de prueba.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">C’est considéré comme une bonne pratique d’avoir uniquement des classes de test marquées comme publiques dans un projet de test.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">È consigliabile che solo le classi di test siano contrassegnate come pubbliche in un progetto di test.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">テスト プロジェクトでは、テスト クラスのみをパブリックとしてマークすることをお勧めします。</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">테스트 프로젝트에서 공용으로 표시된 테스트 클래스만 사용하는 것이 좋습니다.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">Uważa się, że dobrą praktyką jest oznaczanie tylko klas testowych jako publicznych w projekcie testowym.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">É considerado uma boa prática ter somente classes de teste marcadas como públicas em um projeto de teste.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">Рекомендуется использовать только тестовые классы, помеченные как общедоступные в тестовом проекте.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">Test projesinde yalnızca public olarak işaretlenmiş test sınıflarının olması iyi bir uygulama olarak kabul edilir.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">在测试项目中仅将测试类标记为“公开”是一种不错的做法。</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@
<target state="new">Prefer constructors over TestInitialize methods</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorMessageFormat">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PreferTestInitializeOverConstructorTitle">
<source>Prefer TestInitialize methods over constructors</source>
<target state="new">Prefer TestInitialize methods over constructors</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">在測試專案中僅將測試類別標記為公開被認為是一種很好的做法。</target>
Expand Down
Loading
Loading