private TestResult ExecuteInternal()

in src/Adapter/MSTest.CoreAdapter/Execution/TestMethodInfo.cs [250:348]


        private TestResult ExecuteInternal(object[] arguments)
        {
            Debug.Assert(this.TestMethod != null, "UnitTestExecuter.DefaultTestMethodInvoke: testMethod = null.");

            var result = new TestResult();

            // TODO remove dry violation with TestMethodRunner
            var classInstance = this.CreateTestClassInstance(result);
            var testContextSetup = false;
            bool isExceptionThrown = false;
            bool hasTestInitializePassed = false;
            Exception testRunnerException = null;

            try
            {
                try
                {
                    if (classInstance != null && this.SetTestContext(classInstance, result))
                    {
                        // For any failure after this point, we must run TestCleanup
                        testContextSetup = true;

                        if (this.RunTestInitializeMethod(classInstance, result))
                        {
                            hasTestInitializePassed = true;
                            PlatformServiceProvider.Instance.ThreadOperations.ExecuteWithAbortSafety(
                                () => this.TestMethod.InvokeAsSynchronousTask(classInstance, arguments));
                            result.Outcome = TestTools.UnitTesting.UnitTestOutcome.Passed;
                        }
                    }
                }
                catch (Exception ex)
                {
                    isExceptionThrown = true;

                    if (this.IsExpectedException(ex, result))
                    {
                        // Expected Exception was thrown, so Pass the test
                        result.Outcome = TestTools.UnitTesting.UnitTestOutcome.Passed;
                    }
                    else if (result.TestFailureException == null)
                    {
                        // This block should not throw. If it needs to throw, then handling of
                        // ThreadAbortException will need to be revisited. See comment in RunTestMethod.
                        result.TestFailureException = this.HandleMethodException(
                            ex,
                            this.TestClassName,
                            this.TestMethodName);
                    }

                    if (result.Outcome != TestTools.UnitTesting.UnitTestOutcome.Passed)
                    {
                        if (ex is UTF.AssertInconclusiveException || ex.InnerException is UTF.AssertInconclusiveException)
                        {
                            result.Outcome = TestTools.UnitTesting.UnitTestOutcome.Inconclusive;
                        }
                        else
                        {
                            result.Outcome = TestTools.UnitTesting.UnitTestOutcome.Failed;
                        }
                    }
                }

                // if we get here, the test method did not throw the exception
                // if the user specified that the test was going to throw an exception, and
                // it did not, we should fail the test
                // We only perform this check if the test initialize passes and the test method is actually run.
                if (hasTestInitializePassed && !isExceptionThrown && this.TestMethodOptions.ExpectedException != null)
                {
                    result.TestFailureException = new TestFailedException(
                        UnitTestOutcome.Failed,
                        this.TestMethodOptions.ExpectedException.NoExceptionMessage);
                    result.Outcome = TestTools.UnitTesting.UnitTestOutcome.Failed;
                }
            }
            catch (Exception exception)
            {
                testRunnerException = exception;
            }

            // Set the current tests outcome before cleanup so it can be used in the cleanup logic.
            this.TestMethodOptions.TestContext.SetOutcome(result.Outcome);

            // TestCleanup can potentially be a long running operation which shouldn't ideally be in a finally block.
            // Pulling it out so extension writers can abort custom cleanups if need be. Having this in a finally block
            // does not allow a thread abort exception to be raised within the block but throws one after finally is executed
            // crashing the process. This was blocking writing an extension for Dynamic Timeout in VSO.
            if (classInstance != null && testContextSetup)
            {
                this.RunTestCleanupMethod(classInstance, result);
            }

            if (testRunnerException != null)
            {
                throw testRunnerException;
            }

            return result;
        }