diff --git a/src/Adapter/MSTest.TestAdapter/Execution/TestClassInfo.cs b/src/Adapter/MSTest.TestAdapter/Execution/TestClassInfo.cs index cd0d926be6..016a68d2c6 100644 --- a/src/Adapter/MSTest.TestAdapter/Execution/TestClassInfo.cs +++ b/src/Adapter/MSTest.TestAdapter/Execution/TestClassInfo.cs @@ -629,8 +629,7 @@ TestResult DoRun() { if (classCleanupMethod is not null) { - if (ClassAttribute.IgnoreMessage is null && - !ReflectHelper.Instance.IsNonDerivedAttributeDefined(classCleanupMethod.DeclaringType!, false)) + if (!classCleanupMethod.DeclaringType!.IsIgnored(out _)) { ClassCleanupException = InvokeCleanupMethod(classCleanupMethod, remainingCleanupCount: BaseClassCleanupMethods.Count, testContext); } @@ -641,8 +640,7 @@ TestResult DoRun() for (int i = 0; i < BaseClassCleanupMethods.Count; i++) { classCleanupMethod = BaseClassCleanupMethods[i]; - if (ClassAttribute.IgnoreMessage is null && - !ReflectHelper.Instance.IsNonDerivedAttributeDefined(classCleanupMethod.DeclaringType!, false)) + if (!classCleanupMethod.DeclaringType!.IsIgnored(out _)) { ClassCleanupException = InvokeCleanupMethod(classCleanupMethod, remainingCleanupCount: BaseClassCleanupMethods.Count - 1 - i, testContext); if (ClassCleanupException is not null) diff --git a/src/Adapter/MSTest.TestAdapter/Execution/UnitTestRunner.cs b/src/Adapter/MSTest.TestAdapter/Execution/UnitTestRunner.cs index 4c10e5d74e..99c46cdded 100644 --- a/src/Adapter/MSTest.TestAdapter/Execution/UnitTestRunner.cs +++ b/src/Adapter/MSTest.TestAdapter/Execution/UnitTestRunner.cs @@ -351,7 +351,7 @@ private static void RunAssemblyCleanupIfNeeded(ITestContext testContext, ClassCl /// The testMethodInfo. /// The results to return if the test method is not runnable. /// whether the given testMethod is runnable. - private bool IsTestMethodRunnable( + private static bool IsTestMethodRunnable( TestMethod testMethod, TestMethodInfo? testMethodInfo, [NotNullWhen(false)] out TestResult[]? notRunnableResult) @@ -388,34 +388,16 @@ private bool IsTestMethodRunnable( } } - // TODO: Executor should never be null. Is it incorrectly annotated? - string? ignoreMessage = testMethodInfo.Parent.ClassAttribute.IgnoreMessage ?? testMethodInfo.TestMethodOptions.Executor?.IgnoreMessage; - if (ignoreMessage is not null) - { - notRunnableResult = - [ - new TestResult() - { - Outcome = UTF.UnitTestOutcome.Ignored, - IgnoreReason = ignoreMessage, - } - ]; - return false; - } - - IgnoreAttribute? ignoreAttributeOnClass = - _reflectHelper.GetFirstNonDerivedAttributeOrDefault(testMethodInfo.Parent.ClassType, inherit: false); - ignoreMessage = ignoreAttributeOnClass?.IgnoreMessage; - - IgnoreAttribute? ignoreAttributeOnMethod = - _reflectHelper.GetFirstNonDerivedAttributeOrDefault(testMethodInfo.TestMethod, inherit: false); + bool shouldIgnoreClass = testMethodInfo.Parent.ClassType.IsIgnored(out string? ignoreMessageOnClass); + bool shouldIgnoreMethod = testMethodInfo.TestMethod.IsIgnored(out string? ignoreMessageOnMethod); - if (StringEx.IsNullOrEmpty(ignoreMessage) && ignoreAttributeOnMethod is not null) + string? ignoreMessage = ignoreMessageOnClass; + if (StringEx.IsNullOrEmpty(ignoreMessage) && shouldIgnoreMethod) { - ignoreMessage = ignoreAttributeOnMethod.IgnoreMessage; + ignoreMessage = ignoreMessageOnMethod; } - if (ignoreAttributeOnClass is not null || ignoreAttributeOnMethod is not null) + if (shouldIgnoreClass || shouldIgnoreMethod) { notRunnableResult = [ diff --git a/src/Adapter/MSTest.TestAdapter/Helpers/AttributeHelpers.cs b/src/Adapter/MSTest.TestAdapter/Helpers/AttributeHelpers.cs new file mode 100644 index 0000000000..673fbfb4fd --- /dev/null +++ b/src/Adapter/MSTest.TestAdapter/Helpers/AttributeHelpers.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Helpers; + +internal static class AttributeExtensions +{ + public static bool IsIgnored(this ICustomAttributeProvider type, out string? ignoreMessage) + { + IEnumerable attributes = ReflectHelper.Instance.GetDerivedAttributes(type, inherit: false); + IEnumerable> groups = attributes.GroupBy(attr => attr.GroupName); + foreach (IGrouping? group in groups) + { + bool atLeastOneInGroupIsSatisfied = false; + string? firstNonSatisfiedMatch = null; + foreach (ConditionBaseAttribute attribute in group) + { + bool shouldRun = attribute.Mode == ConditionMode.Include ? attribute.ShouldRun : !attribute.ShouldRun; + if (shouldRun) + { + atLeastOneInGroupIsSatisfied = true; + break; + } + + firstNonSatisfiedMatch ??= attribute.IgnoreMessage; + } + + if (!atLeastOneInGroupIsSatisfied) + { + ignoreMessage = firstNonSatisfiedMatch; + return true; + } + } + + ignoreMessage = null; + return false; + } +} diff --git a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md index 3e7ba35873..4404b0bb06 100644 --- a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md +++ b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md @@ -7,3 +7,4 @@ Rule ID | Category | Severity | Notes MSTEST0038 | Usage | Warning | AvoidAssertAreSameWithValueTypesAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0038) MSTEST0039 | Usage | Info | UseNewerAssertThrowsAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0039) MSTEST0040 | Usage | Warning | AvoidUsingAssertsInAsyncVoidContextAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0040) +MSTEST0041 | Usage | Warning | UseConditionBaseWithTestClassAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0041) diff --git a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs index df49efa771..d922cdd19e 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs @@ -45,4 +45,5 @@ internal static class DiagnosticIds public const string AvoidAssertAreSameWithValueTypesRuleId = "MSTEST0038"; public const string UseNewerAssertThrowsRuleId = "MSTEST0039"; public const string AvoidUsingAssertsInAsyncVoidContextRuleId = "MSTEST0040"; + public const string UseConditionBaseWithTestClassRuleId = "MSTEST0041"; } diff --git a/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs b/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs index 900066e322..b77f320483 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs @@ -14,6 +14,7 @@ internal static class WellKnownTypeNames public const string MicrosoftVisualStudioTestToolsUnitTestingClassCleanupExecutionAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.ClassCleanupExecutionAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingClassInitializeAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.ClassInitializeAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingCollectionAssert = "Microsoft.VisualStudio.TestTools.UnitTesting.CollectionAssert"; + public const string MicrosoftVisualStudioTestToolsUnitTestingConditionBaseAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.ConditionBaseAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingCssIterationAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.CssIterationAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingCssProjectStructureAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.CssProjectStructureAttribute"; public const string MicrosoftVisualStudioTestToolsUnitTestingDataRowAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.DataRowAttribute"; diff --git a/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt b/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt index 41e2eb4a23..9972475ad8 100644 --- a/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt +++ b/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt @@ -3,7 +3,11 @@ MSTest.Analyzers.AvoidAssertAreSameWithValueTypesAnalyzer MSTest.Analyzers.AvoidAssertAreSameWithValueTypesAnalyzer.AvoidAssertAreSameWithValueTypesAnalyzer() -> void MSTest.Analyzers.AvoidUsingAssertsInAsyncVoidContextAnalyzer MSTest.Analyzers.AvoidUsingAssertsInAsyncVoidContextAnalyzer.AvoidUsingAssertsInAsyncVoidContextAnalyzer() -> void +MSTest.Analyzers.UseConditionBaseWithTestClassAnalyzer +MSTest.Analyzers.UseConditionBaseWithTestClassAnalyzer.UseConditionBaseWithTestClassAnalyzer() -> void override MSTest.Analyzers.AvoidAssertAreSameWithValueTypesAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void override MSTest.Analyzers.AvoidAssertAreSameWithValueTypesAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray override MSTest.Analyzers.AvoidUsingAssertsInAsyncVoidContextAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void override MSTest.Analyzers.AvoidUsingAssertsInAsyncVoidContextAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray +override MSTest.Analyzers.UseConditionBaseWithTestClassAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void +override MSTest.Analyzers.UseConditionBaseWithTestClassAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray diff --git a/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs b/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs index 3a3fb28261..56a6692d36 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs +++ b/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs @@ -235,7 +235,7 @@ internal static string AvoidExpectedExceptionAttributeTitle { } /// - /// Looks up a localized string similar to Avoid doing assertions in 'async void' methods or lambdas. Exceptions that are thrown in this context will be unobserved exceptions.. + /// Looks up a localized string similar to Do not assert inside 'async void' methods, local functions, or lambdas. Exceptions that are thrown in this context will be unhandled exceptions. When using VSTest under .NET Framework, they will be silently swallowed. When using Microsoft.Testing.Platform or VSTest under modern .NET, they may crash the process.. /// internal static string AvoidUsingAssertsInAsyncVoidContextDescription { get { @@ -244,7 +244,7 @@ internal static string AvoidUsingAssertsInAsyncVoidContextDescription { } /// - /// Looks up a localized string similar to Avoid doing assertions inside 'async void' methods or lambdas because they may not fail the test. + /// Looks up a localized string similar to Do not assert inside 'async void' methods, local functions, or lambdas because they may not fail the test. /// internal static string AvoidUsingAssertsInAsyncVoidContextMessageFormat { get { @@ -253,7 +253,7 @@ internal static string AvoidUsingAssertsInAsyncVoidContextMessageFormat { } /// - /// Looks up a localized string similar to Avoid doing assertions inside 'async void' contexts. + /// Looks up a localized string similar to Do not assert inside 'async void' contexts. /// internal static string AvoidUsingAssertsInAsyncVoidContextTitle { get { @@ -1078,6 +1078,24 @@ internal static string UseClassCleanupBehaviorEndOfClassTitle { } } + /// + /// Looks up a localized string similar to The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute`. + /// + internal static string UseConditionBaseWithTestClassMessageFormat { + get { + return ResourceManager.GetString("UseConditionBaseWithTestClassMessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use 'ConditionBaseAttribute' on test classes. + /// + internal static string UseConditionBaseWithTestClassTitle { + get { + return ResourceManager.GetString("UseConditionBaseWithTestClassTitle", resourceCulture); + } + } + /// /// Looks up a localized string similar to '[DeploymentItem]' can be specified only on test class or test method. /// diff --git a/src/Analyzers/MSTest.Analyzers/Resources.resx b/src/Analyzers/MSTest.Analyzers/Resources.resx index 0e6a2b34ad..694f9c8b78 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.resx +++ b/src/Analyzers/MSTest.Analyzers/Resources.resx @@ -567,4 +567,10 @@ The type declaring these methods should also respect the following rules: Do not assert inside 'async void' methods, local functions, or lambdas. Exceptions that are thrown in this context will be unhandled exceptions. When using VSTest under .NET Framework, they will be silently swallowed. When using Microsoft.Testing.Platform or VSTest under modern .NET, they may crash the process. - + + Use 'ConditionBaseAttribute' on test classes + + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/UseAttributeOnTestMethodAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/UseAttributeOnTestMethodAnalyzer.cs index 9a2e91b464..737d23980a 100644 --- a/src/Analyzers/MSTest.Analyzers/UseAttributeOnTestMethodAnalyzer.cs +++ b/src/Analyzers/MSTest.Analyzers/UseAttributeOnTestMethodAnalyzer.cs @@ -114,6 +114,18 @@ public sealed class UseAttributeOnTestMethodAnalyzer : DiagnosticAnalyzer DiagnosticSeverity.Info, isEnabledByDefault: true); + private const string ConditionBaseAttributeShortName = "ConditionBaseAttribute"; + internal static readonly DiagnosticDescriptor ConditionBaseRule = DiagnosticDescriptorHelper.Create( + DiagnosticIds.UseAttributeOnTestMethodRuleId, + title: new LocalizableResourceString( + nameof(Resources.UseAttributeOnTestMethodAnalyzerTitle), Resources.ResourceManager, typeof(Resources), ConditionBaseAttributeShortName), + messageFormat: new LocalizableResourceString( + nameof(Resources.UseAttributeOnTestMethodAnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources), ConditionBaseAttributeShortName), + description: null, + Category.Usage, + DiagnosticSeverity.Info, + isEnabledByDefault: true); + // IMPORTANT: Remember to add any new rule to the rule tuple. private static readonly List<(string AttributeFullyQualifiedName, DiagnosticDescriptor Rule)> RuleTuples = [ @@ -124,11 +136,20 @@ public sealed class UseAttributeOnTestMethodAnalyzer : DiagnosticAnalyzer (WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingDescriptionAttribute, DescriptionRule), (WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingExpectedExceptionBaseAttribute, ExpectedExceptionRule), (WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingCssIterationAttribute, CssIterationRule), - (WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingCssProjectStructureAttribute, CssProjectStructureRule) + (WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingCssProjectStructureAttribute, CssProjectStructureRule), + (WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingConditionBaseAttribute, ConditionBaseRule), ]; - public override ImmutableArray SupportedDiagnostics { get; } - = ImmutableArray.Create(OwnerRule); + public override ImmutableArray SupportedDiagnostics { get; } = + ImmutableArray.Create( + OwnerRule, + PriorityRule, + TestPropertyRule, + WorkItemRule, + DescriptionRule, + ExpectedExceptionRule, + CssIterationRule, + CssProjectStructureRule); public override void Initialize(AnalysisContext context) { diff --git a/src/Analyzers/MSTest.Analyzers/UseConditionBaseWithTestClassAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/UseConditionBaseWithTestClassAnalyzer.cs new file mode 100644 index 0000000000..f34e1a207f --- /dev/null +++ b/src/Analyzers/MSTest.Analyzers/UseConditionBaseWithTestClassAnalyzer.cs @@ -0,0 +1,73 @@ +// 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; + +/// +/// MSTEST0041: . +/// +[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] +public sealed class UseConditionBaseWithTestClassAnalyzer : DiagnosticAnalyzer +{ + private static readonly LocalizableResourceString Title = new(nameof(Resources.UseConditionBaseWithTestClassTitle), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString MessageFormat = new(nameof(Resources.UseConditionBaseWithTestClassMessageFormat), Resources.ResourceManager, typeof(Resources)); + + internal static readonly DiagnosticDescriptor UseConditionBaseWithTestClassRule = DiagnosticDescriptorHelper.Create( + DiagnosticIds.UseConditionBaseWithTestClassRuleId, + Title, + MessageFormat, + null, + Category.Usage, + DiagnosticSeverity.Warning, + isEnabledByDefault: true); + + public override ImmutableArray SupportedDiagnostics { get; } + = ImmutableArray.Create(UseConditionBaseWithTestClassRule); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + + context.RegisterCompilationStartAction(context => + { + if (context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingTestClassAttribute, out INamedTypeSymbol? testClassAttributeSymbol) && + context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingConditionBaseAttribute, out INamedTypeSymbol? conditionBaseAttributeSymbol)) + { + context.RegisterSymbolAction( + context => AnalyzeSymbol(context, testClassAttributeSymbol, conditionBaseAttributeSymbol), + SymbolKind.NamedType); + } + }); + } + + private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol testClassAttributeSymbol, INamedTypeSymbol conditionBaseAttributeSymbol) + { + INamedTypeSymbol? conditionBaseAttribute = null; + bool isTestClass = false; + foreach (AttributeData attribute in context.Symbol.GetAttributes()) + { + if (attribute.AttributeClass.Inherits(testClassAttributeSymbol)) + { + isTestClass = true; + } + else if (attribute.AttributeClass.Inherits(conditionBaseAttributeSymbol)) + { + conditionBaseAttribute = attribute.AttributeClass; + } + } + + if (conditionBaseAttribute is not null && !isTestClass) + { + context.ReportDiagnostic(context.Symbol.CreateDiagnostic(UseConditionBaseWithTestClassRule, conditionBaseAttribute.Name)); + } + } +} diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf index e3bd8ad8c0..1c98884d41 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf @@ -744,6 +744,16 @@ Typ deklarující tyto metody by měl také respektovat následující pravidla: [{0}] lze nastavit pouze u metod označených pomocí metody [TestMethod]. + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method [DeploymentItem] se dá zadat jenom pro testovací třídu nebo testovací metodu. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf index 9796c1eb6b..d22461589f 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf @@ -745,6 +745,16 @@ Der Typ, der diese Methoden deklariert, sollte auch die folgenden Regeln beachte [{0}] kann nur für Methoden festgelegt werden, die mit [TestMethod] markiert sind. + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method „[DeploymentItem]“ kann nur für die Testklasse oder Testmethode angegeben werden. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf index eeb7206edd..06b4d57f66 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf @@ -744,6 +744,16 @@ El tipo que declara estos métodos también debe respetar las reglas siguientes: [{0}] solo se puede establecer en métodos marcados con [TestMethod] + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method '[DeploymentItem]' solo se puede especificar en la clase de prueba o el método de prueba diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf index 70ac191d80..c05fcb6186 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf @@ -744,6 +744,16 @@ Le type doit être une classe [{0}] ne peut être défini que sur les méthodes marquées avec [TestMethod] + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method « [DeploymentItem] » ne peut être spécifié que sur une classe de test ou une méthode de test diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf index 01cf23b6b4..2cfb7aa22b 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf @@ -744,6 +744,16 @@ Anche il tipo che dichiara questi metodi deve rispettare le regole seguenti: [{0}] può essere impostato solo su metodi contrassegnati con [TestMethod] + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method '[DeploymentItem]' può essere specificato solo per la classe di test o il metodo di test diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf index ca3c1f4caf..c78f49a86f 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf @@ -744,6 +744,16 @@ The type declaring these methods should also respect the following rules: [{0}] は、[TestMethod] でマークされたメソッドにのみ設定できます + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method '[DeploymentItem]' は、テスト クラスまたはテスト メソッドでのみ指定できます diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf index 7ea764fa06..5f7a8a6491 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf @@ -744,6 +744,16 @@ The type declaring these methods should also respect the following rules: [{0}]은(는) [TestMethod] 표시된 메서드에만 설정할 수 있습니다. + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method '[DeploymentItem]'은(는) 테스트 클래스 또는 테스트 메서드에만 지정할 수 있습니다. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf index 1f18149fbe..ccf1f923cf 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf @@ -744,6 +744,16 @@ Typ deklarujący te metody powinien również przestrzegać następujących regu [{0}] można ustawić tylko dla metod oznaczonych znakiem [TestMethod] + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method Element „[DeploymentItem]” można określić tylko dla klasy testowej lub metody testowej diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf index 2587706525..9f309410ac 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf @@ -744,6 +744,16 @@ O tipo que declara esses métodos também deve respeitar as seguintes regras: [{0}] só pode ser definido em métodos marcados com [TestMethod] + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method '[DeploymentItem]' pode ser especificado apenas na classe de teste ou método de teste diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf index 25e75e78e7..0b654e3933 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf @@ -756,6 +756,16 @@ The type declaring these methods should also respect the following rules: [{0}] можно задать только для методов с пометкой [TestMethod] + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method Указать "[DeploymentItem]" можно только для тестового класса или метода. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf index 954070fb61..caa6179feb 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf @@ -746,6 +746,16 @@ Bu yöntemleri bildiren tipin ayrıca aşağıdaki kurallara uyması gerekir: [{0}] yalnızca [TestMethod] ile işaretli yöntemlerde ayarlanabilir + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method '[DeploymentItem]' yalnızca test sınıfında veya test yönteminde belirtilebilir diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf index abd2434682..81713e1a1b 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf @@ -744,6 +744,16 @@ The type declaring these methods should also respect the following rules: 只能对标记了 [TestMethod] 的方法设置 [{0}] + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method 只能对测试类或测试方法指定 "[DeploymentItem]" diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf index d9a1bb4dd8..770b24acf5 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf @@ -744,6 +744,16 @@ The type declaring these methods should also respect the following rules: [{0}] 只能在標示為 [TestMethod] 的方法上設定 + + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + The attribute '{0}' which derives from 'ConditionBaseAttribute' should be used only on classes marked with `TestClassAttribute` + + + + Use 'ConditionBaseAttribute' on test classes + Use 'ConditionBaseAttribute' on test classes + + '[DeploymentItem]' can be specified only on test class or test method '[DeploymentItem]' 只能在測試類或測試方法上指定 diff --git a/src/TestFramework/TestFramework/Attributes/TestMethod/ConditionBaseAttribute.cs b/src/TestFramework/TestFramework/Attributes/TestMethod/ConditionBaseAttribute.cs new file mode 100644 index 0000000000..77b48048a5 --- /dev/null +++ b/src/TestFramework/TestFramework/Attributes/TestMethod/ConditionBaseAttribute.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.VisualStudio.TestTools.UnitTesting; + +/// +/// This attribute is used to conditionally control whether a test class or a test method will run or be ignored, based on a condition and using an optional message. +/// +/// +/// This attribute isn't inherited. Applying it to a base class will not affect derived classes. +/// +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false)] +public abstract class ConditionBaseAttribute : Attribute +{ + protected ConditionBaseAttribute(ConditionMode mode) + => Mode = mode; + + internal ConditionMode Mode { get; } + + /// + /// Gets the ignore message (in case returns ) indicating + /// the reason for ignoring the test method or test class. + /// + public abstract string? IgnoreMessage { get; } + + /// + /// Gets the group name for this attribute. This is relevant when multiple + /// attributes that inherit are present. + /// The ShouldRun values of attributes in the same group are "OR"ed together. + /// While the value from different groups is "AND"ed together. + /// In other words, a test will be ignored if any group has all its values as false. + /// + /// + /// Usually, you can use to return the group name. + /// + public abstract string GroupName { get; } + + /// + /// Gets a value indicating whether the test method or test class should be ignored. + /// + public abstract bool ShouldRun { get; } +} diff --git a/src/TestFramework/TestFramework/Attributes/TestMethod/ConditionMode.cs b/src/TestFramework/TestFramework/Attributes/TestMethod/ConditionMode.cs new file mode 100644 index 0000000000..285cf636c5 --- /dev/null +++ b/src/TestFramework/TestFramework/Attributes/TestMethod/ConditionMode.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.VisualStudio.TestTools.UnitTesting; + +/// +/// An enumeration used with to control whether the condition is reversed. +/// +public enum ConditionMode +{ + /// + /// Runs only when the condition is met (the default). + /// + Include, + + /// + /// Ignores the test when the condition is met (i.e, reverse the condition). + /// + Exclude, +} diff --git a/src/TestFramework/TestFramework/Attributes/TestMethod/IgnoreAttribute.cs b/src/TestFramework/TestFramework/Attributes/TestMethod/IgnoreAttribute.cs index c175d68358..834836fca1 100644 --- a/src/TestFramework/TestFramework/Attributes/TestMethod/IgnoreAttribute.cs +++ b/src/TestFramework/TestFramework/Attributes/TestMethod/IgnoreAttribute.cs @@ -10,7 +10,7 @@ namespace Microsoft.VisualStudio.TestTools.UnitTesting; /// This attribute isn't inherited. Applying it to a base class will not cause derived classes to be ignored. /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false)] -public sealed class IgnoreAttribute : Attribute +public sealed class IgnoreAttribute : ConditionBaseAttribute { /// /// Initializes a new instance of the class with an empty message. @@ -26,10 +26,16 @@ public IgnoreAttribute() /// /// Message specifies reason for ignoring. /// - public IgnoreAttribute(string? message) => IgnoreMessage = message; + public IgnoreAttribute(string? message) + : base(ConditionMode.Include) + => IgnoreMessage = message; /// /// Gets the ignore message indicating the reason for ignoring the test method or test class. /// - public string? IgnoreMessage { get; } + public override string? IgnoreMessage { get; } + + public override bool ShouldRun => false; + + public override string GroupName => "Ignore"; } diff --git a/src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs b/src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs new file mode 100644 index 0000000000..cbb7c5dff8 --- /dev/null +++ b/src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.VisualStudio.TestTools.UnitTesting; + +/// +/// This attribute is used to ignore a test class or a test method, with an optional message. +/// +/// +/// This attribute isn't inherited. Applying it to a base class will not cause derived classes to be ignored. +/// +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +public sealed class OSConditionAttribute : ConditionBaseAttribute +{ + private readonly OperatingSystems _operatingSystems; + + /// + /// Initializes a new instance of the class. + /// + /// The operating systems that this test supports. + public OSConditionAttribute(ConditionMode mode, OperatingSystems operatingSystems) + : base(mode) + { + _operatingSystems = operatingSystems; + IgnoreMessage = $"Test is only supported on {operatingSystems}"; + } + + public OSConditionAttribute(OperatingSystems operatingSystems) + : this(ConditionMode.Include, operatingSystems) + { + } + + public override bool ShouldRun +#if NET462 + // On .NET Framework, we are sure we are running on Windows. + => (_operatingSystems & OperatingSystems.Windows) != 0; +#else + { + get + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return (_operatingSystems & OperatingSystems.Windows) != 0; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return (_operatingSystems & OperatingSystems.Linux) != 0; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return (_operatingSystems & OperatingSystems.MacOSX) != 0; + } + + return false; + } + } +#endif + + public override string? IgnoreMessage { get; } + + public override string GroupName => "OSCondition"; +} diff --git a/src/TestFramework/TestFramework/Attributes/TestMethod/OperatingSystems.cs b/src/TestFramework/TestFramework/Attributes/TestMethod/OperatingSystems.cs new file mode 100644 index 0000000000..bc2c29e1d3 --- /dev/null +++ b/src/TestFramework/TestFramework/Attributes/TestMethod/OperatingSystems.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.VisualStudio.TestTools.UnitTesting; + +/// +/// An enum that is used with to control which operating systems a test method or test class supports or doesn't support. +/// +[Flags] +public enum OperatingSystems +{ + /// + /// Represents the Linux operating system. + /// + Linux = 1, + + // TODO: This is copied from aspnetcore repo. Should we name it MacOS instead? Or OSX? + + /// + /// Representing the MacOS operating system. + /// + MacOSX = 2, + + /// + /// Represents the Windows operating system. + /// + Windows = 4, +} diff --git a/src/TestFramework/TestFramework/Attributes/TestMethod/TestClassAttribute.cs b/src/TestFramework/TestFramework/Attributes/TestMethod/TestClassAttribute.cs index 0da97a08d2..da57c79550 100644 --- a/src/TestFramework/TestFramework/Attributes/TestMethod/TestClassAttribute.cs +++ b/src/TestFramework/TestFramework/Attributes/TestMethod/TestClassAttribute.cs @@ -26,9 +26,4 @@ public class TestClassAttribute : Attribute public virtual TestMethodAttribute? GetTestMethodAttribute(TestMethodAttribute? testMethodAttribute) => // If TestMethod is not extended by derived class then return back the original TestMethodAttribute testMethodAttribute; - - /// - /// Gets or sets a reason to ignore the test class. Setting the property to non-null value will ignore the test class. - /// - public string? IgnoreMessage { get; set; } } diff --git a/src/TestFramework/TestFramework/Attributes/TestMethod/TestMethodAttribute.cs b/src/TestFramework/TestFramework/Attributes/TestMethod/TestMethodAttribute.cs index 1d42b34d43..319fcec986 100644 --- a/src/TestFramework/TestFramework/Attributes/TestMethod/TestMethodAttribute.cs +++ b/src/TestFramework/TestFramework/Attributes/TestMethod/TestMethodAttribute.cs @@ -50,11 +50,6 @@ public TestMethodAttribute() /// public string? DisplayName { get; } - /// - /// Gets or sets a reason to ignore the test method. Setting the property to non-null value will ignore the test method. - /// - public string? IgnoreMessage { get; set; } - /// /// Executes a test method. /// diff --git a/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt b/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt index 70dbfbc553..5c88f25607 100644 --- a/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt +++ b/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt @@ -1,4 +1,7 @@ #nullable enable +abstract Microsoft.VisualStudio.TestTools.UnitTesting.ConditionBaseAttribute.IgnoreMessage.get -> string? +abstract Microsoft.VisualStudio.TestTools.UnitTesting.ConditionBaseAttribute.GroupName.get -> string! +abstract Microsoft.VisualStudio.TestTools.UnitTesting.ConditionBaseAttribute.ShouldRun.get -> bool abstract Microsoft.VisualStudio.TestTools.UnitTesting.RetryBaseAttribute.ExecuteAsync(Microsoft.VisualStudio.TestTools.UnitTesting.RetryContext retryContext) -> System.Threading.Tasks.Task! Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertIsNotEmptyInterpolatedStringHandler Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertIsNotEmptyInterpolatedStringHandler.AppendFormatted(object? value, int alignment = 0, string? format = null) -> void @@ -223,6 +226,11 @@ Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertThrowsExactlyInterpola Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertThrowsExactlyInterpolatedStringHandler.AppendLiteral(string! value) -> void Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertThrowsExactlyInterpolatedStringHandler.AssertThrowsExactlyInterpolatedStringHandler() -> void Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertThrowsExactlyInterpolatedStringHandler.AssertThrowsExactlyInterpolatedStringHandler(int literalLength, int formattedCount, System.Action! action, out bool shouldAppend) -> void +Microsoft.VisualStudio.TestTools.UnitTesting.ConditionBaseAttribute +Microsoft.VisualStudio.TestTools.UnitTesting.ConditionBaseAttribute.ConditionBaseAttribute(Microsoft.VisualStudio.TestTools.UnitTesting.ConditionMode mode) -> void +Microsoft.VisualStudio.TestTools.UnitTesting.ConditionMode +Microsoft.VisualStudio.TestTools.UnitTesting.ConditionMode.Exclude = 1 -> Microsoft.VisualStudio.TestTools.UnitTesting.ConditionMode +Microsoft.VisualStudio.TestTools.UnitTesting.ConditionMode.Include = 0 -> Microsoft.VisualStudio.TestTools.UnitTesting.ConditionMode Microsoft.VisualStudio.TestTools.UnitTesting.DataRowAttribute.IgnoreMessage.get -> string? Microsoft.VisualStudio.TestTools.UnitTesting.DataRowAttribute.IgnoreMessage.set -> void Microsoft.VisualStudio.TestTools.UnitTesting.DelayBackoffType @@ -240,6 +248,13 @@ Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataSourceType.AutoDetect = Microsoft.VisualStudio.TestTools.UnitTesting.ITestDataSourceIgnoreCapability Microsoft.VisualStudio.TestTools.UnitTesting.ITestDataSourceIgnoreCapability.IgnoreMessage.get -> string? Microsoft.VisualStudio.TestTools.UnitTesting.ITestDataSourceIgnoreCapability.IgnoreMessage.set -> void +Microsoft.VisualStudio.TestTools.UnitTesting.OperatingSystems +Microsoft.VisualStudio.TestTools.UnitTesting.OperatingSystems.Linux = 1 -> Microsoft.VisualStudio.TestTools.UnitTesting.OperatingSystems +Microsoft.VisualStudio.TestTools.UnitTesting.OperatingSystems.MacOSX = 2 -> Microsoft.VisualStudio.TestTools.UnitTesting.OperatingSystems +Microsoft.VisualStudio.TestTools.UnitTesting.OperatingSystems.Windows = 4 -> Microsoft.VisualStudio.TestTools.UnitTesting.OperatingSystems +Microsoft.VisualStudio.TestTools.UnitTesting.OSConditionAttribute +Microsoft.VisualStudio.TestTools.UnitTesting.OSConditionAttribute.OSConditionAttribute(Microsoft.VisualStudio.TestTools.UnitTesting.ConditionMode mode, Microsoft.VisualStudio.TestTools.UnitTesting.OperatingSystems operatingSystems) -> void +Microsoft.VisualStudio.TestTools.UnitTesting.OSConditionAttribute.OSConditionAttribute(Microsoft.VisualStudio.TestTools.UnitTesting.OperatingSystems operatingSystems) -> void Microsoft.VisualStudio.TestTools.UnitTesting.RetryAttribute Microsoft.VisualStudio.TestTools.UnitTesting.RetryAttribute.BackoffType.get -> Microsoft.VisualStudio.TestTools.UnitTesting.DelayBackoffType Microsoft.VisualStudio.TestTools.UnitTesting.RetryAttribute.BackoffType.set -> void @@ -255,11 +270,13 @@ Microsoft.VisualStudio.TestTools.UnitTesting.RetryContext.RetryContext() -> void Microsoft.VisualStudio.TestTools.UnitTesting.RetryResult Microsoft.VisualStudio.TestTools.UnitTesting.RetryResult.AddResult(Microsoft.VisualStudio.TestTools.UnitTesting.TestResult![]! testResults) -> void Microsoft.VisualStudio.TestTools.UnitTesting.RetryResult.RetryResult() -> void -Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute.IgnoreMessage.get -> string? -Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute.IgnoreMessage.set -> void -Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute.IgnoreMessage.get -> string? -Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute.IgnoreMessage.set -> void Microsoft.VisualStudio.TestTools.UnitTesting.UnitTestOutcome.Ignored = 10 -> Microsoft.VisualStudio.TestTools.UnitTesting.UnitTestOutcome +override Microsoft.VisualStudio.TestTools.UnitTesting.IgnoreAttribute.IgnoreMessage.get -> string? +override Microsoft.VisualStudio.TestTools.UnitTesting.IgnoreAttribute.GroupName.get -> string! +override Microsoft.VisualStudio.TestTools.UnitTesting.IgnoreAttribute.ShouldRun.get -> bool +override Microsoft.VisualStudio.TestTools.UnitTesting.OSConditionAttribute.IgnoreMessage.get -> string? +override Microsoft.VisualStudio.TestTools.UnitTesting.OSConditionAttribute.GroupName.get -> string! +override Microsoft.VisualStudio.TestTools.UnitTesting.OSConditionAttribute.ShouldRun.get -> bool static Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AreEqual(decimal expected, decimal actual, decimal delta, ref Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertNonGenericAreEqualInterpolatedStringHandler message) -> void static Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AreEqual(double expected, double actual, double delta, ref Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertNonGenericAreEqualInterpolatedStringHandler message) -> void static Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AreEqual(float expected, float actual, float delta, ref Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertNonGenericAreEqualInterpolatedStringHandler message) -> void @@ -316,3 +333,4 @@ static Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsExactly(System.Action! action, System.Func! messageBuilder) -> TException! static Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsExactlyAsync(System.Func! action, string! message = "", params object![]! messageArgs) -> System.Threading.Tasks.Task! static Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsExactlyAsync(System.Func! action, System.Func! messageBuilder) -> System.Threading.Tasks.Task! +*REMOVED*Microsoft.VisualStudio.TestTools.UnitTesting.IgnoreAttribute.IgnoreMessage.get -> string? diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/IgnoreTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/IgnoreTests.cs index 65c4843804..2dd11219bc 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/IgnoreTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/IgnoreTests.cs @@ -18,7 +18,7 @@ public async Task ClassCleanup_Inheritance_WhenClassIsSkipped() // Assert testHostResult.AssertExitCodeIs(ExitCodes.Success); - testHostResult.AssertOutputContainsSummary(failed: 0, passed: 12, skipped: 9); + testHostResult.AssertOutputContainsSummary(failed: 0, passed: 11, skipped: 7); testHostResult.AssertOutputContains("SubClass.Method"); } @@ -36,28 +36,6 @@ public async Task WhenAllTestsAreIgnored_AssemblyInitializeAndCleanupAreSkipped( testHostResult.AssertOutputDoesNotContain("AssemblyCleanup"); } - [TestMethod] - public async Task WhenTestClassIsIgnoredViaIgnoreMessageProperty() - { - var testHost = TestHost.LocateFrom(AssetFixture.ProjectPath, TestAssetFixture.ProjectName, TargetFrameworks.NetCurrent); - TestHostResult testHostResult = await testHost.ExecuteAsync("--settings my.runsettings --filter TestClassWithIgnoreMessage"); - - // Assert - testHostResult.AssertExitCodeIs(ExitCodes.ZeroTests); - testHostResult.AssertOutputContainsSummary(failed: 0, passed: 0, skipped: 1); - } - - [TestMethod] - public async Task WhenTestMethodIsIgnoredViaIgnoreMessageProperty() - { - var testHost = TestHost.LocateFrom(AssetFixture.ProjectPath, TestAssetFixture.ProjectName, TargetFrameworks.NetCurrent); - TestHostResult testHostResult = await testHost.ExecuteAsync("--settings my.runsettings --filter TestClassWithMethodUsingIgnoreMessage"); - - // Assert - testHostResult.AssertExitCodeIs(ExitCodes.Success); - testHostResult.AssertOutputContainsSummary(failed: 0, passed: 1, skipped: 1); - } - [TestMethod] public async Task WhenSpecificDataSourceIsIgnoredViaIgnoreMessageProperty() { @@ -239,29 +217,6 @@ public void TestMethod1() } } -[TestClass(IgnoreMessage = "This test class is ignored")] -public class TestClassWithIgnoreMessage -{ - [TestMethod] - public void TestMethod1() - { - } -} - -[TestClass] -public class TestClassWithMethodUsingIgnoreMessage -{ - [TestMethod(IgnoreMessage = "This test method is ignored")] - public void TestMethod1() - { - } - - [TestMethod] - public void TestMethod2() - { - } -} - [TestClass] public class TestClassWithDataSourcesUsingIgnoreMessage {