diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestAssemblyInfo.cs b/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestAssemblyInfo.cs
index 3f8488795b..d0d55e17ce 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestAssemblyInfo.cs
+++ b/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestAssemblyInfo.cs
@@ -86,7 +86,7 @@ internal set
///
/// Gets or sets the assembly initialization exception.
///
- public Exception? AssemblyInitializationException { get; internal set; }
+ public TestFailedException? AssemblyInitializationException { get; internal set; }
///
/// Gets the assembly cleanup exception.
@@ -110,15 +110,19 @@ internal set
///
/// Runs assembly initialize method.
///
- /// The test context.
- /// Throws a test failed exception if the initialization method throws an exception.
- public async Task RunAssemblyInitializeAsync(TestContext testContext)
+ /// The test context.
+ ///
+ /// A whose is
+ /// when the assembly initialization succeeds, or the failure outcome with
+ /// set when the initialization fails.
+ ///
+ public async Task RunAssemblyInitializeAsync(TestContext testContext)
{
// No assembly initialize => nothing to do.
if (AssemblyInitializeMethod == null)
{
IsAssemblyInitializeExecuted = true;
- return;
+ return new TestResult { Outcome = UnitTestOutcome.Passed };
}
// If assembly initialization is not done, then do it.
@@ -161,7 +165,7 @@ public async Task RunAssemblyInitializeAsync(TestContext testContext)
}
catch (Exception ex)
{
- AssemblyInitializationException = ex;
+ AssemblyInitializationException = GetTestFailedExceptionFromAssemblyInitializeException(ex, AssemblyInitializeMethod);
}
finally
{
@@ -176,37 +180,30 @@ public async Task RunAssemblyInitializeAsync(TestContext testContext)
}
// If assemblyInitialization was successful, then don't do anything
- if (AssemblyInitializationException == null)
- {
- return;
- }
-
- // If the exception is already a `TestFailedException` we throw it as-is
- if (AssemblyInitializationException is TestFailedException)
- {
- throw AssemblyInitializationException;
- }
+ return AssemblyInitializationException is null
+ ? new TestResult { Outcome = UnitTestOutcome.Passed }
+ : new TestResult { TestFailureException = AssemblyInitializationException, Outcome = AssemblyInitializationException.Outcome };
+ }
- Exception realException = AssemblyInitializationException.GetRealException();
+ private static TestFailedException GetTestFailedExceptionFromAssemblyInitializeException(Exception ex, MethodInfo assemblyInitializeMethod)
+ {
+ Exception realException = ex.GetRealException();
UnitTestOutcome outcome = realException is AssertInconclusiveException ? UnitTestOutcome.Inconclusive : UnitTestOutcome.Failed;
// Do not use StackTraceHelper.GetFormattedExceptionMessage(realException) as it prefixes the message with the exception type name.
string exceptionMessage = realException.TryGetMessage();
- DebugEx.Assert(AssemblyInitializeMethod.DeclaringType?.FullName is not null, "AssemblyInitializeMethod.DeclaringType.FullName is null");
+ DebugEx.Assert(assemblyInitializeMethod.DeclaringType?.FullName is not null, "AssemblyInitializeMethod.DeclaringType.FullName is null");
string errorMessage = string.Format(
CultureInfo.CurrentCulture,
Resource.UTA_AssemblyInitMethodThrows,
- AssemblyInitializeMethod.DeclaringType.FullName,
- AssemblyInitializeMethod.Name,
+ assemblyInitializeMethod.DeclaringType.FullName,
+ assemblyInitializeMethod.Name,
realException.GetType().ToString(),
exceptionMessage);
StackTraceInformation? exceptionStackTraceInfo = realException.GetStackTraceInformation();
- var testFailedException = new TestFailedException(outcome, errorMessage, exceptionStackTraceInfo, realException);
- AssemblyInitializationException = testFailedException;
-
- throw testFailedException;
+ return new TestFailedException(outcome, errorMessage, exceptionStackTraceInfo, realException);
}
///
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Execution/UnitTestRunner.cs b/src/Adapter/MSTestAdapter.PlatformServices/Execution/UnitTestRunner.cs
index 6608e4f9d2..501f3f8976 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/Execution/UnitTestRunner.cs
+++ b/src/Adapter/MSTestAdapter.PlatformServices/Execution/UnitTestRunner.cs
@@ -244,15 +244,11 @@ internal async Task RunSingleTestAsync(UnitTestElement unitTestEle
private static async Task RunAssemblyInitializeIfNeededAsync(TestMethodInfo testMethodInfo, ITestContext testContext)
{
- var result = new TestResult { Outcome = UnitTestOutcome.Passed };
+ TestResult? result = null;
try
{
- await testMethodInfo.Parent.Parent.RunAssemblyInitializeAsync(testContext.Context).ConfigureAwait(false);
- }
- catch (TestFailedException ex)
- {
- result = new TestResult { TestFailureException = ex, Outcome = ex.Outcome };
+ result = await testMethodInfo.Parent.Parent.RunAssemblyInitializeAsync(testContext.Context).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -262,7 +258,7 @@ private static async Task RunAssemblyInitializeIfNeededAsync(TestMet
finally
{
var testContextImpl = testContext.Context as TestContextImplementation;
- result.LogOutput = testContextImpl?.GetOut();
+ result!.LogOutput = testContextImpl?.GetOut();
result.LogError = testContextImpl?.GetErr();
result.DebugTrace = testContextImpl?.GetTrace();
result.TestContextMessages = testContext.GetAndClearDiagnosticMessages();
diff --git a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestAssemblyInfoTests.cs b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestAssemblyInfoTests.cs
index 66beaace09..fe081e28cd 100644
--- a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestAssemblyInfoTests.cs
+++ b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestAssemblyInfoTests.cs
@@ -58,7 +58,7 @@ void Action()
public void TestAssemblyHasExecutableCleanupMethodShouldReturnTrueEvenIfAssemblyInitializationThrewAnException()
{
_testAssemblyInfo.AssemblyCleanupMethod = _dummyMethodInfo;
- _testAssemblyInfo.AssemblyInitializationException = new NotImplementedException();
+ _testAssemblyInfo.AssemblyInitializationException = new TestFailedException(UnitTestOutcome.Error, "ERROR");
_testAssemblyInfo.HasExecutableCleanupMethod.Should().BeTrue();
}
@@ -79,9 +79,10 @@ public async Task RunAssemblyInitializeShouldNotInvokeIfAssemblyInitializeIsNull
_testAssemblyInfo.AssemblyInitializeMethod = null;
- await _testAssemblyInfo.RunAssemblyInitializeAsync(null!);
+ TestResult result = await _testAssemblyInfo.RunAssemblyInitializeAsync(null!);
assemblyInitCallCount.Should().Be(0);
+ result.Outcome.Should().Be(UnitTestOutcome.Passed);
}
public async Task RunAssemblyInitializeShouldNotExecuteAssemblyInitializeIfItHasAlreadyExecuted()
@@ -92,9 +93,10 @@ public async Task RunAssemblyInitializeShouldNotExecuteAssemblyInitializeIfItHas
_testAssemblyInfo.IsAssemblyInitializeExecuted = true;
_testAssemblyInfo.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("AssemblyInitializeMethod")!;
- await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext);
+ TestResult result = await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext);
assemblyInitCallCount.Should().Be(0);
+ result.Outcome.Should().Be(UnitTestOutcome.Passed);
}
public async Task RunAssemblyInitializeShouldExecuteAssemblyInitialize()
@@ -103,9 +105,10 @@ public async Task RunAssemblyInitializeShouldExecuteAssemblyInitialize()
DummyTestClass.AssemblyInitializeMethodBody = _ => assemblyInitCallCount++;
_testAssemblyInfo.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("AssemblyInitializeMethod")!;
- await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext);
+ TestResult result = await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext);
assemblyInitCallCount.Should().Be(1);
+ result.Outcome.Should().Be(UnitTestOutcome.Passed);
}
public async Task RunAssemblyInitializeShouldSetAssemblyInitializeExecutedFlag()
@@ -114,9 +117,10 @@ public async Task RunAssemblyInitializeShouldSetAssemblyInitializeExecutedFlag()
_testAssemblyInfo.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("AssemblyInitializeMethod")!;
- await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext);
+ TestResult result = await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext);
_testAssemblyInfo.IsAssemblyInitializeExecuted.Should().BeTrue();
+ result.Outcome.Should().Be(UnitTestOutcome.Passed);
}
public async Task RunAssemblyInitializeShouldSetAssemblyInitializationExceptionOnException()
@@ -126,9 +130,9 @@ public async Task RunAssemblyInitializeShouldSetAssemblyInitializationExceptionO
#pragma warning restore RS0030 // Do not use banned APIs
_testAssemblyInfo.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("AssemblyInitializeMethod")!;
- Func action = () => _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext);
-
- await action.Should().ThrowAsync();
+ TestResult testResult = await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext);
+ testResult.Should().NotBeNull();
+ testResult.TestFailureException.Should().NotBeNull();
_testAssemblyInfo.AssemblyInitializationException.Should().NotBeNull();
}
@@ -139,7 +143,8 @@ public async Task RunAssemblyInitializeShouldThrowTestFailedExceptionOnAssertion
#pragma warning restore RS0030 // Do not use banned APIs
_testAssemblyInfo.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("AssemblyInitializeMethod")!;
- TestFailedException exception = (await new Func(() => _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext)).Should().ThrowAsync()).Which;
+ 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.StackTraceInformation!.ErrorStackTrace.Should().Contain(
@@ -154,7 +159,8 @@ public async Task RunAssemblyInitializeShouldThrowTestFailedExceptionWithInconcl
#pragma warning restore RS0030 // Do not use banned APIs
_testAssemblyInfo.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("AssemblyInitializeMethod")!;
- TestFailedException exception = (await new Func(() => _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext)).Should().ThrowAsync()).Which;
+ 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.StackTraceInformation!.ErrorStackTrace.Should().Contain(
@@ -167,8 +173,8 @@ public async Task RunAssemblyInitializeShouldThrowTestFailedExceptionWithNonAsse
DummyTestClass.AssemblyInitializeMethodBody = tc => throw new ArgumentException("Some actualErrorMessage message", new InvalidOperationException("Inner actualErrorMessage message"));
_testAssemblyInfo.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("AssemblyInitializeMethod")!;
- TestFailedException exception = (await new Func(() => _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext)).Should().ThrowAsync()).Which;
-
+ 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. System.ArgumentException: Some actualErrorMessage message. Aborting test execution.");
exception.StackTraceInformation!.ErrorStackTrace.Should().Contain(
@@ -186,8 +192,8 @@ public async Task RunAssemblyInitializeShouldThrowTheInnerMostExceptionWhenThere
FailingStaticHelper.DoWork();
_testAssemblyInfo.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("AssemblyInitializeMethod")!;
- TestFailedException exception = (await new Func(() => _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext)).Should().ThrowAsync()).Which;
-
+ 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. System.InvalidOperationException: I fail.. Aborting test execution.");
exception.StackTraceInformation!.ErrorStackTrace.StartsWith(
@@ -202,17 +208,25 @@ public async Task RunAssemblyInitializeShouldThrowForAlreadyExecutedTestAssembly
_testAssemblyInfo.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("AssemblyInitializeMethod")!;
_testAssemblyInfo.AssemblyInitializationException = new TestFailedException(UnitTestOutcome.Failed, "Cached Test failure");
- TestFailedException exception = (await new Func(() => _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext)).Should().ThrowAsync()).Which;
+ var exception = (await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext)).TestFailureException as TestFailedException;
+ exception.Should().NotBeNull();
exception.Outcome.Should().Be(UnitTestOutcome.Failed);
exception.Message.Should().Be("Cached Test failure");
}
public async Task RunAssemblyInitializeShouldPassOnTheTestContextToAssemblyInitMethod()
{
- DummyTestClass.AssemblyInitializeMethodBody = tc => (tc == _testContext).Should().BeTrue();
+ bool hasExecuted = false;
+ DummyTestClass.AssemblyInitializeMethodBody = tc =>
+ {
+ (tc == _testContext).Should().BeTrue();
+ hasExecuted = true;
+ };
_testAssemblyInfo.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("AssemblyInitializeMethod")!;
- await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext);
+ TestResult result = await _testAssemblyInfo.RunAssemblyInitializeAsync(_testContext);
+ hasExecuted.Should().BeTrue();
+ result.Outcome.Should().Be(UnitTestOutcome.Passed);
}
#endregion