diff --git a/.editorconfig b/.editorconfig
index e323c80086..fd9640b60c 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -132,7 +132,7 @@ dotnet_diagnostic.IDE0020.severity = warning # IDE0020: IDE0038: Use
dotnet_diagnostic.IDE0028.severity = warning # IDE0028: Simplify collection initialization
dotnet_diagnostic.IDE0031.severity = warning # IDE0031: Use null propagation
dotnet_style_null_propagation = true:warning # IDE0031: Use null propagation
-dotnet_diagnostic.IDE0032.severity = warning # IDE0032: Use auto-implemented property
+dotnet_diagnostic.IDE0032.severity = none # IDE0032: Use auto-implemented property
dotnet_diagnostic.IDE0034.severity = warning # IDE0034: Simplify 'default' expression
dotnet_diagnostic.IDE0035.severity = warning # IDE0035: Remove unreachable code
dotnet_diagnostic.IDE0036.severity = warning # IDE0036: Order modifiers
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 299e8fb283..4b903f1fca 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,7 +4,7 @@
true
- 8.1.0
+ 8.2.217.10.0-preview-24127-033.11.0-beta1.24318.13.11.0
@@ -13,8 +13,8 @@
6.2.14
- 17.11.0
- 1.45.1
+ 17.11.1
+ 1.49.04.3.14.3.1
@@ -58,6 +58,8 @@
+
+
@@ -68,7 +70,7 @@
-
+
diff --git a/NuGet.config b/NuGet.config
index b5ce5f5511..604a77d5c4 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -5,6 +5,11 @@
+
+
+
+
+
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index ec849267ca..dd4e180899 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -13,17 +13,17 @@
https://github.com/dotnet/arcaded7f6456959c71512dd68e03021e0aadd8e27d025
-
+ https://dev.azure.com/devdiv/DevDiv/_git/vs-code-coverage
- 80038c362167aceeeeaed68854d8328be9bebc2a
+ 1406857e7a6df8189656aeb9ae2a75bfc402c65f
-
+ https://github.com/microsoft/testanywhere
- d5261d64cc99fd929f1ad7ba93de50af7b8e4608
+ b6b5c94527b35464e9ffaf471aef378f76888f76
-
+ https://github.com/microsoft/testanywhere
- d5261d64cc99fd929f1ad7ba93de50af7b8e4608
+ b6b5c94527b35464e9ffaf471aef378f76888f76
diff --git a/eng/Versions.props b/eng/Versions.props
index 63686d20c5..0135a7e88f 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -1,16 +1,16 @@
- 3.6.0
+ 3.6.4
- 1.4.0
+ 1.4.3preview10.0.0-beta.24429.6
- 17.12.4
+ 17.13.1
- 1.4.0
- 1.0.0-alpha.24460.4
+ 1.4.3
+ 1.0.0-alpha.24562.1
diff --git a/eng/verify-nupkgs.ps1 b/eng/verify-nupkgs.ps1
index 20c72088ff..d119680355 100644
--- a/eng/verify-nupkgs.ps1
+++ b/eng/verify-nupkgs.ps1
@@ -22,7 +22,7 @@ function Confirm-NugetPackages {
"MSTest.Sdk" = 15;
"MSTest.Internal.TestFx.Documentation" = 10;
"MSTest.TestFramework" = 130;
- "MSTest.TestAdapter" = 167;
+ "MSTest.TestAdapter" = 76;
"MSTest" = 6;
"MSTest.Analyzers" = 10;
}
diff --git a/global.json b/global.json
index b49cd4628a..aa3eb167a6 100644
--- a/global.json
+++ b/global.json
@@ -4,15 +4,15 @@
"runtimes": {
"dotnet": [
"3.1.32",
- "6.0.33",
+ "6.0.36",
"7.0.20",
- "8.0.8"
+ "8.0.11"
],
"dotnet/x86": [
- "8.0.8"
+ "8.0.11"
],
"aspnetcore": [
- "8.0.8"
+ "8.0.11"
]
},
"vs": {
diff --git a/src/Adapter/MSTest.TestAdapter/Execution/TestRunCancellationToken.cs b/src/Adapter/MSTest.TestAdapter/Execution/TestRunCancellationToken.cs
index eebf71446c..7faaabe606 100644
--- a/src/Adapter/MSTest.TestAdapter/Execution/TestRunCancellationToken.cs
+++ b/src/Adapter/MSTest.TestAdapter/Execution/TestRunCancellationToken.cs
@@ -1,6 +1,8 @@
// 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.Concurrent;
+
namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter;
///
@@ -10,8 +12,9 @@ public class TestRunCancellationToken
{
///
/// Callbacks to be invoked when canceled.
+ /// Needs to be a concurrent collection, see https://github.com/microsoft/testfx/issues/3953.
///
- private readonly List _registeredCallbacks = new();
+ private readonly ConcurrentBag _registeredCallbacks = new();
///
/// Stores whether the test run is canceled or not.
@@ -63,7 +66,17 @@ private set
///
/// Unregister the callback method.
///
- public void Unregister() => _registeredCallbacks.Clear();
+ public void Unregister()
+#if NETCOREAPP || WINDOWS_UWP
+ => _registeredCallbacks.Clear();
+#else
+ {
+ while (!_registeredCallbacks.IsEmpty)
+ {
+ _ = _registeredCallbacks.TryTake(out _);
+ }
+ }
+#endif
internal void ThrowIfCancellationRequested()
{
diff --git a/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.nuspec b/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.nuspec
index b09aba1d05..b9842b3993 100644
--- a/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.nuspec
+++ b/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.nuspec
@@ -93,8 +93,8 @@
-
-
+
+
diff --git a/src/Adapter/MSTest.TestAdapter/build/common/MSTest.TestAdapter.props b/src/Adapter/MSTest.TestAdapter/build/common/MSTest.TestAdapter.props
index aa75379c85..5d661becfe 100644
--- a/src/Adapter/MSTest.TestAdapter/build/common/MSTest.TestAdapter.props
+++ b/src/Adapter/MSTest.TestAdapter/build/common/MSTest.TestAdapter.props
@@ -12,7 +12,7 @@
DO NOT CHANGE THE GUID, IT'S A WELL KNOWN EXTENSION POINT AND THIS EXTENSION NEEDS TO BE REGISTERED AT THE END
WE HAVE CODE INSIDE THE TASK 'TestingPlatformEntryPoint' TO ENSURE THE ORDER OF THE REGISTRATION BASED ON THIS GUID
-->
-
+ MSTestMicrosoft.VisualStudio.TestTools.UnitTesting.TestingPlatformBuilderHook
diff --git a/src/Adapter/MSTest.TestAdapter/build/net/MSTest.TestAdapter.targets b/src/Adapter/MSTest.TestAdapter/build/net/MSTest.TestAdapter.targets
index 05548ac62e..f3ef87d399 100644
--- a/src/Adapter/MSTest.TestAdapter/build/net/MSTest.TestAdapter.targets
+++ b/src/Adapter/MSTest.TestAdapter/build/net/MSTest.TestAdapter.targets
@@ -73,18 +73,18 @@
-
- %(CurrentUICultureHierarchy.Identity)
-
+
-
+
+ %(CurrentUICultureHierarchy.Identity)
+
-
- $(CurrentUICultureHierarchy)\%(FileName).resources.dll
+
+
+ %(MSTestV2Files.UICulture)\%(FileName).dll
PreserveNewest%(FullPath)False
diff --git a/src/Adapter/MSTest.TestAdapter/build/netfx-netcore-netstandard/MSTest.TestAdapter.targets b/src/Adapter/MSTest.TestAdapter/build/netfx-netcore-netstandard/MSTest.TestAdapter.targets
index 106ac5a5da..64fb79bf30 100644
--- a/src/Adapter/MSTest.TestAdapter/build/netfx-netcore-netstandard/MSTest.TestAdapter.targets
+++ b/src/Adapter/MSTest.TestAdapter/build/netfx-netcore-netstandard/MSTest.TestAdapter.targets
@@ -66,14 +66,20 @@
+
+
-
- %(CurrentUICultureHierarchy.Identity)
-
+
+ %(CurrentUICultureHierarchy.Identity)
+
+
-
- %(MSTestV2ResourceFiles.CultureString)\%(Filename)%(Extension)
+
+
+
+ %(MSTestV2Files.UICulture)\%(FileName).dll
PreserveNewest
+ %(FullPath)False
diff --git a/src/Adapter/MSTest.TestAdapter/build/uwp/MSTest.TestAdapter.targets b/src/Adapter/MSTest.TestAdapter/build/uwp/MSTest.TestAdapter.targets
index d8baf21f26..c33b561416 100644
--- a/src/Adapter/MSTest.TestAdapter/build/uwp/MSTest.TestAdapter.targets
+++ b/src/Adapter/MSTest.TestAdapter/build/uwp/MSTest.TestAdapter.targets
@@ -29,19 +29,20 @@
-
- %(CurrentUICultureHierarchy.Identity)
-
-
+
-
-
+
+ %(CurrentUICultureHierarchy.Identity)
+
+
+ %(CurrentUICultureHierarchy.Identity)
+
-
- $(CurrentUICultureHierarchy)\%(FileName).resources.dll
+
+
+ %(MSTestV2Files.UICulture)\%(FileName).dll
PreserveNewest%(FullPath)False
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.cs b/src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.cs
index 06d9a359a4..53a2a392b1 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.cs
+++ b/src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.cs
@@ -376,7 +376,15 @@ protected virtual
// the ResourceHelper's currentlyLoading stack to null if an exception occurs.
if (s_currentlyLoading != null && s_currentlyLoading.Count > 0 && s_currentlyLoading.LastIndexOf(assemblyPath) != -1)
{
- EqtTrace.Info("MSTest.AssemblyResolver.OnResolve: Assembly '{0}' is searching for itself recursively '{1}', returning as not found.", name, assemblyPath);
+ SafeLog(
+ name,
+ () =>
+ {
+ if (EqtTrace.IsInfoEnabled)
+ {
+ EqtTrace.Info("MSTest.AssemblyResolver.OnResolve: Assembly '{0}' is searching for itself recursively '{1}', returning as not found.", name, assemblyPath);
+ }
+ });
_resolvedAssemblies[name] = null;
return null;
}
diff --git a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Shipped.md b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Shipped.md
index 98a82d5743..5ce49d10bb 100644
--- a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Shipped.md
+++ b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Shipped.md
@@ -1,4 +1,15 @@
-## Release 3.5.0
+## Release 3.6.0
+
+### New Rules
+
+Rule ID | Category | Severity | Notes
+--------|----------|----------|-------
+MSTEST0018 | Usage | Warning | DynamicDataShouldBeValidAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0018)
+MSTEST0034 | Usage | Info | UseClassCleanupBehaviorEndOfClassAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0034)
+MSTEST0035 | Usage | Info | UseDeploymentItemWithTestMethodOrTestClassAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0035)
+MSTEST0036 | Design | Warning | DoNotUseShadowingAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0036)
+
+## Release 3.5.0
### New Rules
diff --git a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md
index d028872578..6eea619003 100644
--- a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md
+++ b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md
@@ -1,10 +1,2 @@
; Unshipped analyzer release
; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
-### New Rules
-
-Rule ID | Category | Severity | Notes
---------|----------|----------|-------
-MSTEST0018 | Usage | Warning | DynamicDataShouldBeValidAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0018)
-MSTEST0034 | Usage | Info | UseClassCleanupBehaviorEndOfClassAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0034)
-MSTEST0035 | Usage | Info | UseDeploymentItemWithTestMethodOrTestClassAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0035)
-MSTEST0036 | Design | Warning | DoNotUseShadowingAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0036)
diff --git a/src/Analyzers/MSTest.Analyzers/DoNotUseShadowingAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/DoNotUseShadowingAnalyzer.cs
index 5fba21395b..abbefd8916 100644
--- a/src/Analyzers/MSTest.Analyzers/DoNotUseShadowingAnalyzer.cs
+++ b/src/Analyzers/MSTest.Analyzers/DoNotUseShadowingAnalyzer.cs
@@ -112,7 +112,8 @@ private static bool IsMemberShadowing(ISymbol member, ISymbol baseMember)
}
// Compare methods
- if (member is IMethodSymbol methodSymbol && baseMember is IMethodSymbol baseMethodSymbol)
+ if (member is IMethodSymbol methodSymbol && baseMember is IMethodSymbol baseMethodSymbol && methodSymbol.IsGenericMethod == baseMethodSymbol.IsGenericMethod
+ && !(methodSymbol.DeclaredAccessibility == Accessibility.Private && baseMethodSymbol.DeclaredAccessibility == Accessibility.Private))
{
return methodSymbol.Name == baseMethodSymbol.Name &&
methodSymbol.Parameters.Length == baseMethodSymbol.Parameters.Length &&
diff --git a/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs
index ec3599737a..c92572ebd9 100644
--- a/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs
+++ b/src/Analyzers/MSTest.Analyzers/DynamicDataShouldBeValidAnalyzer.cs
@@ -12,6 +12,9 @@
namespace MSTest.Analyzers;
+///
+/// MSTEST0018: .
+///
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public sealed class DynamicDataShouldBeValidAnalyzer : DiagnosticAnalyzer
{
@@ -202,8 +205,7 @@ private static void AnalyzeDataSource(SymbolAnalysisContext context, AttributeDa
return;
}
- if (!member.IsStatic
- || member.DeclaredAccessibility != Accessibility.Public)
+ if (!member.IsStatic)
{
context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(DataMemberSignatureRule, declaringType.Name, memberName));
return;
@@ -218,23 +220,29 @@ private static void AnalyzeDataSource(SymbolAnalysisContext context, AttributeDa
}
// Validate member return type.
- if (member.GetMemberType() is not INamedTypeSymbol memberType)
+ ITypeSymbol? memberTypeSymbol = member.GetMemberType();
+ if (memberTypeSymbol is INamedTypeSymbol memberNamedType)
{
- return;
- }
+ if (!SymbolEqualityComparer.Default.Equals(memberNamedType.ConstructedFrom, ienumerableTypeSymbol)
+ || memberNamedType.TypeArguments.Length != 1)
+ {
+ context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberTypeRule, declaringType.Name, memberName));
+ return;
+ }
- if (!SymbolEqualityComparer.Default.Equals(memberType.ConstructedFrom, ienumerableTypeSymbol)
- || memberType.TypeArguments.Length != 1)
- {
- context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberTypeRule, declaringType.Name, memberName));
- return;
+ ITypeSymbol collectionBoundType = memberNamedType.TypeArguments[0];
+ if (!collectionBoundType.Inherits(itupleTypeSymbol)
+ && collectionBoundType is not IArrayTypeSymbol)
+ {
+ context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberTypeRule, declaringType.Name, memberName));
+ }
}
-
- ITypeSymbol collectionBoundType = memberType.TypeArguments[0];
- if (!collectionBoundType.Inherits(itupleTypeSymbol)
- && (collectionBoundType is not IArrayTypeSymbol arrayTypeSymbol || arrayTypeSymbol.ElementType.SpecialType != SpecialType.System_Object))
+ else if (memberTypeSymbol is IArrayTypeSymbol arrayType)
{
- context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberTypeRule, declaringType.Name, memberName));
+ if (arrayType.ElementType is not IArrayTypeSymbol)
+ {
+ context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(MemberTypeRule, declaringType.Name, memberName));
+ }
}
}
diff --git a/src/Analyzers/MSTest.Analyzers/PublicAPI.Shipped.txt b/src/Analyzers/MSTest.Analyzers/PublicAPI.Shipped.txt
index 4d8fce9705..681365b958 100644
--- a/src/Analyzers/MSTest.Analyzers/PublicAPI.Shipped.txt
+++ b/src/Analyzers/MSTest.Analyzers/PublicAPI.Shipped.txt
@@ -23,16 +23,20 @@ MSTest.Analyzers.DoNotNegateBooleanAssertionAnalyzer
MSTest.Analyzers.DoNotNegateBooleanAssertionAnalyzer.DoNotNegateBooleanAssertionAnalyzer() -> void
MSTest.Analyzers.DoNotStoreStaticTestContextAnalyzer
MSTest.Analyzers.DoNotStoreStaticTestContextAnalyzer.DoNotStoreStaticTestContextAnalyzer() -> void
+MSTest.Analyzers.DoNotUseShadowingAnalyzer
+MSTest.Analyzers.DoNotUseShadowingAnalyzer.DoNotUseShadowingAnalyzer() -> void
MSTest.Analyzers.DoNotUseSystemDescriptionAttributeAnalyzer
MSTest.Analyzers.DoNotUseSystemDescriptionAttributeAnalyzer.DoNotUseSystemDescriptionAttributeAnalyzer() -> void
+MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer
+MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer.DynamicDataShouldBeValidAnalyzer() -> void
+MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor
+MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor.NonNullableReferenceNotInitializedSuppressor() -> void
MSTest.Analyzers.PreferAssertFailOverAlwaysFalseConditionsAnalyzer
MSTest.Analyzers.PreferAssertFailOverAlwaysFalseConditionsAnalyzer.PreferAssertFailOverAlwaysFalseConditionsAnalyzer() -> void
MSTest.Analyzers.PreferConstructorOverTestInitializeAnalyzer
MSTest.Analyzers.PreferConstructorOverTestInitializeAnalyzer.PreferConstructorOverTestInitializeAnalyzer() -> void
MSTest.Analyzers.PreferDisposeOverTestCleanupAnalyzer
MSTest.Analyzers.PreferDisposeOverTestCleanupAnalyzer.PreferDisposeOverTestCleanupAnalyzer() -> void
-MSTest.Analyzers.ReviewAlwaysTrueAssertConditionAnalyzer
-MSTest.Analyzers.ReviewAlwaysTrueAssertConditionAnalyzer.ReviewAlwaysTrueAssertConditionAnalyzer() -> void
MSTest.Analyzers.PreferTestCleanupOverDisposeAnalyzer
MSTest.Analyzers.PreferTestCleanupOverDisposeAnalyzer.PreferTestCleanupOverDisposeAnalyzer() -> void
MSTest.Analyzers.PreferTestInitializeOverConstructorAnalyzer
@@ -41,6 +45,8 @@ MSTest.Analyzers.PublicMethodShouldBeTestMethodAnalyzer
MSTest.Analyzers.PublicMethodShouldBeTestMethodAnalyzer.PublicMethodShouldBeTestMethodAnalyzer() -> void
MSTest.Analyzers.PublicTypeShouldBeTestClassAnalyzer
MSTest.Analyzers.PublicTypeShouldBeTestClassAnalyzer.PublicTypeShouldBeTestClassAnalyzer() -> void
+MSTest.Analyzers.ReviewAlwaysTrueAssertConditionAnalyzer
+MSTest.Analyzers.ReviewAlwaysTrueAssertConditionAnalyzer.ReviewAlwaysTrueAssertConditionAnalyzer() -> void
MSTest.Analyzers.TestClassShouldBeValidAnalyzer
MSTest.Analyzers.TestClassShouldBeValidAnalyzer.TestClassShouldBeValidAnalyzer() -> void
MSTest.Analyzers.TestClassShouldHaveTestMethodAnalyzer
@@ -63,6 +69,10 @@ MSTest.Analyzers.UseAsyncSuffixTestMethodSuppressor
MSTest.Analyzers.UseAsyncSuffixTestMethodSuppressor.UseAsyncSuffixTestMethodSuppressor() -> void
MSTest.Analyzers.UseAttributeOnTestMethodAnalyzer
MSTest.Analyzers.UseAttributeOnTestMethodAnalyzer.UseAttributeOnTestMethodAnalyzer() -> void
+MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer
+MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer.UseClassCleanupBehaviorEndOfClassAnalyzer() -> void
+MSTest.Analyzers.UseDeploymentItemWithTestMethodOrTestClassAnalyzer
+MSTest.Analyzers.UseDeploymentItemWithTestMethodOrTestClassAnalyzer.UseDeploymentItemWithTestMethodOrTestClassAnalyzer() -> void
MSTest.Analyzers.UseParallelizeAttributeAnalyzer
MSTest.Analyzers.UseParallelizeAttributeAnalyzer.UseParallelizeAttributeAnalyzer() -> void
override MSTest.Analyzers.AssemblyCleanupShouldBeValidAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
@@ -85,16 +95,20 @@ override MSTest.Analyzers.DoNotNegateBooleanAssertionAnalyzer.Initialize(Microso
override MSTest.Analyzers.DoNotNegateBooleanAssertionAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.DoNotStoreStaticTestContextAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
override MSTest.Analyzers.DoNotStoreStaticTestContextAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
+override MSTest.Analyzers.DoNotUseShadowingAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
+override MSTest.Analyzers.DoNotUseShadowingAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.DoNotUseSystemDescriptionAttributeAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
override MSTest.Analyzers.DoNotUseSystemDescriptionAttributeAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
+override MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
+override MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
+override MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor.ReportSuppressions(Microsoft.CodeAnalysis.Diagnostics.SuppressionAnalysisContext context) -> void
+override MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor.SupportedSuppressions.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.PreferAssertFailOverAlwaysFalseConditionsAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
override MSTest.Analyzers.PreferAssertFailOverAlwaysFalseConditionsAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.PreferConstructorOverTestInitializeAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
override MSTest.Analyzers.PreferConstructorOverTestInitializeAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.PreferDisposeOverTestCleanupAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
override MSTest.Analyzers.PreferDisposeOverTestCleanupAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
-override MSTest.Analyzers.ReviewAlwaysTrueAssertConditionAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
-override MSTest.Analyzers.ReviewAlwaysTrueAssertConditionAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.PreferTestCleanupOverDisposeAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
override MSTest.Analyzers.PreferTestCleanupOverDisposeAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.PreferTestInitializeOverConstructorAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
@@ -103,6 +117,8 @@ override MSTest.Analyzers.PublicMethodShouldBeTestMethodAnalyzer.Initialize(Micr
override MSTest.Analyzers.PublicMethodShouldBeTestMethodAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.PublicTypeShouldBeTestClassAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
override MSTest.Analyzers.PublicTypeShouldBeTestClassAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
+override MSTest.Analyzers.ReviewAlwaysTrueAssertConditionAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
+override MSTest.Analyzers.ReviewAlwaysTrueAssertConditionAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.TestClassShouldBeValidAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
override MSTest.Analyzers.TestClassShouldBeValidAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.TestClassShouldHaveTestMethodAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
@@ -125,6 +141,10 @@ override MSTest.Analyzers.UseAsyncSuffixTestMethodSuppressor.ReportSuppressions(
override MSTest.Analyzers.UseAsyncSuffixTestMethodSuppressor.SupportedSuppressions.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.UseAttributeOnTestMethodAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
override MSTest.Analyzers.UseAttributeOnTestMethodAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
+override MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
+override MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
+override MSTest.Analyzers.UseDeploymentItemWithTestMethodOrTestClassAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
+override MSTest.Analyzers.UseDeploymentItemWithTestMethodOrTestClassAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
override MSTest.Analyzers.UseParallelizeAttributeAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
override MSTest.Analyzers.UseParallelizeAttributeAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
static Analyzer.Utilities.WellKnownTypeProvider.GetOrCreate(Microsoft.CodeAnalysis.Compilation! compilation) -> Analyzer.Utilities.WellKnownTypeProvider!
diff --git a/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt b/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt
index ec974803bd..ab058de62d 100644
--- a/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt
+++ b/src/Analyzers/MSTest.Analyzers/PublicAPI.Unshipped.txt
@@ -1,21 +1 @@
#nullable enable
-MSTest.Analyzers.DoNotUseShadowingAnalyzer
-MSTest.Analyzers.DoNotUseShadowingAnalyzer.DoNotUseShadowingAnalyzer() -> void
-MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer
-MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer.DynamicDataShouldBeValidAnalyzer() -> void
-MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor
-MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor.NonNullableReferenceNotInitializedSuppressor() -> void
-MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer
-MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer.UseClassCleanupBehaviorEndOfClassAnalyzer() -> void
-MSTest.Analyzers.UseDeploymentItemWithTestMethodOrTestClassAnalyzer
-MSTest.Analyzers.UseDeploymentItemWithTestMethodOrTestClassAnalyzer.UseDeploymentItemWithTestMethodOrTestClassAnalyzer() -> void
-override MSTest.Analyzers.DoNotUseShadowingAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
-override MSTest.Analyzers.DoNotUseShadowingAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
-override MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
-override MSTest.Analyzers.DynamicDataShouldBeValidAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
-override MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor.ReportSuppressions(Microsoft.CodeAnalysis.Diagnostics.SuppressionAnalysisContext context) -> void
-override MSTest.Analyzers.NonNullableReferenceNotInitializedSuppressor.SupportedSuppressions.get -> System.Collections.Immutable.ImmutableArray
-override MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
-override MSTest.Analyzers.UseClassCleanupBehaviorEndOfClassAnalyzer.SupportedDiagnostics.get -> System.Collections.Immutable.ImmutableArray
-override MSTest.Analyzers.UseDeploymentItemWithTestMethodOrTestClassAnalyzer.Initialize(Microsoft.CodeAnalysis.Diagnostics.AnalysisContext! context) -> void
-override MSTest.Analyzers.UseDeploymentItemWithTestMethodOrTestClassAnalyzer.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 a35b887759..7855473260 100644
--- a/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs
+++ b/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs
@@ -375,7 +375,7 @@ internal static string DoNotUseShadowingDescription {
}
///
- /// Looks up a localized string similar to Member '{0}' is already exist in the base class.
+ /// Looks up a localized string similar to Member '{0}' already exists in the base class.
///
internal static string DoNotUseShadowingMessageFormat {
get {
@@ -714,7 +714,7 @@ internal static string TestClassShouldBeValidTitle {
}
///
- /// Looks up a localized string similar to Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'..
+ /// Looks up a localized string similar to Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'..
///
internal static string TestClassShouldHaveTestMethodDescription {
get {
@@ -723,7 +723,7 @@ internal static string TestClassShouldHaveTestMethodDescription {
}
///
- /// Looks up a localized string similar to Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
+ /// Looks up a localized string similar to Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
///
internal static string TestClassShouldHaveTestMethodMessageFormat {
get {
diff --git a/src/Analyzers/MSTest.Analyzers/Resources.resx b/src/Analyzers/MSTest.Analyzers/Resources.resx
index 45f62cdbf0..ff98060e2e 100644
--- a/src/Analyzers/MSTest.Analyzers/Resources.resx
+++ b/src/Analyzers/MSTest.Analyzers/Resources.resx
@@ -329,10 +329,10 @@ The type declaring these methods should also respect the following rules:
Test classes should have valid layout
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'Test class should have test method
@@ -524,7 +524,7 @@ The type declaring these methods should also respect the following rules:
Shadowing test members could cause testing issues (such as NRE).
- Member '{0}' is already exist in the base class
+ Member '{0}' already exists in the base classDo not use shadowing
diff --git a/src/Analyzers/MSTest.Analyzers/TypeContainingTestMethodShouldBeATestClassAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/TypeContainingTestMethodShouldBeATestClassAnalyzer.cs
index f89aa288f8..da57e4d3cc 100644
--- a/src/Analyzers/MSTest.Analyzers/TypeContainingTestMethodShouldBeATestClassAnalyzer.cs
+++ b/src/Analyzers/MSTest.Analyzers/TypeContainingTestMethodShouldBeATestClassAnalyzer.cs
@@ -77,7 +77,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo
bool hasTestMethod = false;
INamedTypeSymbol? currentType = namedTypeSymbol;
- do
+ while (currentType is not null && !hasTestMethod)
{
foreach (ISymbol classMember in currentType.GetMembers())
{
@@ -94,16 +94,10 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo
break;
}
}
-
- if (!hasTestMethod)
- {
- break;
- }
}
currentType = currentType.BaseType;
}
- while (currentType is not null && !hasTestMethod);
if (!hasTestMethod)
{
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf
index 28e78c38ad..91af9e06a1 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf
@@ -287,8 +287,8 @@ Typ deklarující tyto metody by měl také respektovat následující pravidla:
- Member '{0}' is already exist in the base class
- Člen {0} už v základní (kořenové) třídě existuje.
+ Member '{0}' already exists in the base class
+ Člen {0} už v základní (kořenové) třídě existuje.
@@ -509,13 +509,13 @@ Typ deklarující tyto metody by měl také respektovat následující pravidla:
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- Testovací třída by měla mít aspoň jednu testovací metodu nebo by měla být static s metodami s označením [AssemblyInitialization] a/nebo [AssemblyCleanup].
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ Testovací třída by měla mít aspoň jednu testovací metodu nebo by měla být static s metodami s označením [AssemblyInitialization] a/nebo [AssemblyCleanup].
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- Testovací třída {0} by měla mít aspoň jednu testovací metodu nebo by měla být static s metodami s označením [AssemblyInitialization] a/nebo [AssemblyCleanup].
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ Testovací třída {0} by měla mít aspoň jednu testovací metodu nebo by měla být static s metodami s označením [AssemblyInitialization] a/nebo [AssemblyCleanup].
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf
index c48b85d8d1..202b00cd98 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf
@@ -289,8 +289,8 @@ Der Typ, der diese Methoden deklariert, sollte auch die folgenden Regeln beachte
- Member '{0}' is already exist in the base class
- Der Member "{0}" ist bereits in der Basisklasse vorhanden.
+ Member '{0}' already exists in the base class
+ Der Member "{0}" ist bereits in der Basisklasse vorhanden.
@@ -511,13 +511,13 @@ Der Typ, der diese Methoden deklariert, sollte auch die folgenden Regeln beachte
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- Die Testklasse muss mindestens eine Testmethode aufweisen oder "statisch" sein, wenn Methoden mit "[AssemblyInitialization]" und/oder "[AssemblyCleanup]" markiert sind.
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ Die Testklasse muss mindestens eine Testmethode aufweisen oder "statisch" sein, wenn Methoden mit "[AssemblyInitialization]" und/oder "[AssemblyCleanup]" markiert sind.
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- Die Testklasse "{0}" muss mindestens eine Testmethode aufweisen oder "statisch" sein, wenn Methoden mit "[AssemblyInitialization]" und/oder "[AssemblyCleanup]" markiert sind.
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ Die Testklasse "{0}" muss mindestens eine Testmethode aufweisen oder "statisch" sein, wenn Methoden mit "[AssemblyInitialization]" und/oder "[AssemblyCleanup]" markiert sind.
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf
index 37085c8208..c5af60c9d1 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf
@@ -287,8 +287,8 @@ El tipo que declara estos métodos también debe respetar las reglas siguientes:
- Member '{0}' is already exist in the base class
- El miembro ''{0}'' ya existe en la clase base
+ Member '{0}' already exists in the base class
+ El miembro ''{0}'' ya existe en la clase base
@@ -509,13 +509,13 @@ El tipo que declara estos métodos también debe respetar las reglas siguientes:
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- La clase de prueba debe tener al menos un método de prueba o ser 'static' con métodos marcados por '[AssemblyInitialization]' o '[AssemblyCleanup]'.
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ La clase de prueba debe tener al menos un método de prueba o ser 'static' con métodos marcados por '[AssemblyInitialization]' o '[AssemblyCleanup]'.
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- La clase de prueba '{0}' debe tener al menos un método de prueba o ser 'static' con métodos marcados por '[AssemblyInitialization]' y/o '[AssemblyCleanup]'
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ La clase de prueba '{0}' debe tener al menos un método de prueba o ser 'static' con métodos marcados por '[AssemblyInitialization]' y/o '[AssemblyCleanup]'
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf
index 05eb6b1d86..2ad341b45e 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf
@@ -287,8 +287,8 @@ Le type doit être une classe
- Member '{0}' is already exist in the base class
- Le membre '{0}' existe déjà dans la classe de base
+ Member '{0}' already exists in the base class
+ Le membre '{0}' existe déjà dans la classe de base
@@ -509,13 +509,13 @@ Le type doit être une classe
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- La classe de test doit avoir au moins une méthode de test ou être « statique » avec la ou les méthodes marquées par « [AssemblyInitialization] » et/ou « [AssemblyCleanup] ».
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ La classe de test doit avoir au moins une méthode de test ou être « statique » avec la ou les méthodes marquées par « [AssemblyInitialization] » et/ou « [AssemblyCleanup] ».
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- La classe de test « {0} » doit avoir au moins une méthode de test ou être « statique » avec des méthodes marquées par « [AssemblyInitialization] » et/ou « [AssemblyCleanup] »
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ La classe de test « {0} » doit avoir au moins une méthode de test ou être « statique » avec des méthodes marquées par « [AssemblyInitialization] » et/ou « [AssemblyCleanup] »
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf
index deb3238a00..dc5995df7b 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf
@@ -287,8 +287,8 @@ Anche il tipo che dichiara questi metodi deve rispettare le regole seguenti:
- Member '{0}' is already exist in the base class
- Il membro '{0}' esiste già nella classe di base
+ Member '{0}' already exists in the base class
+ Il membro '{0}' esiste già nella classe di base
@@ -509,13 +509,13 @@ Anche il tipo che dichiara questi metodi deve rispettare le regole seguenti:
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- La classe di test deve avere almeno un metodo di test o essere 'static' con metodi contrassegnati da '[AssemblyInitialization]' e/o '[AssemblyCleanup]'.
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ La classe di test deve avere almeno un metodo di test o essere 'static' con metodi contrassegnati da '[AssemblyInitialization]' e/o '[AssemblyCleanup]'.
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- La classe di test '{0}' deve avere almeno un metodo di test o essere 'static' con metodi contrassegnati da '[AssemblyInitialization]' e/o '[AssemblyCleanup]'
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ La classe di test '{0}' deve avere almeno un metodo di test o essere 'static' con metodi contrassegnati da '[AssemblyInitialization]' e/o '[AssemblyCleanup]'
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf
index 9881713a6d..d747f0efeb 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf
@@ -287,8 +287,8 @@ The type declaring these methods should also respect the following rules:
- Member '{0}' is already exist in the base class
- メンバー '{0}' は既に基本クラスに存在します
+ Member '{0}' already exists in the base class
+ メンバー '{0}' は既に基本クラスに存在します
@@ -509,13 +509,13 @@ The type declaring these methods should also respect the following rules:
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- テスト クラスには、少なくとも 1 つのテスト メソッドがあるか、'[AssemblyInitialization]' または '[AssemblyCleanup]' によってマークされたメソッドを含む 'static' である必要があります。
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ テスト クラスには、少なくとも 1 つのテスト メソッドがあるか、'[AssemblyInitialization]' または '[AssemblyCleanup]' によってマークされたメソッドを含む 'static' である必要があります。
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- テスト クラス '{0}' には、少なくとも 1 つのテスト メソッドがあるか、'[AssemblyInitialization]' または '[AssemblyCleanup]' によってマークされたメソッドを含む 'static' である必要があります。
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ テスト クラス '{0}' には、少なくとも 1 つのテスト メソッドがあるか、'[AssemblyInitialization]' または '[AssemblyCleanup]' によってマークされたメソッドを含む 'static' である必要があります。
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf
index 9d0aecbdd7..37f0993abc 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf
@@ -287,8 +287,8 @@ The type declaring these methods should also respect the following rules:
- Member '{0}' is already exist in the base class
- 멤버 '{0}'이(가) 기본 클래스에 이미 있습니다.
+ Member '{0}' already exists in the base class
+ 멤버 '{0}'이(가) 기본 클래스에 이미 있습니다.
@@ -509,13 +509,13 @@ The type declaring these methods should also respect the following rules:
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- 테스트 클래스에는 하나 이상의 테스트 메서드가 있거나 '[AssemblyInitialization]' 및/또는 '[AssemblyCleanup]'으로 표시된 메서드가 있는 'static'이어야 합니다.
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ 테스트 클래스에는 하나 이상의 테스트 메서드가 있거나 '[AssemblyInitialization]' 및/또는 '[AssemblyCleanup]'으로 표시된 메서드가 있는 'static'이어야 합니다.
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- 테스트 클래스 '{0}'에 하나 이상의 테스트 메서드가 있거나 '[AssemblyInitialization]' 및/또는 '[AssemblyCleanup]'으로 표시된 메서드가 있는 'static'이어야 합니다.
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ 테스트 클래스 '{0}'에 하나 이상의 테스트 메서드가 있거나 '[AssemblyInitialization]' 및/또는 '[AssemblyCleanup]'으로 표시된 메서드가 있는 'static'이어야 합니다.
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf
index 5fe248cf5e..cb152e8552 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf
@@ -287,8 +287,8 @@ Typ deklarujący te metody powinien również przestrzegać następujących regu
- Member '{0}' is already exist in the base class
- Element członkowski „{0}” już istnieje w klasie bazowej
+ Member '{0}' already exists in the base class
+ Element członkowski „{0}” już istnieje w klasie bazowej
@@ -509,13 +509,13 @@ Typ deklarujący te metody powinien również przestrzegać następujących regu
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- Klasa testowa powinna mieć co najmniej jedną metodę testową lub być „statyczna” z metodami oznaczonymi jako „[AssemblyInitialization]” i/lub „[AssemblyCleanup]”.
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ Klasa testowa powinna mieć co najmniej jedną metodę testową lub być „statyczna” z metodami oznaczonymi jako „[AssemblyInitialization]” i/lub „[AssemblyCleanup]”.
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- Klasa testowa „{0}” powinna mieć co najmniej jedną metodę testową lub być „statyczna” z metodami oznaczonymi jako „[AssemblyInitialization]” i/lub „[AssemblyCleanup]”.
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ Klasa testowa „{0}” powinna mieć co najmniej jedną metodę testową lub być „statyczna” z metodami oznaczonymi jako „[AssemblyInitialization]” i/lub „[AssemblyCleanup]”.
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf
index 8080f84e6c..bc30b2c16a 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf
@@ -287,8 +287,8 @@ O tipo que declara esses métodos também deve respeitar as seguintes regras:
- Member '{0}' is already exist in the base class
- O membro "{0}" já existe na classe base
+ Member '{0}' already exists in the base class
+ O membro "{0}" já existe na classe base
@@ -509,13 +509,13 @@ O tipo que declara esses métodos também deve respeitar as seguintes regras:
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- A classe de teste deve ter pelo menos um método de teste ou ser "static" com métodos marcados por "[AssemblyInitialization]" e/ou "[AssemblyCleanup]".
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ A classe de teste deve ter pelo menos um método de teste ou ser "static" com métodos marcados por "[AssemblyInitialization]" e/ou "[AssemblyCleanup]".
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- A classe de teste "{0}" deve ter pelo menos um método de teste ou ser "static" com métodos marcados por "[AssemblyInitialization]" e/ou "[AssemblyCleanup]"
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ A classe de teste "{0}" deve ter pelo menos um método de teste ou ser "static" com métodos marcados por "[AssemblyInitialization]" e/ou "[AssemblyCleanup]"
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf
index 808487d6d1..0c5c99ba71 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf
@@ -291,8 +291,8 @@ The type declaring these methods should also respect the following rules:
- Member '{0}' is already exist in the base class
- Элемент "{0}" уже существует в базовом классе
+ Member '{0}' already exists in the base class
+ Элемент "{0}" уже существует в базовом классе
@@ -513,13 +513,13 @@ The type declaring these methods should also respect the following rules:
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- Тестовый класс должен содержать хотя бы один тестовый метод или быть "статическим" с методами, отмеченными "[AssemblyInitialization]" или "[AssemblyCleanup]".
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ Тестовый класс должен содержать хотя бы один тестовый метод или быть "статическим" с методами, отмеченными "[AssemblyInitialization]" или "[AssemblyCleanup]".
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- Тестовый класс "{0}" должен содержать хотя бы один тестовый метод или быть "статическим" с методами, отмеченными "[AssemblyInitialization]" или "[AssemblyCleanup]"
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ Тестовый класс "{0}" должен содержать хотя бы один тестовый метод или быть "статическим" с методами, отмеченными "[AssemblyInitialization]" или "[AssemblyCleanup]"
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf
index f416bdb63e..08688d9799 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf
@@ -287,8 +287,8 @@ Bu yöntemleri bildiren tipin ayrıca aşağıdaki kurallara uyması gerekir:
- Member '{0}' is already exist in the base class
- Üye '{0}' zaten temel sınıfta var
+ Member '{0}' already exists in the base class
+ Üye '{0}' zaten temel sınıfta var
@@ -510,13 +510,13 @@ Bu yöntemleri bildiren tipin ayrıca aşağıdaki kurallara uyması gerekir:
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- Test sınıfı en az bir test yöntemine sahip olmalıdır veya '[AssemblyInitialization]' ve/veya '[AssemblyCleanup]' ile işaretlenen yöntemlere sahip 'static' olmalıdır.
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ Test sınıfı en az bir test yöntemine sahip olmalıdır veya '[AssemblyInitialization]' ve/veya '[AssemblyCleanup]' ile işaretlenen yöntemlere sahip 'static' olmalıdır.
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- '{0}' test sınıfı en az bir test yöntemine sahip olmalıdır veya '[AssemblyInitialization]' ve/veya '[AssemblyCleanup]' ile işaretlenen yöntemlere sahip 'static' olmalıdır
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ '{0}' test sınıfı en az bir test yöntemine sahip olmalıdır veya '[AssemblyInitialization]' ve/veya '[AssemblyCleanup]' ile işaretlenen yöntemlere sahip 'static' olmalıdır
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf
index d5773a770e..85fae7d2fd 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf
@@ -287,8 +287,8 @@ The type declaring these methods should also respect the following rules:
- Member '{0}' is already exist in the base class
- 基类中已存在成员“{0}”
+ Member '{0}' already exists in the base class
+ 基类中已存在成员“{0}”
@@ -509,13 +509,13 @@ The type declaring these methods should also respect the following rules:
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- 测试类应至少有一个测试方法,或者应为 "static" 且方法带有 "[AssemblyInitialization]" 和/或 "[AssemblyInitialization]"。
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ 测试类应至少有一个测试方法,或者应为 "static" 且方法带有 "[AssemblyInitialization]" 和/或 "[AssemblyInitialization]"。
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- 测试类“{0}”应至少有一个测试方法,或者应为 "static" 且方法带有 "[AssemblyInitialization]" 和/或 "[AssemblyInitialization]"。
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ 测试类“{0}”应至少有一个测试方法,或者应为 "static" 且方法带有 "[AssemblyInitialization]" 和/或 "[AssemblyInitialization]"。
diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf
index de3e6c057c..04320e91d8 100644
--- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf
+++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf
@@ -287,8 +287,8 @@ The type declaring these methods should also respect the following rules:
- Member '{0}' is already exist in the base class
- 成員 '{0}' 已存在於基類中
+ Member '{0}' already exists in the base class
+ 成員 '{0}' 已存在於基類中
@@ -509,13 +509,13 @@ The type declaring these methods should also respect the following rules:
- Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'.
- 測試類別至少應有一個測試方法,或是方法以 '[AssemblyInitialization]' 和/或 '[AssemblyCleanup]' 標示的 'static'。
+ Test class should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'.
+ 測試類別至少應有一個測試方法,或是方法以 '[AssemblyInitialization]' 和/或 '[AssemblyCleanup]' 標示的 'static'。
- Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialization]' and/or '[AssemblyCleanup]'
- 測試類別 '{0}' 至少應有一個測試方法,或是方法以 '[AssemblyInitialization]' 和/或 '[AssemblyCleanup]' 標示的 'static'。
+ Test class '{0}' should have at least one test method or be 'static' with method(s) marked by '[AssemblyInitialize]' and/or '[AssemblyCleanup]'
+ 測試類別 '{0}' 至少應有一個測試方法,或是方法以 '[AssemblyInitialization]' 和/或 '[AssemblyCleanup]' 標示的 'static'。
diff --git a/src/Platform/Microsoft.Testing.Extensions.HangDump/HangDumpActivityIndicator.cs b/src/Platform/Microsoft.Testing.Extensions.HangDump/HangDumpActivityIndicator.cs
index c6bd66c240..aeff5caa2a 100644
--- a/src/Platform/Microsoft.Testing.Extensions.HangDump/HangDumpActivityIndicator.cs
+++ b/src/Platform/Microsoft.Testing.Extensions.HangDump/HangDumpActivityIndicator.cs
@@ -35,7 +35,7 @@ internal sealed class HangDumpActivityIndicator : IDataConsumer, ITestSessionLif
private readonly ManualResetEventSlim _signalActivity = new(false);
private readonly ManualResetEventSlim _mutexCreated = new(false);
private readonly bool _traceLevelEnabled;
- private readonly ConcurrentDictionary _testsCurrentExecutionState = new();
+ private readonly ConcurrentDictionary _testsCurrentExecutionState = new();
private Task? _signalActivityIndicatorTask;
private Mutex? _activityIndicatorMutex;
@@ -143,7 +143,7 @@ private async Task CallbackAsync(IRequest request)
if (request is GetInProgressTestsRequest)
{
await _logger.LogDebugAsync($"Received '{nameof(GetInProgressTestsRequest)}'");
- return new GetInProgressTestsResponse(_testsCurrentExecutionState.Select(x => (x.Key, (int)_clock.UtcNow.Subtract(x.Value.Item2).TotalSeconds)).ToArray());
+ return new GetInProgressTestsResponse(_testsCurrentExecutionState.Select(x => (x.Value.Name, (int)_clock.UtcNow.Subtract(x.Value.StartTime).TotalSeconds)).ToArray());
}
else if (request is ExitSignalActivityIndicatorTaskRequest)
{
@@ -173,14 +173,14 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
await _logger.LogTraceAsync($"New in-progress test '{nodeChangedMessage.TestNode.DisplayName}'");
}
- _testsCurrentExecutionState.TryAdd(nodeChangedMessage.TestNode.DisplayName, (typeof(InProgressTestNodeStateProperty), _clock.UtcNow));
+ _testsCurrentExecutionState.TryAdd(nodeChangedMessage.TestNode.Uid, (nodeChangedMessage.TestNode.DisplayName, typeof(InProgressTestNodeStateProperty), _clock.UtcNow));
}
else if (state is PassedTestNodeStateProperty or ErrorTestNodeStateProperty or CancelledTestNodeStateProperty
or FailedTestNodeStateProperty or TimeoutTestNodeStateProperty or SkippedTestNodeStateProperty
- && _testsCurrentExecutionState.TryRemove(nodeChangedMessage.TestNode.DisplayName, out (Type, DateTimeOffset) record)
+ && _testsCurrentExecutionState.TryRemove(nodeChangedMessage.TestNode.Uid, out (string Name, Type Type, DateTimeOffset StartTime) record)
&& _traceLevelEnabled)
{
- await _logger.LogTraceAsync($"Test removed from in-progress list '{nodeChangedMessage.TestNode.DisplayName}' after '{_clock.UtcNow.Subtract(record.Item2)}', total in-progress '{_testsCurrentExecutionState.Count}'");
+ await _logger.LogTraceAsync($"Test removed from in-progress list '{record.Name}' after '{_clock.UtcNow.Subtract(record.StartTime)}', total in-progress '{_testsCurrentExecutionState.Count}'");
}
// Optimization, we're interested in test progression and eventually in the discovery progression
diff --git a/src/Platform/Microsoft.Testing.Extensions.HangDump/HangDumpProcessLifetimeHandler.cs b/src/Platform/Microsoft.Testing.Extensions.HangDump/HangDumpProcessLifetimeHandler.cs
index f1f702c90e..e09eab94e6 100644
--- a/src/Platform/Microsoft.Testing.Extensions.HangDump/HangDumpProcessLifetimeHandler.cs
+++ b/src/Platform/Microsoft.Testing.Extensions.HangDump/HangDumpProcessLifetimeHandler.cs
@@ -2,6 +2,9 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Globalization;
+#if NETCOREAPP
+using System.Runtime.InteropServices;
+#endif
using Microsoft.Testing.Extensions.Diagnostics.Resources;
using Microsoft.Testing.Extensions.HangDump.Serializers;
@@ -362,6 +365,13 @@ private async Task TakeDumpAsync()
_ => throw ApplicationStateGuard.Unreachable(),
};
+ // Wrap the dump path into "" when it has space in it, this is a workaround for this runtime issue: https://github.com/dotnet/diagnostics/issues/5020
+ // It only affects windows. Otherwise the dump creation fails with: [createdump] The pid argument is no longer supported
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && finalDumpFileName.Contains(' '))
+ {
+ finalDumpFileName = $"\"{finalDumpFileName}\"";
+ }
+
diagnosticsClient.WriteDump(dumpType, finalDumpFileName, true);
#else
MiniDumpWriteDump.MiniDumpTypeOption miniDumpTypeOption = _dumpType.ToLowerInvariant().Trim() switch
diff --git a/src/Platform/Microsoft.Testing.Platform.MSBuild/Tasks/TestingPlatformAutoRegisteredExtensions.cs b/src/Platform/Microsoft.Testing.Platform.MSBuild/Tasks/TestingPlatformAutoRegisteredExtensions.cs
index afc5755114..a1ce5ff9df 100644
--- a/src/Platform/Microsoft.Testing.Platform.MSBuild/Tasks/TestingPlatformAutoRegisteredExtensions.cs
+++ b/src/Platform/Microsoft.Testing.Platform.MSBuild/Tasks/TestingPlatformAutoRegisteredExtensions.cs
@@ -174,7 +174,7 @@ private static string GetSourceCode(string language, string extensionsFragments)
//------------------------------------------------------------------------------
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
-public static class SelfRegisteredExtensions
+internal static class SelfRegisteredExtensions
{
public static void AddSelfRegisteredExtensions(this global::Microsoft.Testing.Platform.Builder.ITestApplicationBuilder builder, string[] args)
{
@@ -193,7 +193,7 @@ public static void AddSelfRegisteredExtensions(this global::Microsoft.Testing.Pl
'------------------------------------------------------------------------------
-Public Module SelfRegisteredExtensions
+Friend Module SelfRegisteredExtensions
Public Sub AddSelfRegisteredExtensions(ByVal builder As Global.Microsoft.Testing.Platform.Builder.ITestApplicationBuilder, ByVal args As Global.System.String())
diff --git a/src/Platform/Microsoft.Testing.Platform.MSBuild/buildMultiTargeting/Microsoft.Testing.Platform.MSBuild.targets b/src/Platform/Microsoft.Testing.Platform.MSBuild/buildMultiTargeting/Microsoft.Testing.Platform.MSBuild.targets
index 37c0a13b02..a8ff84d21d 100644
--- a/src/Platform/Microsoft.Testing.Platform.MSBuild/buildMultiTargeting/Microsoft.Testing.Platform.MSBuild.targets
+++ b/src/Platform/Microsoft.Testing.Platform.MSBuild/buildMultiTargeting/Microsoft.Testing.Platform.MSBuild.targets
@@ -330,4 +330,18 @@
+
+
+
+
+
+
+
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/IHotReloadPlatformOutputDevice.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/IHotReloadPlatformOutputDevice.cs
new file mode 100644
index 0000000000..6ffbff1af4
--- /dev/null
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/IHotReloadPlatformOutputDevice.cs
@@ -0,0 +1,11 @@
+// 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.Testing.Platform.OutputDevice;
+
+internal interface IHotReloadPlatformOutputDevice : IPlatformOutputDevice
+{
+ Task DisplayBeforeHotReloadSessionStartAsync();
+
+ Task DisplayAfterHotReloadSessionEndAsync();
+}
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiCodes.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiCodes.cs
index 08be8b624c..79dc78c804 100644
--- a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiCodes.cs
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiCodes.cs
@@ -16,7 +16,7 @@ internal static class AnsiCodes
///
/// The control sequence introducer.
///
- public const string CSI = "\x1b[";
+ public const string CSI = $"{Esc}[";
///
/// Select graphic rendition.
@@ -24,7 +24,7 @@ internal static class AnsiCodes
///
/// Print color-code to change text color.
///
- public const string SetColor = ";1m";
+ public const string SetColor = "m";
///
/// Select graphic rendition - set bold mode.
@@ -45,17 +45,17 @@ internal static class AnsiCodes
///
/// Print urltext to render a hyperlink.
///
- public const string LinkPrefix = "\x1b]8;;";
+ public const string LinkPrefix = $"{Esc}]8;;";
///
/// .
///
- public const string LinkInfix = "\x1b\\";
+ public const string LinkInfix = $"{Esc}\\";
///
/// .
///
- public const string LinkSuffix = "\x1b]8;;\x1b\\";
+ public const string LinkSuffix = $"{Esc}]8;;{Esc}\\";
///
/// Moves up the specified number of lines and puts cursor at the beginning of the line.
@@ -100,12 +100,12 @@ internal static class AnsiCodes
///
/// Hides the cursor.
///
- public const string HideCursor = "\x1b[?25l";
+ public const string HideCursor = $"{Esc}[?25l";
///
/// Shows/restores the cursor.
///
- public const string ShowCursor = "\x1b[?25h";
+ public const string ShowCursor = $"{Esc}[?25h";
///
/// Set progress state to a busy spinner.
@@ -115,7 +115,7 @@ internal static class AnsiCodes
/// ConEmu specific OSC codes.
/// iTerm2 proprietary escape codes.
///
- public const string SetBusySpinner = "\x1b]9;4;3;\x1b\\";
+ public const string SetBusySpinner = $"{Esc}]9;4;3;{Esc}\\";
///
/// Remove progress state, restoring taskbar status to normal.
@@ -125,7 +125,7 @@ internal static class AnsiCodes
/// ConEmu specific OSC codes.
/// iTerm2 proprietary escape codes.
///
- public const string RemoveBusySpinner = "\x1b]9;4;0;\x1b\\";
+ public const string RemoveBusySpinner = $"{Esc}]9;4;0;{Esc}\\";
public static string Colorize(string? s, TerminalColor color)
=> RoslynString.IsNullOrWhiteSpace(s) ? s ?? string.Empty : $"{CSI}{(int)color}{SetColor}{s}{SetDefaultColor}";
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiTerminal.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiTerminal.cs
index a3e82d9c4d..27576e76c6 100644
--- a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiTerminal.cs
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiTerminal.cs
@@ -235,7 +235,7 @@ public void AppendLink(string? path, int? lineNumber)
urlString = uri.ToString();
}
- SetColor(TerminalColor.Gray);
+ SetColor(TerminalColor.DarkGray);
Append(AnsiCodes.LinkPrefix);
Append(urlString);
Append(AnsiCodes.LinkInfix);
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiTerminalTestProgressFrame.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiTerminalTestProgressFrame.cs
index 1ddd457c42..c2b3d7da46 100644
--- a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiTerminalTestProgressFrame.cs
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/AnsiTerminalTestProgressFrame.cs
@@ -53,7 +53,7 @@ public void AppendTestWorkerProgress(int i, AnsiTerminal terminal)
terminal.Append('[');
charsTaken++;
- terminal.SetColor(TerminalColor.DarkGreen);
+ terminal.SetColor(TerminalColor.Green);
terminal.Append('✓');
charsTaken++;
string passedText = passed.ToString(CultureInfo.CurrentCulture);
@@ -64,7 +64,7 @@ public void AppendTestWorkerProgress(int i, AnsiTerminal terminal)
terminal.Append('/');
charsTaken++;
- terminal.SetColor(TerminalColor.DarkRed);
+ terminal.SetColor(TerminalColor.Red);
terminal.Append('x');
charsTaken++;
string failedText = failed.ToString(CultureInfo.CurrentCulture);
@@ -75,7 +75,7 @@ public void AppendTestWorkerProgress(int i, AnsiTerminal terminal)
terminal.Append('/');
charsTaken++;
- terminal.SetColor(TerminalColor.DarkYellow);
+ terminal.SetColor(TerminalColor.Yellow);
terminal.Append('↓');
charsTaken++;
string skippedText = skipped.ToString(CultureInfo.CurrentCulture);
@@ -177,7 +177,12 @@ public void Render(AnsiTerminalTestProgressFrame previousFrame, AnsiTerminal ter
terminal.MoveCursorUp(previousFrame.ProgressCount + 2);
}
- terminal.AppendLine();
+ // When there is nothing to render, don't write empty lines, e.g. when we start the test run, and then we kick off build
+ // in dotnet test, there is a long pause where we have no assemblies and no test results (yet).
+ if (ProgressCount > 0)
+ {
+ terminal.AppendLine();
+ }
int i = 0;
for (; i < ProgressCount; i++)
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/NonAnsiTerminal.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/NonAnsiTerminal.cs
index 2af7044ad9..519e8431ab 100644
--- a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/NonAnsiTerminal.cs
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/NonAnsiTerminal.cs
@@ -144,9 +144,9 @@ public void StopUpdate()
TerminalColor.DarkBlue => ConsoleColor.DarkBlue,
TerminalColor.DarkMagenta => ConsoleColor.DarkMagenta,
TerminalColor.DarkCyan => ConsoleColor.DarkCyan,
- TerminalColor.DarkWhite => ConsoleColor.White,
+ TerminalColor.Gray => ConsoleColor.White,
TerminalColor.Default => _defaultForegroundColor,
- TerminalColor.Gray => ConsoleColor.Gray,
+ TerminalColor.DarkGray => ConsoleColor.Gray,
TerminalColor.Red => ConsoleColor.Red,
TerminalColor.Green => ConsoleColor.Green,
TerminalColor.Yellow => ConsoleColor.Yellow,
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalColor.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalColor.cs
index bccc7196df..1120f47962 100644
--- a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalColor.cs
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalColor.cs
@@ -14,39 +14,39 @@ internal enum TerminalColor
Black = 30,
///
- /// Red.
+ /// DarkRed.
///
DarkRed = 31,
///
- /// Green.
+ /// DarkGreen.
///
DarkGreen = 32,
///
- /// Yellow.
+ /// DarkYellow.
///
DarkYellow = 33,
///
- /// Blue.
+ /// DarkBlue.
///
DarkBlue = 34,
///
- /// Magenta.
+ /// DarkMagenta.
///
DarkMagenta = 35,
///
- /// Cyan.
+ /// DarkCyan.
///
DarkCyan = 36,
///
- /// White.
+ /// Gray. This entry looks out of order, but in reality 37 is dark white, which is lighter than bright black = Dark Gray in Console colors.
///
- DarkWhite = 37,
+ Gray = 37,
///
/// Default.
@@ -54,9 +54,9 @@ internal enum TerminalColor
Default = 39,
///
- /// Gray.
+ /// DarkGray. This entry looks out of order, but in reality 90 is bright black, which is darker than dark white = Gray in Console colors.
///
- Gray = 90,
+ DarkGray = 90,
///
/// Red.
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.cs
index 6076758537..b695d70a00 100644
--- a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.cs
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.cs
@@ -50,6 +50,8 @@ internal sealed partial class TerminalTestReporter : IDisposable
private bool _wasCancelled;
+ private bool? _shouldShowPassedTests;
+
#if NET7_0_OR_GREATER
[GeneratedRegex(@$"^ at ((?.+) in (?.+):line (?\d+)|(?.+))$", RegexOptions.ExplicitCapture, 1000)]
private static partial Regex GetFrameRegex();
@@ -254,7 +256,7 @@ private void AppendTestRunSummary(ITerminal terminal)
if (!_options.ShowAssembly && _assemblies.Count == 1)
{
TestProgressState testProgressState = _assemblies.Values.Single();
- terminal.SetColor(TerminalColor.Gray);
+ terminal.SetColor(TerminalColor.DarkGray);
terminal.Append(" - ");
terminal.ResetColor();
AppendAssemblyLinkTargetFrameworkAndArchitecture(terminal, testProgressState.Assembly, testProgressState.TargetFramework, testProgressState.Architecture);
@@ -317,7 +319,7 @@ private void AppendTestRunSummary(ITerminal terminal)
if (colorizeSkipped)
{
- terminal.SetColor(TerminalColor.DarkYellow);
+ terminal.SetColor(TerminalColor.Yellow);
}
terminal.AppendLine(skippedText);
@@ -339,7 +341,7 @@ private static void AppendAssemblyResult(ITerminal terminal, bool succeeded, int
{
if (!succeeded)
{
- terminal.SetColor(TerminalColor.DarkRed);
+ terminal.SetColor(TerminalColor.Red);
// If the build failed, we print one of three red strings.
string text = (countErrors > 0, countWarnings > 0) switch
{
@@ -353,13 +355,13 @@ private static void AppendAssemblyResult(ITerminal terminal, bool succeeded, int
}
else if (countWarnings > 0)
{
- terminal.SetColor(TerminalColor.DarkYellow);
+ terminal.SetColor(TerminalColor.Yellow);
terminal.Append($"succeeded with {countWarnings} warning(s)");
terminal.ResetColor();
}
else
{
- terminal.SetColor(TerminalColor.DarkGreen);
+ terminal.SetColor(TerminalColor.Green);
terminal.Append(PlatformResources.PassedLowercase);
terminal.ResetColor();
}
@@ -373,7 +375,7 @@ internal void TestCompleted(
TestOutcome outcome,
TimeSpan duration,
string? errorMessage,
- string? errorStackTrace,
+ Exception? exception,
string? expected,
string? actual)
{
@@ -399,7 +401,7 @@ internal void TestCompleted(
}
_terminalWithProgress.UpdateWorker(asm.SlotIndex);
- if (outcome != TestOutcome.Passed || _options.ShowPassedTests)
+ if (outcome != TestOutcome.Passed || GetShowPassedTests())
{
_terminalWithProgress.WriteToTerminal(terminal => RenderTestCompleted(
terminal,
@@ -410,12 +412,18 @@ internal void TestCompleted(
outcome,
duration,
errorMessage,
- errorStackTrace,
+ exception,
expected,
actual));
}
}
+ private bool GetShowPassedTests()
+ {
+ _shouldShowPassedTests ??= _options.ShowPassedTests();
+ return _shouldShowPassedTests.Value;
+ }
+
internal /* for testing */ void RenderTestCompleted(
ITerminal terminal,
string assembly,
@@ -425,20 +433,20 @@ internal void TestCompleted(
TestOutcome outcome,
TimeSpan duration,
string? errorMessage,
- string? errorStackTrace,
+ Exception? exception,
string? expected,
string? actual)
{
- if (outcome == TestOutcome.Passed && !_options.ShowPassedTests)
+ if (outcome == TestOutcome.Passed && !GetShowPassedTests())
{
return;
}
TerminalColor color = outcome switch
{
- TestOutcome.Error or TestOutcome.Fail or TestOutcome.Canceled or TestOutcome.Timeout => TerminalColor.DarkRed,
- TestOutcome.Skipped => TerminalColor.DarkYellow,
- TestOutcome.Passed => TerminalColor.DarkGreen,
+ TestOutcome.Error or TestOutcome.Fail or TestOutcome.Canceled or TestOutcome.Timeout => TerminalColor.Red,
+ TestOutcome.Skipped => TerminalColor.Yellow,
+ TestOutcome.Passed => TerminalColor.Green,
_ => throw new NotSupportedException(),
};
string outcomeText = outcome switch
@@ -455,7 +463,7 @@ internal void TestCompleted(
terminal.ResetColor();
terminal.Append(' ');
terminal.Append(displayName);
- terminal.SetColor(TerminalColor.Gray);
+ terminal.SetColor(TerminalColor.DarkGray);
terminal.Append(' ');
AppendLongDuration(terminal, duration);
if (_options.ShowAssembly)
@@ -469,9 +477,10 @@ internal void TestCompleted(
terminal.AppendLine();
- FormatErrorMessage(terminal, errorMessage);
+ FormatErrorMessage(terminal, errorMessage, exception, outcome);
FormatExpectedAndActual(terminal, expected, actual);
- FormatStackTrace(terminal, errorStackTrace);
+ FormatStackTrace(terminal, exception);
+ FormatInnerExceptions(terminal, exception);
}
private static void AppendAssemblyLinkTargetFrameworkAndArchitecture(ITerminal terminal, string assembly, string? targetFramework, string? architecture)
@@ -495,25 +504,16 @@ private static void AppendAssemblyLinkTargetFrameworkAndArchitecture(ITerminal t
}
}
- private static void FormatStackTrace(ITerminal terminal, string? errorStackTrace)
+ private static void FormatStackTrace(ITerminal terminal, Exception? exception)
{
- if (RoslynString.IsNullOrWhiteSpace(errorStackTrace))
+ if (exception?.StackTrace is not { } stackTrace)
{
return;
}
- terminal.SetColor(TerminalColor.DarkRed);
- terminal.Append(SingleIndentation);
- terminal.Append(PlatformResources.StackTrace);
- terminal.AppendLine(":");
-
- if (!errorStackTrace.Contains('\n'))
- {
- AppendStackFrame(terminal, errorStackTrace);
- return;
- }
+ terminal.SetColor(TerminalColor.DarkGray);
- string[] lines = errorStackTrace.Split(NewLineStrings, StringSplitOptions.None);
+ string[] lines = stackTrace.Split(NewLineStrings, StringSplitOptions.None);
foreach (string line in lines)
{
AppendStackFrame(terminal, line);
@@ -529,7 +529,7 @@ private static void FormatStackTrace(ITerminal terminal, string? errorStackTrace
if (match.Success)
{
bool weHaveFilePathAndCodeLine = !RoslynString.IsNullOrWhiteSpace(match.Groups["code"].Value);
- terminal.SetColor(TerminalColor.Gray);
+ terminal.SetColor(TerminalColor.DarkGray);
terminal.Append(PlatformResources.StackFrameAt);
terminal.Append(' ');
terminal.ResetColor();
@@ -545,7 +545,7 @@ private static void FormatStackTrace(ITerminal terminal, string? errorStackTrace
if (weHaveFilePathAndCodeLine)
{
- terminal.SetColor(TerminalColor.Gray);
+ terminal.SetColor(TerminalColor.DarkGray);
terminal.Append(' ');
terminal.Append(PlatformResources.StackFrameIn);
terminal.Append(' ');
@@ -581,18 +581,57 @@ private static void FormatExpectedAndActual(ITerminal terminal, string? expected
terminal.ResetColor();
}
- private static void FormatErrorMessage(ITerminal terminal, string? errorMessage)
+ private static void FormatErrorMessage(ITerminal terminal, string? errorMessage, Exception? exception, TestOutcome outcome)
{
- if (RoslynString.IsNullOrWhiteSpace(errorMessage))
+ if (RoslynString.IsNullOrWhiteSpace(errorMessage) && exception is null)
{
return;
}
terminal.SetColor(TerminalColor.Red);
- AppendIndentedLine(terminal, errorMessage, SingleIndentation);
+
+ if (exception is null)
+ {
+ AppendIndentedLine(terminal, errorMessage, SingleIndentation);
+ }
+ else if (outcome == TestOutcome.Fail)
+ {
+ // For failed tests, we don't prefix the message with the exception type because it is most likely an assertion specific exception like AssertionFailedException, and we prefer to show that without the exception type to avoid additional noise.
+ AppendIndentedLine(terminal, errorMessage ?? exception.Message, SingleIndentation);
+ }
+ else
+ {
+ AppendIndentedLine(terminal, $"{exception.GetType().FullName}: {errorMessage ?? exception.Message}", SingleIndentation);
+ }
+
terminal.ResetColor();
}
+ private static void FormatInnerExceptions(ITerminal terminal, Exception? exception)
+ {
+ IEnumerable aggregateExceptions = exception switch
+ {
+ AggregateException aggregate => aggregate.Flatten().InnerExceptions,
+ _ => [exception?.InnerException],
+ };
+
+ foreach (Exception? aggregate in aggregateExceptions)
+ {
+ Exception? currentException = aggregate;
+ while (currentException is not null)
+ {
+ terminal.SetColor(TerminalColor.Red);
+ terminal.Append(SingleIndentation);
+ terminal.Append("--->");
+ FormatErrorMessage(terminal, null, currentException, TestOutcome.Error);
+
+ FormatStackTrace(terminal, currentException);
+
+ currentException = currentException.InnerException;
+ }
+ }
+ }
+
private static void AppendIndentedLine(ITerminal terminal, string? message, string indent)
{
if (RoslynString.IsNullOrWhiteSpace(message))
@@ -653,7 +692,7 @@ private static void AppendLongDuration(ITerminal terminal, TimeSpan duration, bo
{
if (colorize)
{
- terminal.SetColor(TerminalColor.Gray);
+ terminal.SetColor(TerminalColor.DarkGray);
}
HumanReadableDurationFormatter.Append(terminal, duration, wrapInParentheses);
@@ -772,8 +811,8 @@ private static TerminalColor ToTerminalColor(ConsoleColor consoleColor)
ConsoleColor.DarkRed => TerminalColor.DarkRed,
ConsoleColor.DarkMagenta => TerminalColor.DarkMagenta,
ConsoleColor.DarkYellow => TerminalColor.DarkYellow,
+ ConsoleColor.DarkGray => TerminalColor.DarkGray,
ConsoleColor.Gray => TerminalColor.Gray,
- ConsoleColor.DarkGray => TerminalColor.Gray,
ConsoleColor.Blue => TerminalColor.Blue,
ConsoleColor.Green => TerminalColor.Green,
ConsoleColor.Cyan => TerminalColor.Cyan,
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.cs
index 9cdd7b4c01..d2e84bc340 100644
--- a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.cs
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.cs
@@ -13,7 +13,7 @@ internal sealed class TerminalTestReporterOptions
///
/// Gets a value indicating whether we should show passed tests.
///
- public bool ShowPassedTests { get; init; }
+ public Func ShowPassedTests { get; init; } = () => true;
///
/// Gets a value indicating whether we should show information about which assembly is the source of the data on screen. Turn this off when running directly from an exe to reduce noise, because the path will always be the same.
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs
index 5792660438..9bb19adfd8 100644
--- a/src/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs
@@ -25,7 +25,7 @@ namespace Microsoft.Testing.Platform.OutputDevice;
///
/// Implementation of output device that writes to terminal with progress and optionally with ANSI.
///
-internal partial class TerminalOutputDevice : IPlatformOutputDevice,
+internal partial class TerminalOutputDevice : IHotReloadPlatformOutputDevice,
IDataConsumer,
IOutputDeviceDataProducer,
ITestSessionLifetimeHandler,
@@ -123,11 +123,16 @@ public Task InitializeAsync()
bool noAnsi = _commandLineOptions.IsOptionSet(TerminalTestReporterCommandLineOptionsProvider.NoAnsiOption);
bool noProgress = _commandLineOptions.IsOptionSet(TerminalTestReporterCommandLineOptionsProvider.NoProgressOption);
- bool showPassed = false;
+ // _runtimeFeature.IsHotReloadEnabled is not set to true here, even if the session will be HotReload,
+ // we need to postpone that decision until the first test result.
+ //
+ // This works but is NOT USED, we prefer to have the same experience of not showing passed tests in hotReload mode as in normal mode.
+ // Func showPassed = () => _runtimeFeature.IsHotReloadEnabled;
+ Func showPassed = () => false;
bool outputOption = _commandLineOptions.TryGetOptionArgumentList(TerminalTestReporterCommandLineOptionsProvider.OutputOption, out string[]? arguments);
if (outputOption && arguments?.Length > 0 && TerminalTestReporterCommandLineOptionsProvider.OutputOptionDetailedArgument.Equals(arguments[0], StringComparison.OrdinalIgnoreCase))
{
- showPassed = true;
+ showPassed = () => true;
}
Func shouldShowProgress = noProgress
@@ -270,6 +275,9 @@ public virtual async Task DisplayBannerAsync(string? bannerMessage)
}
}
+ public async Task DisplayBeforeHotReloadSessionStartAsync()
+ => await DisplayBeforeSessionStartAsync();
+
public async Task DisplayBeforeSessionStartAsync()
{
RoslynDebug.Assert(_terminalTestReporter is not null);
@@ -284,15 +292,30 @@ public async Task DisplayBeforeSessionStartAsync()
}
}
+ public async Task DisplayAfterHotReloadSessionEndAsync()
+ => await DisplayAfterSessionEndRunInternalAsync();
+
public async Task DisplayAfterSessionEndRunAsync()
{
- RoslynDebug.Assert(_terminalTestReporter is not null);
-
if (_isVSTestMode || _isListTests || _isServerMode)
{
return;
}
+ // Do NOT check and store the value in the constructor
+ // it won't be populated yet, so you will always see false.
+ if (_runtimeFeature.IsHotReloadEnabled)
+ {
+ return;
+ }
+
+ await DisplayAfterSessionEndRunInternalAsync();
+ }
+
+ private async Task DisplayAfterSessionEndRunInternalAsync()
+ {
+ RoslynDebug.Assert(_terminalTestReporter is not null);
+
using (await _asyncMonitor.LockAsync(TimeoutHelper.DefaultHangTimeSpanTimeout))
{
if (!_firstCallTo_OnSessionStartingAsync)
@@ -411,8 +434,8 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
testNodeStateChanged.TestNode.DisplayName,
TestOutcome.Error,
duration,
- errorMessage: errorState.Exception?.Message ?? errorState.Explanation,
- errorState.Exception?.StackTrace,
+ errorState.Explanation,
+ errorState.Exception,
expected: null,
actual: null);
break;
@@ -425,8 +448,8 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
testNodeStateChanged.TestNode.DisplayName,
TestOutcome.Fail,
duration,
- errorMessage: failedState.Exception?.Message ?? failedState.Explanation,
- failedState.Exception?.StackTrace,
+ failedState.Explanation,
+ failedState.Exception,
expected: failedState.Exception?.Data["assert.expected"] as string,
actual: failedState.Exception?.Data["assert.actual"] as string);
break;
@@ -439,8 +462,8 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
testNodeStateChanged.TestNode.DisplayName,
TestOutcome.Timeout,
duration,
- errorMessage: timeoutState.Exception?.Message ?? timeoutState.Explanation,
- timeoutState.Exception?.StackTrace,
+ timeoutState.Explanation,
+ timeoutState.Exception,
expected: null,
actual: null);
break;
@@ -453,8 +476,8 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
testNodeStateChanged.TestNode.DisplayName,
TestOutcome.Canceled,
duration,
- errorMessage: cancelledState.Exception?.Message ?? cancelledState.Explanation,
- cancelledState.Exception?.StackTrace,
+ cancelledState.Explanation,
+ cancelledState.Exception,
expected: null,
actual: null);
break;
@@ -468,7 +491,7 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
outcome: TestOutcome.Passed,
duration: duration,
errorMessage: null,
- errorStackTrace: null,
+ exception: null,
expected: null,
actual: null);
break;
@@ -482,7 +505,7 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
TestOutcome.Skipped,
duration,
errorMessage: null,
- errorStackTrace: null,
+ exception: null,
expected: null,
actual: null);
break;
diff --git a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Shipped.txt b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Shipped.txt
index 60531fbd53..87b7d881ce 100644
--- a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Shipped.txt
+++ b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Shipped.txt
@@ -1,11 +1,50 @@
#nullable enable
[TPEXP]Microsoft.Testing.Platform.Capabilities.TestFramework.IBannerMessageOwnerCapability
[TPEXP]Microsoft.Testing.Platform.Capabilities.TestFramework.IBannerMessageOwnerCapability.GetBannerMessageAsync() -> System.Threading.Tasks.Task!
+[TPEXP]Microsoft.Testing.Platform.Capabilities.TestFramework.TestFrameworkCapabilitiesExtensions
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.Deconstruct(out string! StandardError) -> void
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.StandardError.get -> string!
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.StandardError.init -> void
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.StandardErrorProperty(Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty! original) -> void
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.StandardErrorProperty(string! StandardError) -> void
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.Deconstruct(out string! StandardOutput) -> void
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.StandardOutput.get -> string!
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.StandardOutput.init -> void
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.StandardOutputProperty(Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty! original) -> void
+[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.StandardOutputProperty(string! StandardOutput) -> void
+[TPEXP]Microsoft.Testing.Platform.Requests.IExecuteRequestCompletionNotifier
+[TPEXP]Microsoft.Testing.Platform.Requests.IExecuteRequestCompletionNotifier.Complete() -> void
+[TPEXP]Microsoft.Testing.Platform.Services.IClientInfo
+[TPEXP]Microsoft.Testing.Platform.Services.IClientInfo.Id.get -> string!
+[TPEXP]Microsoft.Testing.Platform.Services.IClientInfo.Version.get -> string!
[TPEXP]Microsoft.Testing.Platform.Services.IPlatformInformation
[TPEXP]Microsoft.Testing.Platform.Services.IPlatformInformation.BuildDate.get -> System.DateTimeOffset?
[TPEXP]Microsoft.Testing.Platform.Services.IPlatformInformation.CommitHash.get -> string?
[TPEXP]Microsoft.Testing.Platform.Services.IPlatformInformation.Name.get -> string!
[TPEXP]Microsoft.Testing.Platform.Services.IPlatformInformation.Version.get -> string?
+[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.Equals(object? obj) -> bool
+[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.GetHashCode() -> int
+[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.ToString() -> string!
+[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.Equals(object? obj) -> bool
+[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.GetHashCode() -> int
+[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.ToString() -> string!
+[TPEXP]static Microsoft.Testing.Platform.Capabilities.TestFramework.TestFrameworkCapabilitiesExtensions.GetCapability(this Microsoft.Testing.Platform.Capabilities.TestFramework.ITestFrameworkCapabilities! capabilities) -> T?
+[TPEXP]static Microsoft.Testing.Platform.Capabilities.TestFramework.TestFrameworkCapabilitiesExtensions.HasCapability(this Microsoft.Testing.Platform.Capabilities.TestFramework.ITestFrameworkCapabilities! capabilities) -> bool
+[TPEXP]static Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.operator !=(Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty? left, Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty? right) -> bool
+[TPEXP]static Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.operator ==(Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty? left, Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty? right) -> bool
+[TPEXP]static Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.operator !=(Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty? left, Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty? right) -> bool
+[TPEXP]static Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.operator ==(Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty? left, Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty? right) -> bool
+[TPEXP]static Microsoft.Testing.Platform.Services.ServiceProviderExtensions.GetClientInfo(this System.IServiceProvider! serviceProvider) -> Microsoft.Testing.Platform.Services.IClientInfo!
+[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.$() -> Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty!
+[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.EqualityContract.get -> System.Type!
+[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.Equals(Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty? other) -> bool
+[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.PrintMembers(System.Text.StringBuilder! builder) -> bool
+[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.$() -> Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty!
+[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.EqualityContract.get -> System.Type!
+[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.Equals(Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty? other) -> bool
+[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.PrintMembers(System.Text.StringBuilder! builder) -> bool
Microsoft.Testing.Platform.Builder.ConfigurationOptions
Microsoft.Testing.Platform.Builder.ConfigurationOptions.ConfigurationOptions() -> void
Microsoft.Testing.Platform.Builder.ConfigurationOptions.ConfigurationSources.get -> Microsoft.Testing.Platform.Builder.ConfigurationSourcesOptions!
@@ -330,6 +369,8 @@ Microsoft.Testing.Platform.OutputDevice.FormattedTextOutputDeviceData.Background
Microsoft.Testing.Platform.OutputDevice.FormattedTextOutputDeviceData.ForegroundColor.get -> Microsoft.Testing.Platform.OutputDevice.IColor?
Microsoft.Testing.Platform.OutputDevice.FormattedTextOutputDeviceData.ForegroundColor.init -> void
Microsoft.Testing.Platform.OutputDevice.FormattedTextOutputDeviceData.FormattedTextOutputDeviceData(string! text) -> void
+Microsoft.Testing.Platform.OutputDevice.FormattedTextOutputDeviceData.Padding.get -> int?
+Microsoft.Testing.Platform.OutputDevice.FormattedTextOutputDeviceData.Padding.init -> void
Microsoft.Testing.Platform.OutputDevice.IColor
Microsoft.Testing.Platform.OutputDevice.IOutputDevice
Microsoft.Testing.Platform.OutputDevice.IOutputDevice.DisplayAsync(Microsoft.Testing.Platform.Extensions.OutputDevice.IOutputDeviceDataProducer! producer, Microsoft.Testing.Platform.OutputDevice.IOutputDeviceData! data) -> System.Threading.Tasks.Task!
diff --git a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt
index 0efc76dd10..7dc5c58110 100644
--- a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt
+++ b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt
@@ -1,42 +1 @@
#nullable enable
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.StandardOutput.get -> string!
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.StandardOutput.init -> void
-[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.EqualityContract.get -> System.Type!
-[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.ToString() -> string!
-[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.PrintMembers(System.Text.StringBuilder! builder) -> bool
-[TPEXP]static Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.operator !=(Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty? left, Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty? right) -> bool
-[TPEXP]static Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.operator ==(Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty? left, Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty? right) -> bool
-[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.GetHashCode() -> int
-[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.Equals(object? obj) -> bool
-[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.$() -> Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty!
-[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.Equals(Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty? other) -> bool
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.StandardOutputProperty(Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty! original) -> void
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.Deconstruct(out string! StandardOutput) -> void
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardOutputProperty.StandardOutputProperty(string! StandardOutput) -> void
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.StandardError.get -> string!
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.StandardError.init -> void
-[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.EqualityContract.get -> System.Type!
-[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.ToString() -> string!
-[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.PrintMembers(System.Text.StringBuilder! builder) -> bool
-[TPEXP]static Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.operator !=(Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty? left, Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty? right) -> bool
-[TPEXP]static Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.operator ==(Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty? left, Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty? right) -> bool
-[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.GetHashCode() -> int
-[TPEXP]override Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.Equals(object? obj) -> bool
-[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.$() -> Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty!
-[TPEXP]virtual Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.Equals(Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty? other) -> bool
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.StandardErrorProperty(Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty! original) -> void
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.Deconstruct(out string! StandardError) -> void
-[TPEXP]Microsoft.Testing.Platform.Extensions.Messages.StandardErrorProperty.StandardErrorProperty(string! StandardError) -> void
-Microsoft.Testing.Platform.OutputDevice.FormattedTextOutputDeviceData.Padding.get -> int?
-Microsoft.Testing.Platform.OutputDevice.FormattedTextOutputDeviceData.Padding.init -> void
-[TPEXP]Microsoft.Testing.Platform.Capabilities.TestFramework.TestFrameworkCapabilitiesExtensions
-[TPEXP]Microsoft.Testing.Platform.Requests.IExecuteRequestCompletionNotifier
-[TPEXP]Microsoft.Testing.Platform.Requests.IExecuteRequestCompletionNotifier.Complete() -> void
-[TPEXP]Microsoft.Testing.Platform.Services.IClientInfo
-[TPEXP]Microsoft.Testing.Platform.Services.IClientInfo.Id.get -> string!
-[TPEXP]Microsoft.Testing.Platform.Services.IClientInfo.Version.get -> string!
-[TPEXP]static Microsoft.Testing.Platform.Capabilities.TestFramework.TestFrameworkCapabilitiesExtensions.GetCapability(this Microsoft.Testing.Platform.Capabilities.TestFramework.ITestFrameworkCapabilities! capabilities) -> T?
-[TPEXP]static Microsoft.Testing.Platform.Capabilities.TestFramework.TestFrameworkCapabilitiesExtensions.HasCapability(this Microsoft.Testing.Platform.Capabilities.TestFramework.ITestFrameworkCapabilities! capabilities) -> bool
-[TPEXP]static Microsoft.Testing.Platform.Services.ServiceProviderExtensions.GetClientInfo(this System.IServiceProvider! serviceProvider) -> Microsoft.Testing.Platform.Services.IClientInfo!
diff --git a/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/JsonRpcMethods.cs b/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/JsonRpcMethods.cs
index e0a988755e..cf8b52f5df 100644
--- a/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/JsonRpcMethods.cs
+++ b/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/JsonRpcMethods.cs
@@ -60,7 +60,7 @@ internal static class JsonRpcStrings
public const string Message = "message";
// Telemetry
- public const string EventName = "EventName";
+ public const string EventName = "eventName";
public const string Metrics = "metrics";
// Process
diff --git a/src/Platform/Microsoft.Testing.Platform/Telemetry/TelemetryManager.cs b/src/Platform/Microsoft.Testing.Platform/Telemetry/TelemetryManager.cs
index 2cc9e319db..3ac6bb615a 100644
--- a/src/Platform/Microsoft.Testing.Platform/Telemetry/TelemetryManager.cs
+++ b/src/Platform/Microsoft.Testing.Platform/Telemetry/TelemetryManager.cs
@@ -47,8 +47,29 @@ public async Task BuildAsync(ServiceProvider serviceProvide
await logger.LogDebugAsync($"{EnvironmentVariableConstants.DOTNET_CLI_TELEMETRY_OPTOUT} environment variable: '{cli_telemetryOptOut}'");
isTelemetryOptedOut = (cli_telemetryOptOut is "1" or "true") || isTelemetryOptedOut;
- // NO_LOGO
+ await logger.LogDebugAsync($"Telemetry is '{(!isTelemetryOptedOut ? "ENABLED" : "DISABLED")}'");
+
+ if (!isTelemetryOptedOut && _telemetryFactory is not null)
+ {
+ await ShowTelemetryBannerFirstNoticeAsync(serviceProvider, logger, environment);
+ }
+
+ serviceProvider.TryAddService(new TelemetryInformation(!isTelemetryOptedOut, TelemetryProperties.VersionValue));
+ ITelemetryCollector telemetryCollector = _telemetryFactory is null || isTelemetryOptedOut
+ ? new NopTelemetryService(!isTelemetryOptedOut)
+ : _telemetryFactory(serviceProvider);
+
+ if (!isTelemetryOptedOut)
+ {
+ await logger.LogDebugAsync($"Telemetry collector provider: '{telemetryCollector.GetType()}'");
+ }
+
+ return telemetryCollector;
+ }
+
+ private async Task ShowTelemetryBannerFirstNoticeAsync(ServiceProvider serviceProvider, ILogger logger, IEnvironment environment)
+ {
// If the environment variable is not set or is set to 0, telemetry is opted in.
ICommandLineOptions commandLineOptions = serviceProvider.GetCommandLineOptions();
bool doNotShowLogo = commandLineOptions.IsOptionSet(PlatformCommandLineProvider.NoBannerOptionKey);
@@ -61,64 +82,53 @@ public async Task BuildAsync(ServiceProvider serviceProvide
await logger.LogDebugAsync($"{EnvironmentVariableConstants.DOTNET_NOLOGO} environment variable: '{dotnetNoLogoEnvVar}'");
doNotShowLogo = (dotnetNoLogoEnvVar is "1" or "true") || doNotShowLogo;
- await logger.LogDebugAsync($"Telemetry is '{(!isTelemetryOptedOut ? "ENABLED" : "DISABLED")}'");
-
- if (!isTelemetryOptedOut && !doNotShowLogo)
+ if (doNotShowLogo)
{
- ITestApplicationModuleInfo testApplicationModuleInfo = serviceProvider.GetTestApplicationModuleInfo();
+ return;
+ }
+
+ ITestApplicationModuleInfo testApplicationModuleInfo = serviceProvider.GetTestApplicationModuleInfo();
#pragma warning disable RS0030 // Do not use banned APIs - There is no easy way to disable it for all members
- string? directory = environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData, Environment.SpecialFolderOption.Create);
+ string? directory = environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData, Environment.SpecialFolderOption.Create);
#pragma warning restore RS0030 // Do not use banned APIs
- if (directory is not null)
- {
- directory = Path.Combine(directory, "Microsoft", "TestingPlatform");
- }
+ if (directory is not null)
+ {
+ directory = Path.Combine(directory, "Microsoft", "TestingPlatform");
+ }
- IFileSystem fileSystem = serviceProvider.GetFileSystem();
- string fileName = Path.ChangeExtension(Path.GetFileName(testApplicationModuleInfo.GetCurrentTestApplicationFullPath()), "testingPlatformFirstTimeUseSentinel");
- bool sentinelIsNotPresent =
- RoslynString.IsNullOrWhiteSpace(directory)
- || !fileSystem.Exists(Path.Combine(directory, fileName));
+ IFileSystem fileSystem = serviceProvider.GetFileSystem();
+ string fileName = Path.ChangeExtension(Path.GetFileName(testApplicationModuleInfo.GetCurrentTestApplicationFullPath()), "testingPlatformFirstTimeUseSentinel");
+ bool sentinelIsNotPresent =
+ RoslynString.IsNullOrWhiteSpace(directory)
+ || !fileSystem.Exists(Path.Combine(directory, fileName));
- if (!doNotShowLogo && sentinelIsNotPresent)
+ if (!sentinelIsNotPresent)
+ {
+ return;
+ }
+
+ IOutputDevice outputDevice = serviceProvider.GetOutputDevice();
+ await outputDevice.DisplayAsync(this, new TextOutputDeviceData(PlatformResources.TelemetryNotice));
+
+ string? path = null;
+ try
+ {
+ // See if we should write the file, and write it.
+ if (!RoslynString.IsNullOrWhiteSpace(directory))
{
- IOutputDevice outputDevice = serviceProvider.GetOutputDevice();
- await outputDevice.DisplayAsync(this, new TextOutputDeviceData(PlatformResources.TelemetryNotice));
+ Directory.CreateDirectory(directory);
- string? path = null;
- try
- {
- // See if we should write the file, and write it.
- if (!RoslynString.IsNullOrWhiteSpace(directory))
- {
- Directory.CreateDirectory(directory);
-
- // Write empty file.
- path = Path.Combine(directory, fileName);
- using (fileSystem.NewFileStream(path, FileMode.Create, FileAccess.Write))
- {
- }
- }
- }
- catch (Exception exception) when (exception is IOException or SystemException)
+ // Write empty file.
+ path = Path.Combine(directory, fileName);
+ using (fileSystem.NewFileStream(path, FileMode.Create, FileAccess.Write))
{
- await logger.LogErrorAsync($"Could not write sentinel file for telemetry to path,'{path ?? ""}'.", exception);
}
}
}
-
- serviceProvider.TryAddService(new TelemetryInformation(!isTelemetryOptedOut, TelemetryProperties.VersionValue));
-
- ITelemetryCollector telemetryCollector = _telemetryFactory is null || isTelemetryOptedOut
- ? new NopTelemetryService(!isTelemetryOptedOut)
- : _telemetryFactory(serviceProvider);
-
- if (!isTelemetryOptedOut)
+ catch (Exception exception) when (exception is IOException or SystemException)
{
- await logger.LogDebugAsync($"Telemetry collector provider: '{telemetryCollector.GetType()}'");
+ await logger.LogErrorAsync($"Could not write sentinel file for telemetry to path,'{path ?? ""}'.", exception);
}
-
- return telemetryCollector;
}
public Task IsEnabledAsync() => throw new NotImplementedException();
diff --git a/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs b/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs
index d3d7a1d085..43465e0d68 100644
--- a/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs
+++ b/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs
@@ -1641,12 +1641,15 @@ private static bool CompareIEnumerable(IEnumerable? expected, IEnumerable? actua
object? curExpected = expectedEnum.Current;
object? curActual = actualEnum.Current;
-
- if (curExpected is IEnumerable curExpectedEnum && curActual is IEnumerable curActualEnum)
+ if (comparer.Compare(curExpected, curActual) == 0)
+ {
+ position++;
+ }
+ else if (curExpected is IEnumerable curExpectedEnum && curActual is IEnumerable curActualEnum)
{
stack.Push(new(expectedEnum, actualEnum, position + 1));
stack.Push(new(curExpectedEnum.GetEnumerator(), curActualEnum.GetEnumerator(), 0));
- break;
+ continue;
}
else if (comparer.Compare(curExpected, curActual) != 0)
{
@@ -1656,8 +1659,6 @@ private static bool CompareIEnumerable(IEnumerable? expected, IEnumerable? actua
position);
return false;
}
-
- position++;
}
if (actualEnum.MoveNext() && !expectedEnum.MoveNext())
diff --git a/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Shipped.txt b/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Shipped.txt
index ee5377dcb0..23ce9ae2e1 100644
--- a/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Shipped.txt
+++ b/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Shipped.txt
@@ -143,6 +143,11 @@ Microsoft.VisualStudio.TestTools.UnitTesting.ParallelizeAttribute.Workers.set ->
Microsoft.VisualStudio.TestTools.UnitTesting.PriorityAttribute
Microsoft.VisualStudio.TestTools.UnitTesting.PriorityAttribute.Priority.get -> int
Microsoft.VisualStudio.TestTools.UnitTesting.PriorityAttribute.PriorityAttribute(int priority) -> void
+Microsoft.VisualStudio.TestTools.UnitTesting.STATestClassAttribute
+Microsoft.VisualStudio.TestTools.UnitTesting.STATestClassAttribute.STATestClassAttribute() -> void
+Microsoft.VisualStudio.TestTools.UnitTesting.STATestMethodAttribute
+Microsoft.VisualStudio.TestTools.UnitTesting.STATestMethodAttribute.STATestMethodAttribute() -> void
+Microsoft.VisualStudio.TestTools.UnitTesting.STATestMethodAttribute.STATestMethodAttribute(string? displayName) -> void
Microsoft.VisualStudio.TestTools.UnitTesting.StringAssert
Microsoft.VisualStudio.TestTools.UnitTesting.TestCategoryAttribute
Microsoft.VisualStudio.TestTools.UnitTesting.TestCategoryAttribute.TestCategoryAttribute(string! testCategory) -> void
@@ -208,6 +213,8 @@ Microsoft.VisualStudio.TestTools.UnitTesting.TestResult.TestResult() -> void
Microsoft.VisualStudio.TestTools.UnitTesting.TestTimeout
Microsoft.VisualStudio.TestTools.UnitTesting.TestTimeout.Infinite = 2147483647 -> Microsoft.VisualStudio.TestTools.UnitTesting.TestTimeout
Microsoft.VisualStudio.TestTools.UnitTesting.TimeoutAttribute
+Microsoft.VisualStudio.TestTools.UnitTesting.TimeoutAttribute.CooperativeCancellation.get -> bool
+Microsoft.VisualStudio.TestTools.UnitTesting.TimeoutAttribute.CooperativeCancellation.set -> void
Microsoft.VisualStudio.TestTools.UnitTesting.TimeoutAttribute.Timeout.get -> int
Microsoft.VisualStudio.TestTools.UnitTesting.TimeoutAttribute.TimeoutAttribute(int timeout) -> void
Microsoft.VisualStudio.TestTools.UnitTesting.TimeoutAttribute.TimeoutAttribute(Microsoft.VisualStudio.TestTools.UnitTesting.TestTimeout timeout) -> void
diff --git a/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt b/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt
index 7241987b6a..ab058de62d 100644
--- a/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt
+++ b/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt
@@ -1,8 +1 @@
#nullable enable
-Microsoft.VisualStudio.TestTools.UnitTesting.STATestClassAttribute
-Microsoft.VisualStudio.TestTools.UnitTesting.STATestClassAttribute.STATestClassAttribute() -> void
-Microsoft.VisualStudio.TestTools.UnitTesting.STATestMethodAttribute
-Microsoft.VisualStudio.TestTools.UnitTesting.STATestMethodAttribute.STATestMethodAttribute() -> void
-Microsoft.VisualStudio.TestTools.UnitTesting.STATestMethodAttribute.STATestMethodAttribute(string? displayName) -> void
-Microsoft.VisualStudio.TestTools.UnitTesting.TimeoutAttribute.CooperativeCancellation.get -> bool
-Microsoft.VisualStudio.TestTools.UnitTesting.TimeoutAttribute.CooperativeCancellation.set -> void
diff --git a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HangDumpOutputTests.cs b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HangDumpOutputTests.cs
new file mode 100644
index 0000000000..e5bb4b6ff3
--- /dev/null
+++ b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HangDumpOutputTests.cs
@@ -0,0 +1,157 @@
+// 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.Testing.Platform.Acceptance.IntegrationTests.Helpers;
+using Microsoft.Testing.Platform.Helpers;
+
+namespace Microsoft.Testing.Platform.Acceptance.IntegrationTests;
+
+[TestGroup]
+public sealed class HangDumpOutputTests : AcceptanceTestBase
+{
+ private readonly TestAssetFixture _testAssetFixture;
+
+ public HangDumpOutputTests(ITestExecutionContext testExecutionContext, TestAssetFixture testAssetFixture)
+ : base(testExecutionContext) => _testAssetFixture = testAssetFixture;
+
+ [Arguments("Mini")]
+ public async Task HangDump_Outputs_HangingTests_EvenWhenHangingTestsHaveTheSameDisplayName(string format)
+ {
+ // This test makes sure that when tests have the same display name (e.g. like Test1 from both Class1 and Class2)
+ // they will still show up in the hanging tests. This was not the case before when we were just putting them into
+ // a dictionary based on DisplayName. In that case both tests were started at the same time, and only 1 entry was added
+ // to currently executing tests. When first test with name Test1 completed we removed that entry, but Class2.Test1 was still
+ // running. Solution is to use a more unique identifier.
+ string resultDirectory = Path.Combine(_testAssetFixture.TargetAssetPath, Guid.NewGuid().ToString("N"), format);
+ var testHost = TestInfrastructure.TestHost.LocateFrom(_testAssetFixture.TargetAssetPath, "HangDump", TargetFrameworks.NetCurrent.Arguments);
+ TestHostResult testHostResult = await testHost.ExecuteAsync(
+ $"--hangdump --hangdump-timeout 8s --hangdump-type {format} --results-directory {resultDirectory} --no-progress",
+ new Dictionary
+ {
+ { "SLEEPTIMEMS1", "100" },
+ { "SLEEPTIMEMS2", "600000" },
+ });
+ testHostResult.AssertExitCodeIs(ExitCodes.TestHostProcessExitedNonGracefully);
+ testHostResult.AssertOutputContains("Test1");
+ }
+
+ [TestFixture(TestFixtureSharingStrategy.PerTestGroup)]
+ public sealed class TestAssetFixture(AcceptanceFixture acceptanceFixture) : TestAssetFixtureBase(acceptanceFixture.NuGetGlobalPackagesFolder)
+ {
+ private const string AssetName = "TestAssetFixture";
+
+ public string TargetAssetPath => GetAssetPath(AssetName);
+
+ public override IEnumerable<(string ID, string Name, string Code)> GetAssetsToGenerate()
+ {
+ yield return (AssetName, AssetName,
+ Sources
+ .PatchTargetFrameworks(TargetFrameworks.All)
+ .PatchCodeWithReplace("$MicrosoftTestingPlatformVersion$", MicrosoftTestingPlatformVersion));
+ }
+
+ private const string Sources = """
+#file HangDump.csproj
+
+
+
+ $TargetFrameworks$
+ Exe
+ true
+ enable
+ preview
+
+
+
+
+
+
+
+#file Program.cs
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Globalization;
+
+using Microsoft.Testing.Platform;
+using Microsoft.Testing.Platform.Extensions.TestFramework;
+using Microsoft.Testing.Platform.Builder;
+using Microsoft.Testing.Platform.Capabilities.TestFramework;
+using Microsoft.Testing.Extensions;
+using Microsoft.Testing.Platform.Extensions.Messages;
+using Microsoft.Testing.Platform.Requests;
+using Microsoft.Testing.Platform.Services;
+
+public class Startup
+{
+ public static async Task Main(string[] args)
+ {
+ ITestApplicationBuilder builder = await TestApplication.CreateBuilderAsync(args);
+ builder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_,__) => new DummyTestAdapter());
+ builder.AddHangDumpProvider();
+ using ITestApplication app = await builder.BuildAsync();
+ return await app.RunAsync();
+ }
+}
+
+public class DummyTestAdapter : ITestFramework, IDataProducer
+{
+ public string Uid => nameof(DummyTestAdapter);
+
+ public string Version => "2.0.0";
+
+ public string DisplayName => nameof(DummyTestAdapter);
+
+ public string Description => nameof(DummyTestAdapter);
+
+ public Task IsEnabledAsync() => Task.FromResult(true);
+
+ public Type[] DataTypesProduced => new[] { typeof(TestNodeUpdateMessage) };
+
+ public Task CreateTestSessionAsync(CreateTestSessionContext context)
+ => Task.FromResult(new CreateTestSessionResult() { IsSuccess = true });
+
+ public Task CloseTestSessionAsync(CloseTestSessionContext context)
+ => Task.FromResult(new CloseTestSessionResult() { IsSuccess = true });
+
+ public async Task ExecuteRequestAsync(ExecuteRequestContext context)
+ {
+ await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode()
+ {
+ Uid = "Class1.Test1",
+ DisplayName = "Test1",
+ Properties = new PropertyBag(new InProgressTestNodeStateProperty()),
+ }));
+
+ await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode()
+ {
+ Uid = "Class2.Test1",
+ DisplayName = "Test1",
+ Properties = new PropertyBag(new InProgressTestNodeStateProperty()),
+ }));
+
+ Thread.Sleep(int.Parse(Environment.GetEnvironmentVariable("SLEEPTIMEMS1")!, CultureInfo.InvariantCulture));
+
+ await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode()
+ {
+ Uid = "Class1.Test1",
+ DisplayName = "Test1",
+ Properties = new PropertyBag(new PassedTestNodeStateProperty()),
+ }));
+
+ Thread.Sleep(int.Parse(Environment.GetEnvironmentVariable("SLEEPTIMEMS2")!, CultureInfo.InvariantCulture));
+
+ await context.MessageBus.PublishAsync(this, new TestNodeUpdateMessage(context.Request.Session.SessionUid, new TestNode()
+ {
+ Uid = "Class2.Test1",
+ DisplayName = "Test1",
+ Properties = new PropertyBag(new PassedTestNodeStateProperty()),
+ }));
+
+ context.Complete();
+ }
+}
+""";
+ }
+}
diff --git a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HangDumpTests.cs b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HangDumpTests.cs
index dac37079fb..c73a9da2a0 100644
--- a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HangDumpTests.cs
+++ b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HangDumpTests.cs
@@ -47,6 +47,24 @@ public async Task HangDump_CustomFileName_CreateDump()
Assert.IsTrue(dumpFile is not null, $"Dump file not found '{TargetFrameworks.NetCurrent}'\n{testHostResult}'");
}
+ public async Task HangDump_PathWithSpaces_CreateDump()
+ {
+ string resultDir = Path.Combine(_testAssetFixture.TargetAssetPath, Guid.NewGuid().ToString("N"), TargetFrameworks.NetCurrent.Arguments);
+ string resultDirectory = Path.Combine(resultDir, "directory with spaces");
+ Directory.CreateDirectory(resultDirectory);
+ var testHost = TestInfrastructure.TestHost.LocateFrom(_testAssetFixture.TargetAssetPath, "HangDump", TargetFrameworks.NetCurrent.Arguments);
+ TestHostResult testHostResult = await testHost.ExecuteAsync(
+ $"""--hangdump --hangdump-timeout 8s --hangdump-filename myhungdumpfile_%p.dmp --results-directory "{resultDirectory}" """,
+ new Dictionary
+ {
+ { "SLEEPTIMEMS1", "4000" },
+ { "SLEEPTIMEMS2", "20000" },
+ });
+ testHostResult.AssertExitCodeIs(ExitCodes.TestHostProcessExitedNonGracefully);
+ string? dumpFile = Directory.GetFiles(resultDirectory, "myhungdumpfile_*.dmp", SearchOption.AllDirectories).SingleOrDefault();
+ Assert.IsTrue(dumpFile is not null, $"Dump file not found '{TargetFrameworks.NetCurrent}'\n{testHostResult}'");
+ }
+
[Arguments("Mini")]
[Arguments("Heap")]
[Arguments("Triage")]
diff --git a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/MSBuildTests.Solution.cs b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/MSBuildTests.Solution.cs
index e004a8ced4..7ad84c074d 100644
--- a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/MSBuildTests.Solution.cs
+++ b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/MSBuildTests.Solution.cs
@@ -11,28 +11,9 @@ public class MSBuildTests_Solution : AcceptanceTestBase
private readonly AcceptanceFixture _acceptanceFixture;
private const string AssetName = "MSTestProject";
- static MSBuildTests_Solution()
- {
- string dotnetMuxerSDK = Directory.GetDirectories(Path.Combine(RootFinder.Find(), ".dotnet", "sdk")).OrderByDescending(x => x).First();
- File.WriteAllText(Path.Combine(dotnetMuxerSDK, "Microsoft.Common.CrossTargeting.targets"), MicrosoftCommonCrossTargeting);
- if (!File.Exists(Path.Combine(dotnetMuxerSDK, "Microsoft.Common.Test.targets")))
- {
- File.WriteAllText(Path.Combine(dotnetMuxerSDK, "Microsoft.Common.Test.targets"), MicrosoftCommonTesttargets);
- }
- }
-
public MSBuildTests_Solution(ITestExecutionContext testExecutionContext, AcceptanceFixture acceptanceFixture)
: base(testExecutionContext) => _acceptanceFixture = acceptanceFixture;
- private void CheckPatch()
- {
- // https://github.com/dotnet/sdk/issues/37712
- if (DateTime.UtcNow.Date > new DateTime(2024, 12, 1))
- {
- throw new InvalidOperationException("Check if we can remove the patch!");
- }
- }
-
internal static IEnumerable> GetBuildMatrix()
{
foreach (TestArgumentsEntry<(string SingleTfmOrMultiTfm, BuildConfiguration BuildConfiguration, bool IsMultiTfm)> entry in GetBuildMatrixSingleAndMultiTfmBuildConfiguration())
@@ -52,8 +33,6 @@ private void CheckPatch()
[ArgumentsProvider(nameof(GetBuildMatrix))]
public async Task MSBuildTests_UseMSBuildTestInfrastructure_Should_Run_Solution_Tests(string singleTfmOrMultiTfm, BuildConfiguration _, bool isMultiTfm, string command)
{
- CheckPatch();
-
using TestAsset generator = await TestAsset.GenerateAssetAsync(
AssetName,
SourceCode
@@ -155,215 +134,5 @@ public void TestMethod1()
global using Microsoft.Testing.Platform.Builder;
global using Microsoft.Testing.Internal.Framework;
global using Microsoft.Testing.Platform.MSBuild;
-""";
-
- private const string MicrosoftCommonCrossTargeting = """
-
-
-
- true
- true
-
-
-
-
-
-
-
-
-
- <_ThisProjectBuildMetadata Include="$(MSBuildProjectFullPath)">
- @(_TargetFrameworkInfo)
- @(_TargetFrameworkInfo->'%(TargetFrameworkMonikers)')
- @(_TargetFrameworkInfo->'%(TargetPlatformMonikers)')
- $(_AdditionalPropertiesFromProject)
- false
- @(_TargetFrameworkInfo->'%(IsRidAgnostic)')
-
-
- false
- $(Platform)
- $(Platforms)
-
-
-
-
-
- <_TargetFramework Include="$(TargetFrameworks)" />
-
- <_TargetFrameworkNormalized Include="@(_TargetFramework->Trim()->Distinct())" />
- <_InnerBuildProjects Include="$(MSBuildProjectFile)">
- TargetFramework=%(_TargetFrameworkNormalized.Identity)
-
-
-
-
-
-
-
-
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
- Build
-
-
-
-
-
-
-
-
-
-
-
- $([MSBuild]::IsRunningFromVisualStudio())
- $([MSBuild]::GetToolsDirectory32())\..\..\..\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.targets
- $(MSBuildToolsPath)\NuGet.targets
-
-
-
-
-
- true
-
-
-
-
- true
-
-
-
- true
-
-
-
- <_DirectoryBuildTargetsFile Condition="'$(_DirectoryBuildTargetsFile)' == ''">Directory.Build.targets
- <_DirectoryBuildTargetsBasePath Condition="'$(_DirectoryBuildTargetsBasePath)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), '$(_DirectoryBuildTargetsFile)'))
- $([System.IO.Path]::Combine('$(_DirectoryBuildTargetsBasePath)', '$(_DirectoryBuildTargetsFile)'))
-
-
-
- false
-
-
-
-""";
-
- private const string MicrosoftCommonTesttargets = """
-
-
-
""";
}
diff --git a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TelemetryTests.cs b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TelemetryTests.cs
index 73432d0ba4..c533062424 100644
--- a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TelemetryTests.cs
+++ b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TelemetryTests.cs
@@ -35,8 +35,6 @@ public async Task Telemetry_ByDefault_TelemetryIsEnabled(string tfm)
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TestApplicationOptions.EnableTelemetry: True
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TESTINGPLATFORM_TELEMETRY_OPTOUT environment variable: ''
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG DOTNET_CLI_TELEMETRY_OPTOUT environment variable: ''
-.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TESTINGPLATFORM_NOBANNER environment variable: ''
-.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG DOTNET_NOLOGO environment variable: ''
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG Telemetry is 'ENABLED'
""";
await AssertDiagnosticReportAsync(testHostResult, diagPathPattern, diagContentsPattern);
@@ -64,8 +62,6 @@ public async Task Telemetry_WhenOptingOutTelemetry_WithEnvironmentVariable_Telem
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TestApplicationOptions.EnableTelemetry: True
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TESTINGPLATFORM_TELEMETRY_OPTOUT environment variable: '1'
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG DOTNET_CLI_TELEMETRY_OPTOUT environment variable: ''
-.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TESTINGPLATFORM_NOBANNER environment variable: ''
-.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG DOTNET_NOLOGO environment variable: ''
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG Telemetry is 'DISABLED'
""";
await AssertDiagnosticReportAsync(testHostResult, diagPathPattern, diagContentsPattern);
@@ -93,8 +89,6 @@ public async Task Telemetry_WhenOptingOutTelemetry_With_DOTNET_CLI_EnvironmentVa
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TestApplicationOptions.EnableTelemetry: True
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TESTINGPLATFORM_TELEMETRY_OPTOUT environment variable: ''
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG DOTNET_CLI_TELEMETRY_OPTOUT environment variable: '1'
-.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TESTINGPLATFORM_NOBANNER environment variable: ''
-.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG DOTNET_NOLOGO environment variable: ''
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG Telemetry is 'DISABLED'
""";
await AssertDiagnosticReportAsync(testHostResult, diagPathPattern, diagContentsPattern);
@@ -116,8 +110,6 @@ public async Task Telemetry_WhenEnableTelemetryIsFalse_WithTestApplicationOption
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TestApplicationOptions.EnableTelemetry: False
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TESTINGPLATFORM_TELEMETRY_OPTOUT environment variable: ''
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG DOTNET_CLI_TELEMETRY_OPTOUT environment variable: ''
-.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG TESTINGPLATFORM_NOBANNER environment variable: ''
-.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG DOTNET_NOLOGO environment variable: ''
.+ Microsoft.Testing.Platform.Telemetry.TelemetryManager DEBUG Telemetry is 'DISABLED'
""";
await AssertDiagnosticReportAsync(testHostResult, diagPathPattern, diagContentsPattern);
diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/DoNotUseShadowingAnalyzerTests.cs b/test/UnitTests/MSTest.Analyzers.UnitTests/DoNotUseShadowingAnalyzerTests.cs
index 71458475d9..9f3e51de07 100644
--- a/test/UnitTests/MSTest.Analyzers.UnitTests/DoNotUseShadowingAnalyzerTests.cs
+++ b/test/UnitTests/MSTest.Analyzers.UnitTests/DoNotUseShadowingAnalyzerTests.cs
@@ -48,6 +48,94 @@ public void Method() { }
await VerifyCS.VerifyAnalyzerAsync(code);
}
+ public async Task WhenTestClassHaveSameMethodAsBaseClassMethod_ButBothArePrivate_NoDiagnostic()
+ {
+ string code = """
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ public class BaseClass
+ {
+ private void Method() { }
+ }
+
+ [TestClass]
+ public class DerivedClass : BaseClass
+ {
+ private void Method() { }
+ }
+ """;
+
+ await VerifyCS.VerifyAnalyzerAsync(code);
+ }
+
+ public async Task WhenTestClassHaveSameMethodAsBaseClassMethod_ButBaseIsPrivate_Diagnostic()
+ {
+ string code = """
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ public class BaseClass
+ {
+ private void Method() { }
+ }
+
+ [TestClass]
+ public class DerivedClass : BaseClass
+ {
+ public void [|Method|]() { }
+ }
+ """;
+
+ await VerifyCS.VerifyAnalyzerAsync(code);
+ }
+
+ public async Task WhenTestClassHaveSameMethodAsBaseClassMethod_ButDerivedClassIsPrivate_Diagnostic()
+ {
+ string code = """
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ public class BaseClass
+ {
+ public void Method() { }
+ }
+
+ [TestClass]
+ public class DerivedClass : BaseClass
+ {
+ private void [|Method|]() { }
+ }
+ """;
+
+ await VerifyCS.VerifyAnalyzerAsync(code);
+ }
+
+ public async Task WhenTestClassHaveSameMethodAsBaseClassMethod_ButOneIsGeneric_NoDiagnostic()
+ {
+ string code = """
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using System;
+ [TestClass]
+ public class BaseTest
+ {
+ protected TObject CreateObject()
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [TestClass]
+ public class ExtendedTest : BaseTest
+ {
+ private SomeType CreateObject()
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class SomeType
+ {
+ }
+ """;
+
+ await VerifyCS.VerifyAnalyzerAsync(code);
+ }
+
public async Task WhenTestClassHaveSameMethodAsBaseClassMethod_WithParameters_Diagnostic()
{
string code = """
diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs b/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs
index c5967776f1..b15c8c2c9d 100644
--- a/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs
+++ b/test/UnitTests/MSTest.Analyzers.UnitTests/DynamicDataShouldBeValidAnalyzerTests.cs
@@ -164,12 +164,112 @@ public void TestMethod214(int i, string s)
{
}
+ [DynamicData("DataJaggedArray")]
+ [TestMethod]
+ public void TestMethod301(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData("SomeDataJaggedArray", typeof(SomeClass))]
+ [TestMethod]
+ public void TestMethod302(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData(dynamicDataSourceName: "DataJaggedArray")]
+ [TestMethod]
+ public void TestMethod303(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeDataJaggedArray")]
+ [TestMethod]
+ public void TestMethod304(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData("GetDataJaggedArray", DynamicDataSourceType.Method)]
+ [TestMethod]
+ public void TestMethod311(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData("GetSomeDataJaggedArray", typeof(SomeClass), DynamicDataSourceType.Method)]
+ [TestMethod]
+ public void TestMethod312(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData(dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetDataJaggedArray")]
+ [TestMethod]
+ public void TestMethod313(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetSomeDataJaggedArray")]
+ [TestMethod]
+ public void TestMethod314(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData("DataNonObjectTypeArray")]
+ [TestMethod]
+ public void TestMethod401(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData("SomeDataNonObjectTypeArray", typeof(SomeClass))]
+ [TestMethod]
+ public void TestMethod402(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData(dynamicDataSourceName: "DataNonObjectTypeArray")]
+ [TestMethod]
+ public void TestMethod403(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceName: "SomeDataNonObjectTypeArray")]
+ [TestMethod]
+ public void TestMethod404(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData("GetDataNonObjectTypeArray", DynamicDataSourceType.Method)]
+ [TestMethod]
+ public void TestMethod411(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData("GetSomeDataNonObjectTypeArray", typeof(SomeClass), DynamicDataSourceType.Method)]
+ [TestMethod]
+ public void TestMethod412(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData(dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetDataNonObjectTypeArray")]
+ [TestMethod]
+ public void TestMethod413(MyTestClass[] testClasses)
+ {
+ }
+
+ [DynamicData(dynamicDataDeclaringType: typeof(SomeClass), dynamicDataSourceType: DynamicDataSourceType.Method, dynamicDataSourceName: "GetSomeDataNonObjectTypeArray")]
+ [TestMethod]
+ public void TestMethod414(MyTestClass[] testClasses)
+ {
+ }
+
public static IEnumerable