Skip to content

Commit

Permalink
MSTEST0006: Avoid '[ExpectedException]'
Browse files Browse the repository at this point in the history
  • Loading branch information
Evangelink committed Dec 30, 2023
1 parent 6b7e0df commit a0fe125
Show file tree
Hide file tree
Showing 21 changed files with 344 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ MSTEST0002 | Usage | Warning | TestClassShouldBeValidAnalyzer, [Documentation](h
MSTEST0003 | Usage | Warning | TestMethodShouldBeValidAnalyzer, [Documentation](https://github.com/microsoft/testfx/blob/main/docs/analyzers/MSTEST0003.md)
MSTEST0004 | Design | Disabled | PublicTypeShouldBeTestClassAnalyzer, [Documentation](https://github.com/microsoft/testfx/blob/main/docs/analyzers/MSTEST0004.md)
MSTEST0005 | Usage | Warning | TestContextShouldBeValidAnalyzer, [Documentation](https://github.com/microsoft/testfx/blob/main/docs/analyzers/MSTEST0005.md)
MSTEST0006 | Design | Info | AvoidExpectedExceptionAttributeAnalyzer, [Documentation](https://github.com/microsoft/testfx/blob/main/docs/analyzers/MSTEST0002.md)
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 AvoidExpectedExceptionAttributeAnalyzer : DiagnosticAnalyzer
{
private static readonly LocalizableResourceString Title = new(nameof(Resources.AvoidExpectedExceptionAttributeTitle), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableResourceString Description = new(nameof(Resources.AvoidExpectedExceptionAttributeDescription), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableResourceString MessageFormat = new(nameof(Resources.AvoidExpectedExceptionAttributeMessageFormat), Resources.ResourceManager, typeof(Resources));

internal static readonly DiagnosticDescriptor Rule = new(
DiagnosticIds.AvoidExpectedExceptionAttributeRuleId,
Title,
MessageFormat,
Categories.Design,
DiagnosticSeverity.Info,
isEnabledByDefault: true,
Description,
$"https://github.com/microsoft/testfx/blob/main/docs/analyzers/{DiagnosticIds.AvoidExpectedExceptionAttributeRuleId}.md");

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.MicrosoftVisualStudioTestToolsUnitTestingExpectedExceptionAttribute, out var expectedExceptionAttributeSymbol))
{
context.RegisterSymbolAction(context => AnalyzeSymbol(context, expectedExceptionAttributeSymbol), SymbolKind.Method);
}
});
}

private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol expectedExceptionAttributeSymbol)
{
var methodSymbol = (IMethodSymbol)context.Symbol;
if (methodSymbol.GetAttributes().Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, expectedExceptionAttributeSymbol)))
{
context.ReportDiagnostic(methodSymbol.CreateDiagnostic(Rule));
}
}
}
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 @@ -10,4 +10,5 @@ internal static class DiagnosticIds
public const string TestMethodShouldBeValidRuleId = "MSTEST0003";
public const string PublicTypeShouldBeTestClassRuleId = "MSTEST0004";
public const string TestContextShouldBeValidRuleId = "MSTEST0005";
public const string AvoidExpectedExceptionAttributeRuleId = "MSTEST0006";
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ internal static class WellKnownTypeNames
public const string MicrosoftVisualStudioTestToolsUnitTestingTestClassAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute";
public const string MicrosoftVisualStudioTestToolsUnitTestingTestContext = "Microsoft.VisualStudio.TestTools.UnitTesting.TestContext";
public const string MicrosoftVisualStudioTestToolsUnitTestingTestMethodAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute";
public const string MicrosoftVisualStudioTestToolsUnitTestingExpectedExceptionAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.ExpectedExceptionAttribute";

public const string SystemThreadingTasksTask = "System.Threading.Tasks.Task";
public const string SystemThreadingTasksTask1 = "System.Threading.Tasks.Task`1";
Expand Down
27 changes: 27 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.

9 changes: 9 additions & 0 deletions src/Analyzers/MSTest.Analyzers/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AvoidExpectedExceptionAttributeDescription" xml:space="preserve">
<value>Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</value>
</data>
<data name="AvoidExpectedExceptionAttributeMessageFormat" xml:space="preserve">
<value>Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</value>
</data>
<data name="AvoidExpectedExceptionAttributeTitle" xml:space="preserve">
<value>Avoid '[ExpectedException]'</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
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="cs" original="../Resources.resx">
<body>
<trans-unit id="AvoidExpectedExceptionAttributeDescription">
<source>Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</source>
<target state="new">Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeMessageFormat">
<source>Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</source>
<target state="new">Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeTitle">
<source>Avoid '[ExpectedException]'</source>
<target state="new">Avoid '[ExpectedException]'</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
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="de" original="../Resources.resx">
<body>
<trans-unit id="AvoidExpectedExceptionAttributeDescription">
<source>Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</source>
<target state="new">Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeMessageFormat">
<source>Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</source>
<target state="new">Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeTitle">
<source>Avoid '[ExpectedException]'</source>
<target state="new">Avoid '[ExpectedException]'</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
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="es" original="../Resources.resx">
<body>
<trans-unit id="AvoidExpectedExceptionAttributeDescription">
<source>Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</source>
<target state="new">Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeMessageFormat">
<source>Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</source>
<target state="new">Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeTitle">
<source>Avoid '[ExpectedException]'</source>
<target state="new">Avoid '[ExpectedException]'</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
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="fr" original="../Resources.resx">
<body>
<trans-unit id="AvoidExpectedExceptionAttributeDescription">
<source>Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</source>
<target state="new">Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeMessageFormat">
<source>Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</source>
<target state="new">Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeTitle">
<source>Avoid '[ExpectedException]'</source>
<target state="new">Avoid '[ExpectedException]'</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
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="it" original="../Resources.resx">
<body>
<trans-unit id="AvoidExpectedExceptionAttributeDescription">
<source>Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</source>
<target state="new">Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeMessageFormat">
<source>Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</source>
<target state="new">Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeTitle">
<source>Avoid '[ExpectedException]'</source>
<target state="new">Avoid '[ExpectedException]'</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
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="ja" original="../Resources.resx">
<body>
<trans-unit id="AvoidExpectedExceptionAttributeDescription">
<source>Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</source>
<target state="new">Prefer 'Assert.ThrowsException' or 'Assert.ThrowsExceptionAsync' over '[ExpectedException]' as it ensures that only the expected call throws the expected exception. The assert APIs also provide more flexibility and allow you to assert extra properties of the exeption.</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeMessageFormat">
<source>Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</source>
<target state="new">Prefer 'Assert.ThrowsException/ThrowsExceptionAsync' over '[ExpectedException]'</target>
<note />
</trans-unit>
<trans-unit id="AvoidExpectedExceptionAttributeTitle">
<source>Avoid '[ExpectedException]'</source>
<target state="new">Avoid '[ExpectedException]'</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

0 comments on commit a0fe125

Please sign in to comment.