From 67fa1bb4a4c4f73d3cad82df50605fa42333e9df Mon Sep 17 00:00:00 2001
From: Copilot <223556219+Copilot@users.noreply.github.com>
Date: Sat, 16 May 2026 18:39:51 +0200
Subject: [PATCH 1/2] Apply structured assertion messages (RFC 012) to
Assert.Fail / Assert.Inconclusive
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../TestFramework/Assertions/Assert.Fail.cs | 5 +-
.../Assertions/Assert.Inconclusive.cs | 10 +++-
.../Resources/FrameworkMessages.resx | 3 +
.../Resources/xlf/FrameworkMessages.cs.xlf | 5 ++
.../Resources/xlf/FrameworkMessages.de.xlf | 5 ++
.../Resources/xlf/FrameworkMessages.es.xlf | 5 ++
.../Resources/xlf/FrameworkMessages.fr.xlf | 5 ++
.../Resources/xlf/FrameworkMessages.it.xlf | 5 ++
.../Resources/xlf/FrameworkMessages.ja.xlf | 5 ++
.../Resources/xlf/FrameworkMessages.ko.xlf | 5 ++
.../Resources/xlf/FrameworkMessages.pl.xlf | 5 ++
.../Resources/xlf/FrameworkMessages.pt-BR.xlf | 5 ++
.../Resources/xlf/FrameworkMessages.ru.xlf | 5 ++
.../Resources/xlf/FrameworkMessages.tr.xlf | 5 ++
.../xlf/FrameworkMessages.zh-Hans.xlf | 5 ++
.../xlf/FrameworkMessages.zh-Hant.xlf | 5 ++
.../RetryTests.cs | 2 +-
.../Execution/TestAssemblyInfoTests.cs | 8 +--
.../Execution/TestClassInfoTests.cs | 8 +--
.../Execution/TestExecutionManagerTests.cs | 2 +-
.../Execution/TestMethodInfoTests.cs | 10 ++--
.../AssertTests.FailInconclusive.cs | 56 +++++++++++++++++++
.../AssertTests.InconclusiveTests.cs | 2 +-
.../Assertions/AssertTests.ScopeTests.cs | 6 +-
24 files changed, 157 insertions(+), 20 deletions(-)
create mode 100644 test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.FailInconclusive.cs
diff --git a/src/TestFramework/TestFramework/Assertions/Assert.Fail.cs b/src/TestFramework/TestFramework/Assertions/Assert.Fail.cs
index e377044d5a..b5558784f3 100644
--- a/src/TestFramework/TestFramework/Assertions/Assert.Fail.cs
+++ b/src/TestFramework/TestFramework/Assertions/Assert.Fail.cs
@@ -24,6 +24,9 @@ public sealed partial class Assert
public static void Fail(string message = "")
{
TelemetryCollector.TrackAssertionCall("Assert.Fail");
- ThrowAssertFailed("Assert.Fail", BuildUserMessage(message));
+
+ StructuredAssertionMessage structured = new(string.Empty);
+ structured.WithUserMessage(message);
+ ThrowAssertFailed(structured);
}
}
diff --git a/src/TestFramework/TestFramework/Assertions/Assert.Inconclusive.cs b/src/TestFramework/TestFramework/Assertions/Assert.Inconclusive.cs
index ecd743b0c9..65d79b4ab5 100644
--- a/src/TestFramework/TestFramework/Assertions/Assert.Inconclusive.cs
+++ b/src/TestFramework/TestFramework/Assertions/Assert.Inconclusive.cs
@@ -26,7 +26,13 @@ public static void Inconclusive(string message = "")
TelemetryCollector.TrackAssertionCall("Assert.Inconclusive");
string userMessage = BuildUserMessage(message);
- throw new AssertInconclusiveException(
- FormatAssertionFailed("Assert.Inconclusive", userMessage));
+ throw new AssertInconclusiveException(FormatInconclusive(userMessage));
}
+
+ private static string FormatInconclusive(string? message)
+ => string.IsNullOrWhiteSpace(message)
+ ? FrameworkMessages.InconclusivePrefix
+ : message![0] is '\n' or '\r'
+ ? string.Concat(FrameworkMessages.InconclusivePrefix, message)
+ : $"{FrameworkMessages.InconclusivePrefix} {message}";
}
diff --git a/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx b/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx
index 4c06871944..cca6a902a6 100644
--- a/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx
+++ b/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx
@@ -289,6 +289,9 @@ Actual: {2}
{0} failed.
+
+ Assert.Inconclusive.
+
{0} Expected type:<{1}>. Actual type:<{2}>.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf
index b2828f2192..494ef0b370 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf
@@ -442,6 +442,11 @@ Skutečnost: {2}
Očekávala se kolekce {1} velikosti. Skutečnost: {2} {0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
Vlastnost TestContext.{0} souvisí s aktuálním testem a není k dispozici během sestavení nebo používání testovacích přípravků tříd.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf
index 3b0497e62d..d75d6880b9 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf
@@ -442,6 +442,11 @@ Tatsächlich: {2}
Es wurde eine Sammlung mit einer Größe {1} erwartet. Tatsächlich: {2}. {0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
Die Eigenschaft „TestContext.{0}“ im Zusammenhang mit dem aktuellen Test steht während Assembly- oder Klassenfixierungen nicht zur Verfügung.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf
index f6180a742f..3676037ee7 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf
@@ -442,6 +442,11 @@ Real: {2}
Se esperaba una colección de tamaño {1}. Real: {2}. {0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
La propiedad "TestContext.{0}" está relacionado con la prueba actual y no está disponible durante los accesorios de ensamblado o clase.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf
index 21e859b0b8..0faed641e3 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf
@@ -442,6 +442,11 @@ Réel : {2}
Collection de tailles attendue {1}. Réel : {2}. {0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
La propriété « TestContext.{0} », liée au test en cours, n’est pas disponible pendant les fixtures d’assembly ou de classe.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf
index 6d2040c828..f0173929f3 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf
@@ -442,6 +442,11 @@ Effettivo: {2}
Prevista raccolta di dimensioni {1}. Effettivo: {2}. {0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
La proprietà 'TestContext.{0}' relativa al test corrente non è disponibile durante le fixture di assembly o classe.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf
index 392fa6ef72..de3ba8d95b 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf
@@ -442,6 +442,11 @@ Actual: {2}
サイズ {1} のコレクションが必要です。実際: {2}。{0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
プロパティ 'TestContext.{0}' は現在のテストに関連しており、アセンブリまたはクラス フィクスチャの間は使用できません。
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf
index caed5cd6c5..ff7817e6cc 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf
@@ -442,6 +442,11 @@ Actual: {2}
{1} 크기 컬렉션이 필요합니다. 실제: {2}. {0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
현재 테스트와 관련된 'TestContext.{0}' 속성은 어셈블리나 클래스 픽스처 실행 중에는 사용할 수 없습니다.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf
index 5da692e8b6..fb82ee88fa 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf
@@ -442,6 +442,11 @@ Rzeczywiste: {2}
Oczekiwano kolekcji rozmiaru {1}. Wartość rzeczywista: {2}. {0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
Właściwość „TestContext.{0}” jest powiązana z bieżącym testem i nie jest dostępna podczas montażu lub konfiguracji klasy.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf
index 935e661ad4..0aabcd371f 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf
@@ -442,6 +442,11 @@ Real: {2}
Coleção esperada de tamanho {1}. Real: {2}. {0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
A propriedade "TestContext.{0}" está relacionada ao teste atual não está disponível durante os acessórios de assembly ou classe.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf
index 310e5898df..54f52b0998 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf
@@ -442,6 +442,11 @@ Actual: {2}
Ожидается коллекция размеров {1}. Фактически: {2}. {0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
Свойство "TestContext.{0}" связано с текущим тестом и недоступно во время выполнения средств тестирования сборок или классов.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf
index 5bb57205a5..a88a1c8356 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf
@@ -442,6 +442,11 @@ Gerçekte olan: {2}
Beklenen boyut {1}. Gerçek: {2}. {0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
'TestContext.{0}' özelliği, derleme veya sınıf sabitlemeleri sırasında mevcut testle ilişkili değildir.
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf
index 6fa3cb17f3..eec7bdabd1 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf
@@ -442,6 +442,11 @@ Actual: {2}
大小 {1} 的预期集合。实际: {2}。{0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
属性‘TestContext.{0}’与当前测试相关,在程序集或类固定例程期间不可用。
diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf
index 366ab94673..b1f6004156 100644
--- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf
+++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf
@@ -442,6 +442,11 @@ Actual: {2}
預期的大小集合 {1}。實際: {2}。{0}
+
+ Assert.Inconclusive.
+ Assert.Inconclusive.
+
+
The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures.
屬性 'TestContext.{0}' 與目前測試相關,無法在組件或類別測試夾具期間使用。
diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/RetryTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/RetryTests.cs
index 4d8ff10a08..bcaf20e488 100644
--- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/RetryTests.cs
+++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/RetryTests.cs
@@ -26,7 +26,7 @@ TestMethod5 executed 4 times.
""");
testHostResult.AssertOutputContains("failed TestMethod5");
- testHostResult.AssertOutputContains("Assert.Fail failed. Failing TestMethod4. Attempts: 4 (from TestContext: 4)");
+ testHostResult.AssertOutputContains("Assertion failed.\r\nFailing TestMethod4. Attempts: 4 (from TestContext: 4)");
testHostResult.AssertOutputContainsSummary(failed: 1, passed: 4, skipped: 0);
}
diff --git a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestAssemblyInfoTests.cs b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestAssemblyInfoTests.cs
index fe081e28cd..8450abb090 100644
--- a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestAssemblyInfoTests.cs
+++ b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestAssemblyInfoTests.cs
@@ -146,7 +146,7 @@ public async Task RunAssemblyInitializeShouldThrowTestFailedExceptionOnAssertion
var exception = (await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext)).TestFailureException as TestFailedException;
exception.Should().NotBeNull();
exception.Outcome.Should().Be(UnitTestOutcome.Failed);
- exception.Message.Should().Be("Assembly Initialization method Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestAssemblyInfoTests+DummyTestClass.AssemblyInitializeMethod threw exception. Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Assert.Fail failed. Test failure. Aborting test execution.");
+ exception.Message.Should().Be("Assembly Initialization method Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestAssemblyInfoTests+DummyTestClass.AssemblyInitializeMethod threw exception. Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Assertion failed.\r\nTest failure. Aborting test execution.");
exception.StackTraceInformation!.ErrorStackTrace.Should().Contain(
"Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestAssemblyInfoTests.DummyTestClass.AssemblyInitializeMethod");
exception.InnerException.Should().BeOfType();
@@ -162,7 +162,7 @@ public async Task RunAssemblyInitializeShouldThrowTestFailedExceptionWithInconcl
var exception = (await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext)).TestFailureException as TestFailedException;
exception.Should().NotBeNull();
exception.Outcome.Should().Be(UnitTestOutcome.Inconclusive);
- exception.Message.Should().Be("Assembly Initialization method Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestAssemblyInfoTests+DummyTestClass.AssemblyInitializeMethod threw exception. Microsoft.VisualStudio.TestTools.UnitTesting.AssertInconclusiveException: Assert.Inconclusive failed. Test Inconclusive. Aborting test execution.");
+ exception.Message.Should().Be("Assembly Initialization method Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestAssemblyInfoTests+DummyTestClass.AssemblyInitializeMethod threw exception. Microsoft.VisualStudio.TestTools.UnitTesting.AssertInconclusiveException: Assert.Inconclusive. Test Inconclusive. Aborting test execution.");
exception.StackTraceInformation!.ErrorStackTrace.Should().Contain(
"Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestAssemblyInfoTests.DummyTestClass.AssemblyInitializeMethod");
exception.InnerException.Should().BeOfType();
@@ -264,7 +264,7 @@ public async Task RunAssemblyCleanupShouldReturnAssertFailureExceptionDetails()
_testAssemblyInfo.AssemblyCleanupMethod = typeof(DummyTestClass).GetMethod("AssemblyCleanupMethod")!;
string? actualErrorMessage = (await _testAssemblyInfo.ExecuteAssemblyCleanupAsync(GetTestContext()))?.Message;
actualErrorMessage!.StartsWith(
- "Assembly Cleanup method DummyTestClass.AssemblyCleanupMethod failed. Error Message: Assert.Fail failed. Test Failure..", StringComparison.Ordinal).Should().BeTrue($"Value: {actualErrorMessage}");
+ "Assembly Cleanup method DummyTestClass.AssemblyCleanupMethod failed. Error Message: Assertion failed.\r\nTest Failure..", StringComparison.Ordinal).Should().BeTrue($"Value: {actualErrorMessage}");
}
public async Task RunAssemblyCleanupShouldReturnAssertInconclusiveExceptionDetails()
@@ -276,7 +276,7 @@ public async Task RunAssemblyCleanupShouldReturnAssertInconclusiveExceptionDetai
_testAssemblyInfo.AssemblyCleanupMethod = typeof(DummyTestClass).GetMethod("AssemblyCleanupMethod")!;
string? actualErrorMessage = (await _testAssemblyInfo.ExecuteAssemblyCleanupAsync(GetTestContext()))?.Message;
actualErrorMessage!.StartsWith(
- "Assembly Cleanup method DummyTestClass.AssemblyCleanupMethod failed. Error Message: Assert.Inconclusive failed. Test Inconclusive..", StringComparison.Ordinal).Should().BeTrue($"Value: {actualErrorMessage}");
+ "Assembly Cleanup method DummyTestClass.AssemblyCleanupMethod failed. Error Message: Assert.Inconclusive. Test Inconclusive..", StringComparison.Ordinal).Should().BeTrue($"Value: {actualErrorMessage}");
}
public async Task RunAssemblyCleanupShouldReturnExceptionDetailsOfNonAssertExceptions()
diff --git a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestClassInfoTests.cs b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestClassInfoTests.cs
index 1db8a177bc..d131c9b542 100644
--- a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestClassInfoTests.cs
+++ b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestClassInfoTests.cs
@@ -350,7 +350,7 @@ public void RunClassInitializeShouldThrowTestFailedExceptionOnAssertionFailure()
exception.Should().NotBeNull();
exception.Outcome.Should().Be(UnitTestOutcome.Failed);
- exception.Message.Should().Be("Class Initialization method Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestClassInfoTests+DummyTestClass.ClassInitializeMethod threw exception. Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Assert.Fail failed. Test failure.");
+ exception.Message.Should().Be("Class Initialization method Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestClassInfoTests+DummyTestClass.ClassInitializeMethod threw exception. Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Assertion failed.\r\nTest failure.");
exception.StackTraceInformation!.ErrorStackTrace.Contains(
"Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestClassInfoTests.DummyTestClass.ClassInitializeMethod", StringComparison.Ordinal).Should().BeTrue();
exception.InnerException.Should().BeOfType();
@@ -367,7 +367,7 @@ public void RunClassInitializeShouldThrowTestFailedExceptionWithInconclusiveOnAs
exception.Should().NotBeNull();
exception.Outcome.Should().Be(UnitTestOutcome.Inconclusive);
- exception.Message.Should().Be("Class Initialization method Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestClassInfoTests+DummyTestClass.ClassInitializeMethod threw exception. Microsoft.VisualStudio.TestTools.UnitTesting.AssertInconclusiveException: Assert.Inconclusive failed. Test Inconclusive.");
+ exception.Message.Should().Be("Class Initialization method Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestClassInfoTests+DummyTestClass.ClassInitializeMethod threw exception. Microsoft.VisualStudio.TestTools.UnitTesting.AssertInconclusiveException: Assert.Inconclusive. Test Inconclusive.");
exception.StackTraceInformation!.ErrorStackTrace.Contains(
"Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution.TestClassInfoTests.DummyTestClass.ClassInitializeMethod", StringComparison.Ordinal).Should().BeTrue();
exception.InnerException.Should().BeOfType();
@@ -481,7 +481,7 @@ public async Task RunClassCleanupShouldReturnAssertFailureExceptionDetails()
// Assert
classCleanupException.Should().NotBeNull();
classCleanupException.Message.StartsWith("Class Cleanup method DummyTestClass.ClassCleanupMethod failed.", StringComparison.Ordinal).Should().BeTrue();
- classCleanupException.Message.Contains("Error Message: Assert.Fail failed. Test Failure.").Should().BeTrue();
+ classCleanupException.Message.Contains("Error Message: Assertion failed.\r\nTest Failure.").Should().BeTrue();
classCleanupException.Message.Should().Contain(
$"{typeof(TestClassInfoTests).FullName}.DummyTestClass.ClassCleanupMethod",
$"Value: {classCleanupException.Message}");
@@ -502,7 +502,7 @@ public async Task RunClassCleanupShouldReturnAssertInconclusiveExceptionDetails(
// Assert
classCleanupException.Should().NotBeNull();
classCleanupException.Message.StartsWith("Class Cleanup method DummyTestClass.ClassCleanupMethod failed.", StringComparison.Ordinal).Should().BeTrue();
- classCleanupException.Message.Contains("Error Message: Assert.Inconclusive failed. Test Inconclusive.").Should().BeTrue();
+ classCleanupException.Message.Contains("Error Message: Assert.Inconclusive. Test Inconclusive.").Should().BeTrue();
classCleanupException.Message.Should().Contain(
$"{typeof(TestClassInfoTests).FullName}.DummyTestClass.ClassCleanupMethod",
$"Value: {classCleanupException.Message}");
diff --git a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestExecutionManagerTests.cs b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestExecutionManagerTests.cs
index e9ead72c13..59608bc623 100644
--- a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestExecutionManagerTests.cs
+++ b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestExecutionManagerTests.cs
@@ -159,7 +159,7 @@ public async Task RunTestsForMultipleTestShouldSendMultipleResults()
List expectedTestCaseStartList = ["PassingTest", "FailingTest"];
List expectedTestCaseEndList = ["PassingTest:Passed", "FailingTest:Failed"];
- List expectedResultList = ["PassingTest Passed", "FailingTest Failed\r\n Message: Assert.Fail failed."];
+ List expectedResultList = ["PassingTest Passed", "FailingTest Failed\r\n Message: Assertion failed."];
expectedTestCaseStartList.SequenceEqual(_frameworkHandle.TestCaseStartList).Should().BeTrue();
expectedTestCaseEndList.SequenceEqual(_frameworkHandle.TestCaseEndList).Should().BeTrue();
diff --git a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestMethodInfoTests.cs b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestMethodInfoTests.cs
index e4ed2fa1a8..8335a860c7 100644
--- a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestMethodInfoTests.cs
+++ b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestMethodInfoTests.cs
@@ -863,7 +863,7 @@ public async Task TestMethodInfoInvokeWhenTestThrowsAssertFailReturnsExpectedRes
Resource.UTA_InitMethodThrows,
typeof(DummyTestClass).FullName,
_testClassInfo.TestInitializeMethod!.Name,
- "Assert.Fail failed. dummyFailMessage");
+ "Assertion failed.\r\ndummyFailMessage");
var testMethodInfo = new TestMethodInfo(_methodInfo, _testClassInfo)
{
@@ -898,7 +898,7 @@ public async Task TestMethodInfoInvokeWhenTestThrowsAssertInconclusiveReturnsExp
Resource.UTA_InitMethodThrows,
typeof(DummyTestClass).FullName,
_testClassInfo.TestInitializeMethod!.Name,
- "Assert.Inconclusive failed. dummyFailMessage");
+ "Assert.Inconclusive. dummyFailMessage");
var testMethodInfo = new TestMethodInfo(_methodInfo, _testClassInfo)
{
@@ -942,7 +942,7 @@ public async Task TestMethodInfoInvokeWhenConstructorThrowsAssertInconclusiveRet
var exception = result.TestFailureException as TestFailedException;
exception.Should().NotBeNull();
- exception.Message.Should().Be("Assert.Inconclusive failed. dummyInconclusiveMessage");
+ exception.Message.Should().Be("Assert.Inconclusive. dummyInconclusiveMessage");
exception.Outcome.Should().Be(UnitTestOutcome.Inconclusive);
exception.InnerException.Should().BeOfType();
#if DEBUG
@@ -1110,7 +1110,7 @@ public async Task TestMethodInfoInvokeWhenTestCleanupThrowsAssertInconclusiveRet
Resource.UTA_CleanupMethodThrows,
typeof(DummyTestClass).FullName,
_testClassInfo.TestCleanupMethod.Name,
- "Microsoft.VisualStudio.TestTools.UnitTesting.AssertInconclusiveException: Assert.Inconclusive failed. Test inconclusive");
+ "Microsoft.VisualStudio.TestTools.UnitTesting.AssertInconclusiveException: Assert.Inconclusive. Test inconclusive");
TestResult result = await _testMethodInfo.InvokeAsync(null);
@@ -1137,7 +1137,7 @@ public async Task TestMethodInfoInvokeWhenTestCleanupThrowsAssertFailedReturnsEx
Resource.UTA_CleanupMethodThrows,
typeof(DummyTestClass).FullName,
_testClassInfo.TestCleanupMethod!.Name,
- "Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Assert.Fail failed. Test failed");
+ "Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Assertion failed.\r\nTest failed");
TestResult result = await _testMethodInfo.InvokeAsync(null);
diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.FailInconclusive.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.FailInconclusive.cs
new file mode 100644
index 0000000000..79b631d843
--- /dev/null
+++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.FailInconclusive.cs
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using AwesomeAssertions;
+
+namespace Microsoft.VisualStudio.TestPlatform.TestFramework.UnitTests;
+
+public partial class AssertTests
+{
+ public void FailWithoutMessageShouldUseStructuredPrefixOnly()
+ {
+ Action action = () => Assert.Fail();
+ action.Should().Throw()
+ .WithMessage("Assertion failed.");
+ }
+
+ public void FailWithMessageShouldPlaceUserMessageOnOwnLine()
+ {
+ Action action = () => Assert.Fail("custom reason");
+ action.Should().Throw()
+ .WithMessage(
+ """
+ Assertion failed.
+ custom reason
+ """);
+ }
+
+ public void FailWithEmptyMessageShouldNotAddBlankLine()
+ {
+ Action action = () => Assert.Fail(string.Empty);
+ action.Should().Throw()
+ .WithMessage("Assertion failed.");
+ }
+
+ public void InconclusiveWithoutMessageShouldUseInconclusivePrefix()
+ {
+ Action action = () => Assert.Inconclusive();
+ action.Should().Throw()
+ .WithMessage("Assert.Inconclusive.");
+ }
+
+ public void InconclusiveWithMessageShouldAppendUserMessage()
+ {
+ Action action = () => Assert.Inconclusive("db unavailable");
+ action.Should().Throw()
+ .WithMessage("Assert.Inconclusive. db unavailable");
+ }
+
+ // See https://github.com/dotnet/sdk/issues/25373
+ public void InconclusiveDoesNotThrowWhenMessageContainsInvalidStringFormatCompositeAndNoArgumentsPassed_Regression()
+ {
+ Action action = () => Assert.Inconclusive("{");
+ action.Should().Throw()
+ .WithMessage("Assert.Inconclusive. {");
+ }
+}
diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.InconclusiveTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.InconclusiveTests.cs
index d0b8d8fcc7..f580a72679 100644
--- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.InconclusiveTests.cs
+++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.InconclusiveTests.cs
@@ -12,6 +12,6 @@ public void InconclusiveDoesNotThrowWhenMessageContainsInvalidStringFormatCompos
{
Action action = () => Assert.Inconclusive("{");
action.Should().Throw()
- .And.Message.Should().Contain("Assert.Inconclusive failed. {");
+ .And.Message.Should().Contain("Assert.Inconclusive. {");
}
}
diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ScopeTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ScopeTests.cs
index fe99ada571..6038f2c7fe 100644
--- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ScopeTests.cs
+++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ScopeTests.cs
@@ -122,7 +122,11 @@ public void Scope_AssertFail_IsHardFailure()
// Assert.Fail is a hard assertion — it throws immediately, even within a scope.
action.Should().Throw()
- .WithMessage("Assert.Fail failed. first failure");
+ .WithMessage(
+ """
+ Assertion failed.
+ first failure
+ """);
}
public void Scope_AssertIsNotNull_IsSoftFailure()
From e24a4c57743fe33e83efa6808fc59d1d4d7733fa Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 17 May 2026 09:48:10 +0000
Subject: [PATCH 2/2] Fix review feedback for fail and inconclusive assertions
Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
---
.../MSTest.Acceptance.IntegrationTests/RetryTests.cs | 4 +++-
.../Assertions/AssertTests.FailInconclusive.cs | 7 -------
2 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/RetryTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/RetryTests.cs
index bcaf20e488..677ade2d2e 100644
--- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/RetryTests.cs
+++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/RetryTests.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;
+
using Microsoft.Testing.Platform.Acceptance.IntegrationTests;
using Microsoft.Testing.Platform.Acceptance.IntegrationTests.Helpers;
using Microsoft.Testing.Platform.Helpers;
@@ -26,7 +28,7 @@ TestMethod5 executed 4 times.
""");
testHostResult.AssertOutputContains("failed TestMethod5");
- testHostResult.AssertOutputContains("Assertion failed.\r\nFailing TestMethod4. Attempts: 4 (from TestContext: 4)");
+ testHostResult.AssertOutputContains($"Assertion failed.{Environment.NewLine}Failing TestMethod4. Attempts: 4 (from TestContext: 4)");
testHostResult.AssertOutputContainsSummary(failed: 1, passed: 4, skipped: 0);
}
diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.FailInconclusive.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.FailInconclusive.cs
index 79b631d843..53b9471fd8 100644
--- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.FailInconclusive.cs
+++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.FailInconclusive.cs
@@ -46,11 +46,4 @@ public void InconclusiveWithMessageShouldAppendUserMessage()
.WithMessage("Assert.Inconclusive. db unavailable");
}
- // See https://github.com/dotnet/sdk/issues/25373
- public void InconclusiveDoesNotThrowWhenMessageContainsInvalidStringFormatCompositeAndNoArgumentsPassed_Regression()
- {
- Action action = () => Assert.Inconclusive("{");
- action.Should().Throw()
- .WithMessage("Assert.Inconclusive. {");
- }
}