private static IEnumerable <string> GetDebugArgs(NodejsProjectSettings settings, out int port) { port = GetFreePort(); return(new[] { "--debug-brk=" + port.ToString() }); }
/// <summary> /// This is the equivalent of "Run Selected Tests" functionality. /// </summary> /// <param name="tests">The list of TestCases selected to run</param> /// <param name="runContext">Defines the settings related to the current run</param> /// <param name="frameworkHandle">Handle to framework. Used for recording results</param> public void RunTests(IEnumerable <TestCase> tests, IRunContext runContext, IFrameworkHandle frameworkHandle) { ValidateArg.NotNull(tests, "tests"); ValidateArg.NotNull(runContext, "runContext"); ValidateArg.NotNull(frameworkHandle, "frameworkHandle"); _cancelRequested.Reset(); // .ts file path -> project settings var fileToTests = new Dictionary <string, List <TestCase> >(); var sourceToSettings = new Dictionary <string, NodejsProjectSettings>(); NodejsProjectSettings projectSettings = null; // put tests into dictionary where key is their source file foreach (var test in tests) { if (!fileToTests.ContainsKey(test.CodeFilePath)) { fileToTests[test.CodeFilePath] = new List <TestCase>(); } fileToTests[test.CodeFilePath].Add(test); } // where key is the file and value is a list of tests foreach (var entry in fileToTests) { var firstTest = entry.Value.ElementAt(0); if (!sourceToSettings.TryGetValue(firstTest.Source, out projectSettings)) { sourceToSettings[firstTest.Source] = projectSettings = LoadProjectSettings(firstTest.Source); } _currentTests = entry.Value; _frameworkHandle = frameworkHandle; // Run all test cases in a given file RunTestCases(entry.Value, runContext, frameworkHandle, projectSettings); } }
private void RunTestCases(IEnumerable <TestCase> tests, IRunContext runContext, IFrameworkHandle frameworkHandle, NodejsProjectSettings settings) { // May be null, but this is handled by RunTestCase if it matters. // No VS instance just means no debugging, but everything else is // okay. if (tests.Count() == 0) { return; } using (var app = VisualStudioApp.FromEnvironmentVariable(NodejsConstants.NodeToolsProcessIdEnvironmentVariable)) { var port = 0; var nodeArgs = new List <string>(); // .njsproj file path -> project settings var sourceToSettings = new Dictionary <string, NodejsProjectSettings>(); var testObjects = new List <TestCaseObject>(); if (!File.Exists(settings.NodeExePath)) { frameworkHandle.SendMessage(TestMessageLevel.Error, "Interpreter path does not exist: " + settings.NodeExePath); return; } // All tests being run are for the same test file, so just use the first test listed to get the working dir var testInfo = new NodejsTestInfo(tests.First().FullyQualifiedName); var workingDir = Path.GetDirectoryName(CommonUtils.GetAbsoluteFilePath(settings.WorkingDir, testInfo.ModulePath)); var nodeVersion = Nodejs.GetNodeVersion(settings.NodeExePath); // We can only log telemetry when we're running in VS. // Since the required assemblies are not on disk if we're not running in VS, we have to reference them in a separate method // this way the .NET framework only tries to load the assemblies when we actually need them. if (app != null) { LogTelemetry(tests.Count(), nodeVersion, runContext.IsBeingDebugged); } foreach (var test in tests) { if (_cancelRequested.WaitOne(0)) { break; } if (settings == null) { frameworkHandle.SendMessage( TestMessageLevel.Error, $"Unable to determine interpreter to use for {test.Source}."); frameworkHandle.RecordEnd(test, TestOutcome.Failed); } var args = new List <string>(); args.AddRange(GetInterpreterArgs(test, workingDir, settings.ProjectRootDir)); // Fetch the run_tests argument for starting node.exe if not specified yet if (nodeArgs.Count == 0 && args.Count > 0) { nodeArgs.Add(args[0]); } testObjects.Add(new TestCaseObject(args[1], args[2], args[3], args[4], args[5])); } if (runContext.IsBeingDebugged && app != null) { app.GetDTE().Debugger.DetachAll(); // Ensure that --debug-brk is the first argument nodeArgs.InsertRange(0, GetDebugArgs(out port)); } _nodeProcess = ProcessOutput.Run( settings.NodeExePath, nodeArgs, settings.WorkingDir, /* env */ null, /* visible */ false, /* redirector */ new TestExecutionRedirector(this.ProcessTestRunnerEmit), /* quote args */ false); if (runContext.IsBeingDebugged && app != null) { try { //the '#ping=0' is a special flag to tell VS node debugger not to connect to the port, //because a connection carries the consequence of setting off --debug-brk, and breakpoints will be missed. var qualifierUri = string.Format("tcp://localhost:{0}#ping=0", port); while (!app.AttachToProcess(_nodeProcess, NodejsRemoteDebugPortSupplierUnsecuredId, qualifierUri)) { if (_nodeProcess.Wait(TimeSpan.FromMilliseconds(500))) { break; } } #if DEBUG } catch (COMException ex) { frameworkHandle.SendMessage(TestMessageLevel.Error, "Error occurred connecting to debuggee."); frameworkHandle.SendMessage(TestMessageLevel.Error, ex.ToString()); KillNodeProcess(); } #else } catch (COMException) {
private static IEnumerable<string> GetDebugArgs(NodejsProjectSettings settings, out int port) { port = GetFreePort(); return new[] { "--debug-brk=" + port.ToString() }; }