diff --git a/.gitignore b/.gitignore index b631c59..f8f973b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ npm-debug.log yarn.* [Bb]in/ [Oo]bj/ -lcov.info \ No newline at end of file +lcov.info +.vscode-test +*.vsix \ No newline at end of file diff --git a/package.json b/package.json index 9a19e81..f7c03e9 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "MIT", "icon": "testexplorer_dark.png", "engines": { - "vscode": "^1.25.1" + "vscode": "^1.45.1" }, "categories": [ "Programming Languages" @@ -253,6 +253,16 @@ "default": "", "description": "Additional arguments that are added to the dotnet test command." }, + "dotnet-test-explorer.testhost.started.pattern": { + "type": "string", + "default": "Host debugging is enabled", + "description": "Pattern in stdout of testhost that triggers attachment of debugger" + }, + "dotnet-test-explorer.testhost.processId.pattern": { + "type": "string", + "default": "Process Id: (\\d+),", + "description": "Pattern in stdout of testhost that matches its process id" + }, "dotnet-test-explorer.leftClickAction": { "type": "string", "default": "gotoTest", @@ -267,6 +277,11 @@ "type": "boolean", "default": false, "description": "If true, will discover/build and run test in parallel if you have multiple test projects" + }, + "dotnet-test-explorer.clearTerminalBeforeTestRun": { + "type": "boolean", + "default": false, + "description": "If true, clears the output panel before running/debugging test" } } }, diff --git a/src/debug.ts b/src/debug.ts index 9033d2a..35f3da1 100644 --- a/src/debug.ts +++ b/src/debug.ts @@ -1,6 +1,4 @@ import * as vscode from "vscode"; -import { TestCommands } from "./testCommands"; -import { ITestResult, TestResult } from "./testResult"; import { Utility } from "./utility"; export interface IDebugRunnerInfo { @@ -12,7 +10,8 @@ export interface IDebugRunnerInfo { } export class Debug { - private processIdRegexp = /Process Id: (.*),/gm; + private processIdRegexp = new RegExp(Utility.testhostProcessIdPattern, 'mi'); + private debuggingEnabledRegexp = new RegExp(Utility.testhostStartedPattern, 'mi'); public onData(data: string, debugRunnerInfo?: IDebugRunnerInfo): IDebugRunnerInfo { @@ -20,8 +19,8 @@ export class Debug { debugRunnerInfo = {isRunning: false, isSettingUp: true, waitingForAttach: false, processId: ""}; } - if (!debugRunnerInfo.waitingForAttach) { - debugRunnerInfo.waitingForAttach = data.indexOf("Waiting for debugger attach...") > -1; + if (!debugRunnerInfo.waitingForAttach && this.debuggingEnabledRegexp.test(data)) { + debugRunnerInfo.waitingForAttach = true; } if (debugRunnerInfo.processId.length <= 0) { diff --git a/src/executor.ts b/src/executor.ts index 7b67d4e..5860438 100644 --- a/src/executor.ts +++ b/src/executor.ts @@ -4,6 +4,7 @@ import { platform } from "os"; import * as vscode from "vscode"; import { Debug, IDebugRunnerInfo } from "./debug"; import { Logger } from "./logger"; +import { Utility } from "./utility"; export class Executor { @@ -31,6 +32,9 @@ export class Executor { Logger.Log(`Process ${childProcess.pid} started`); this.processes.push(childProcess); + childProcess.stdout.on("data", (buf) => { + Logger.LogRaw(buf); + }); childProcess.on("close", (code: number) => { @@ -63,6 +67,7 @@ export class Executor { if (addToProcessList) { Logger.Log(`Process ${childProcess.pid} started`); + Logger.Log(`Waiting for debugger to attach`); this.processes.push(childProcess); @@ -72,19 +77,18 @@ export class Executor { return; } - Logger.Log(`Waiting for debugger to attach`); - const stdout = String(buf); + Logger.LogRaw(stdout); this.debugRunnerInfo = debug.onData(stdout, this.debugRunnerInfo); if (this.debugRunnerInfo.config) { - Logger.Log(`Debugger process found, attaching`); + Logger.Log(`Debugger process found (pid: ${this.debugRunnerInfo.processId}), attaching`); this.debugRunnerInfo.isRunning = true; - vscode.debug.startDebugging(vscode.workspace.workspaceFolders[0], this.debugRunnerInfo.config).then( (c) => { + vscode.debug.startDebugging(vscode.workspace.workspaceFolders[0], this.debugRunnerInfo.config).then((c) => { // When we attach to the debugger it seems to be stuck before loading the actual assembly that's running in code // This is to try to continue past this invisible break point and into the actual code the user wants to debug setTimeout(() => { diff --git a/src/logger.ts b/src/logger.ts index d0ba00b..409ea65 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -2,20 +2,28 @@ import * as vscode from "vscode"; export class Logger { - public static Log(message: string, output: string = this.defaultOutput): void { + public static LogRaw(message: string, output: string = this.defaultOutput): void { if (this.outputTerminals[output] === undefined ) { this.outputTerminals[output] = vscode.window.createOutputChannel(output); } - this.outputTerminals[output].appendLine(message); + this.outputTerminals[output].appendLine(message.trim()); + } + + public static Log(message: string): void { + Logger.LogRaw(`[INFO] ${message}`); } public static LogError(message: string, error: any): void { - Logger.Log(`[ERROR] ${message} - ${Logger.formatError(error)}`); + Logger.LogRaw(`[ERROR] ${message} - ${Logger.formatError(error)}`); } public static LogWarning(message: string): void { - Logger.Log(`[WARNING] ${message}`); + Logger.LogRaw(`[WARNING] ${message}`); + } + + public static Clear(output: string = this.defaultOutput): void { + this.outputTerminals[output].clear(); } public static Show(): void { diff --git a/src/testCommands.ts b/src/testCommands.ts index 042dc43..1e5ece2 100644 --- a/src/testCommands.ts +++ b/src/testCommands.ts @@ -262,6 +262,10 @@ export class TestCommands implements Disposable { this.runBuildCommandForSpecificDirectory(testDirectoryPath) .then(() => { + if (Utility.clearTerminalBeforeTestRun){ + Logger.Clear(); + Logger.Show(); + } Logger.Log(`Executing ${command} in ${testDirectoryPath}`); if (!debug) { @@ -272,8 +276,6 @@ export class TestCommands implements Disposable { reject(new Error("UserAborted")); } - Logger.Log(stdout, "Test Explorer (Test runner output)"); - resolve(); }, testDirectoryPath, true); } else { @@ -284,8 +286,6 @@ export class TestCommands implements Disposable { reject(new Error("UserAborted")); } - Logger.Log(stdout, "Test Explorer (Test runner output)"); - resolve(); }, testDirectoryPath, true); } diff --git a/src/utility.ts b/src/utility.ts index 36e9163..0b06abc 100644 --- a/src/utility.ts +++ b/src/utility.ts @@ -7,6 +7,7 @@ export class Utility { public static skipBuild: boolean; public static runInParallel: boolean; + public static clearTerminalBeforeTestRun: boolean; public static get codeLensEnabled(): boolean { return Utility.showCodeLens; @@ -38,6 +39,16 @@ export class Utility { return (testArguments && testArguments.length > 0) ? ` ${testArguments}` : ""; } + public static get testhostStartedPattern(): string { + const pattern = Utility.getConfiguration().get("testhost.started.pattern"); + return (pattern && pattern.length > 0) ? pattern : "Host debugging is enabled"; + } + + public static get testhostProcessIdPattern(): string { + const pattern = Utility.getConfiguration().get("testhost.processId.pattern"); + return (pattern && pattern.length > 0) ? pattern : "Process Id: (\d+),"; + } + public static getConfiguration(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration("dotnet-test-explorer"); } @@ -74,6 +85,7 @@ export class Utility { Utility.autoExpandTree = configuration.get("autoExpandTree", false); Utility.skipBuild = Utility.additionalArgumentsOption.indexOf("--no-build") > -1; Utility.runInParallel = configuration.get("runInParallel", false); + Utility.clearTerminalBeforeTestRun = configuration.get("clearTerminalBeforeTestRun", false); } /** diff --git a/test/debug.test.ts b/test/debug.test.ts index 7296075..437e9d9 100644 --- a/test/debug.test.ts +++ b/test/debug.test.ts @@ -10,13 +10,13 @@ suite("Debug tests", () => { assert.equal(results.isSettingUp, true); }); - test("Detects that debug is ready for attach har started", () => { + test("Detects that debug is ready for attach has started", () => { const debug = new Debug(); let results = debug.onData("data"); results = debug.onData(` This is output from vstest - Waiting for debugger attach... + Host debugging is enabled Tra la lalala la `, results); @@ -44,7 +44,7 @@ suite("Debug tests", () => { results = debug.onData(` This is output from vstest - Waiting for debugger attach... + Host debugging is enabled Tra la lalala la `, results);