public TestOutcome Execute(string testMetadataPath, string testResultsPath, string runConfigPath, string searchPathRoot) { TextWriter writer = assemblyTestContext.LogWriter["MSTest Output"]; string executablePath = MSTestResolver.FindMSTestPathForVisualStudioVersion(runner.GetVisualStudioVersion()); if (executablePath == null) { assemblyTestContext.LogWriter.Failures.Write(Resources.MSTestController_MSTestExecutableNotFound); return(TestOutcome.Error); } string executableDir = Path.GetDirectoryName(executablePath); string privateAssembliesDir = Path.Combine(executableDir, "PrivateAssemblies"); string publicAssembliesDir = Path.Combine(executableDir, "PublicAssemblies"); RuntimeAccessor.AssemblyLoader.AddHintDirectory(executableDir); RuntimeAccessor.AssemblyLoader.AddHintDirectory(privateAssembliesDir); RuntimeAccessor.AssemblyLoader.AddHintDirectory(publicAssembliesDir); // Obtain an Executor. Assembly commandLineAssembly = Assembly.Load(runner.GetCommandLineAssemblyName()); Type executorType = commandLineAssembly.GetType("Microsoft.VisualStudio.TestTools.CommandLine.Executor"); object executor = Activator.CreateInstance(executorType); try { // Configure the Executor's Output to send output to the assembly log writer. PropertyInfo outputProperty = executorType.GetProperty("Output", BindingFlags.Public | BindingFlags.Static); object output = outputProperty.GetValue(executor, null); FieldInfo standardOutputField = output.GetType().GetField("m_standardOutput", BindingFlags.NonPublic | BindingFlags.Instance); standardOutputField.SetValue(output, new StreamWriterAdapter(writer)); // Register commands with the executor to set command-line arguments. Type commandFactoryType = commandLineAssembly.GetType("Microsoft.VisualStudio.TestTools.CommandLine.CommandFactory"); CreateAndAddCommand(executor, commandFactoryType, "/nologo", null); CreateAndAddCommand(executor, commandFactoryType, "/noisolation", null); CreateAndAddCommand(executor, commandFactoryType, "/testmetadata", testMetadataPath); CreateAndAddCommand(executor, commandFactoryType, "/resultsfile", testResultsPath); CreateAndAddCommand(executor, commandFactoryType, "/runconfig", runConfigPath); CreateAndAddCommand(executor, commandFactoryType, "/searchpathroot", searchPathRoot); CreateAndAddCommand(executor, commandFactoryType, "/testlist", SelectedTestListName); // Get the TMI. tmi = commandFactoryType.GetProperty("Tmi", BindingFlags.Public | BindingFlags.Static).GetValue(null, null); // Add event handlers. AddEventHandler(tmi, "TestRunStartedEvent", HandleTestRunStarted); AddEventHandler(tmi, "TestRunFinishedEvent", HandleTestRunFinished); AddEventHandler(tmi, "TestStartedEvent", HandleTestStarted); AddEventHandler(tmi, "TestFinishedEvent", HandleTestFinished); // Execute! InitializeLookupTables(); bool success = (bool)executorType.GetMethod("Execute").Invoke(executor, null); TestOutcome assemblyOutcome = assemblyTestStepState.Outcome; if (!success) { assemblyOutcome = TestOutcome.Error; } return(assemblyOutcome); } catch (Exception ex) { assemblyTestContext.LogWriter.Failures.WriteException(ex, "A fatal exception occurred while running MSTest tests."); return(TestOutcome.Error); } finally { // Release state. assemblyTestStepState = null; tmi = null; testCommandsByTestId.Clear(); testStepStatesByTestResultId.Clear(); testStepStatesByTest.Clear(); testsExecuted.Clear(); // Dispose the Executor. (Also disposes the TMI behind the scenes.) ((IDisposable)executor).Dispose(); } }