From 05aaa2d3aa8ab36938719b69ce5237d25ff97b98 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Wed, 27 Dec 2017 17:30:57 -0800 Subject: [PATCH 01/20] Run All Tests Running But Building repeatedly --- src/features/codeLensProvider.ts | 44 ++++++++++++++++++++-- src/features/dotnetTest.ts | 64 +++++++++++++++++++++++++++++--- 2 files changed, 99 insertions(+), 9 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 2f58640e92..935a8e7777 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -31,8 +31,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen private _options: Options; - constructor(server: OmniSharpServer, reporter: TelemetryReporter, testManager: TestManager) - { + constructor(server: OmniSharpServer, reporter: TelemetryReporter, testManager: TestManager) { super(server, reporter); this._resetCachedOptions(); @@ -53,8 +52,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen }; provideCodeLenses(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.CodeLens[] | Thenable { - if (!this._options.showReferencesCodeLens && !this._options.showTestsCodeLens) - { + if (!this._options.showReferencesCodeLens && !this._options.showTestsCodeLens) { return []; } @@ -119,6 +117,10 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen return; } + if (node.Kind == "ClassDeclaration" && node.ChildNodes.length > 0) { + this._updateCodeLensForTestClass(bucket, fileName, node); + } + let testFeature = node.Features.find(value => (value.Name == 'XunitTestMethod' || value.Name == 'NUnitTestMethod' || value.Name == 'MSTestMethod')); if (testFeature) { // this test method has a test feature @@ -139,4 +141,38 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen { title: "debug test", command: 'dotnet.test.debug', arguments: [testFeature.Data, fileName, testFrameworkName] })); } } + + private _updateCodeLensForTestClass(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { + //if the class doesnot contain any method then return + if (!node.ChildNodes.find(value => (value.Kind == "MethodDeclaration"))) { + return; + } + + let argumentArray = new Array>(); + let newArguments; + for (let child of node.ChildNodes) { + if (child.Kind == "MethodDeclaration") { + let testFeature = child.Features.find(value => (value.Name == 'XunitTestMethod' || value.Name == 'NUnitTestMethod' || value.Name == 'MSTestMethod')); + if (testFeature) { + // this test method has a test feature + let testFrameworkName = 'xunit'; + if (testFeature.Name == 'NUnitTestMethod') { + testFrameworkName = 'nunit'; + } + else if (testFeature.Name == 'MSTestMethod') { + testFrameworkName = 'mstest'; + } + + newArguments = [testFeature.Data, fileName, testFrameworkName]; + argumentArray.push(newArguments); + } + } + } + //console.log(typeof (newArguments)); + if (argumentArray.length) { + bucket.push(new vscode.CodeLens( + toRange(node.Location), + { title: "run all test", command: 'dotnet.tests.run', arguments: argumentArray })); + } + } } diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 27a2c0bace..a63b43ea73 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -32,6 +32,10 @@ export default class TestManager extends AbstractProvider { 'dotnet.test.run', (testMethod, fileName, testFrameworkName) => this._runDotnetTest(testMethod, fileName, testFrameworkName)); + let d4 = vscode.commands.registerCommand( + 'dotnet.tests.run', + (...testsToRun) => this._runDotnetTestsInClass(testsToRun)); + let d2 = vscode.commands.registerCommand( 'dotnet.test.debug', (testMethod, fileName, testFrameworkName) => this._debugDotnetTest(testMethod, fileName, testFrameworkName)); @@ -48,7 +52,7 @@ export default class TestManager extends AbstractProvider { } }); - this.addDisposables(d1, d2, d3); + this.addDisposables(d1, d2, d3, d4); } private _getOutputChannel(): vscode.OutputChannel { @@ -150,7 +154,7 @@ export default class TestManager extends AbstractProvider { return Promise.resolve(); } - private _runDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { + private async _runDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { const output = this._getOutputChannel(); output.show(); @@ -161,11 +165,10 @@ export default class TestManager extends AbstractProvider { output.appendLine(e.Message); }); - this._saveDirtyFiles() + await this._saveDirtyFiles() .then(_ => this._recordRunRequest(testFrameworkName)) .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) - .then(projectInfo => - { + .then(projectInfo => { let targetFrameworkVersion: string; if (projectInfo.DotNetProject) { @@ -188,6 +191,57 @@ export default class TestManager extends AbstractProvider { }); } + private async _runDotnetTestsInClass(testsToRun) { + + let allResults : protocol.V2.DotNetTestResult[]; + for (let [testMethod, fileName, testFrameworkName] of testsToRun) { + const output = this._getOutputChannel(); + + output.show(); + output.appendLine(`Running test ${testMethod}...`); + output.appendLine(''); + + const listener = this._server.onTestMessage(e => { + output.appendLine(e.Message); + }); + + await this._saveDirtyFiles() + .then(_ => this._recordRunRequest(testFrameworkName)) + .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) + .then(projectInfo => { + let targetFrameworkVersion: string; + + if (projectInfo.DotNetProject) { + targetFrameworkVersion = undefined; + } + else if (projectInfo.MsBuildProject) { + targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; + } + else { + throw new Error('Expected project.json or .csproj project.'); + } + + return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion); + }) + .then(results => { + //pushing all the results to one result + if (!allResults) { + allResults = results; + } + else { + Array.prototype.push.apply(allResults, results); + } + } + ) + .then(() => listener.dispose()) + .catch(reason => { + listener.dispose(); + vscode.window.showErrorMessage(`Failed to run test because ${reason}.`); + }); + } + await this._reportResults(allResults); + } + private _createLaunchConfiguration(program: string, args: string, cwd: string, debuggerEventsPipeName: string) { let debugOptions = vscode.workspace.getConfiguration('csharp').get('unitTestDebuggingOptions'); From e93efc83b5883ffd49872364bc7c595fe447d132 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Wed, 27 Dec 2017 17:45:50 -0800 Subject: [PATCH 02/20] Disposable variable for run all test --- src/features/dotnetTest.ts | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index a63b43ea73..f62141419e 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -32,11 +32,15 @@ export default class TestManager extends AbstractProvider { 'dotnet.test.run', (testMethod, fileName, testFrameworkName) => this._runDotnetTest(testMethod, fileName, testFrameworkName)); + let d2 = vscode.commands.registerCommand( + 'dotnet.test.debug', + (testMethod, fileName, testFrameworkName) => this._debugDotnetTest(testMethod, fileName, testFrameworkName)); + let d4 = vscode.commands.registerCommand( 'dotnet.tests.run', (...testsToRun) => this._runDotnetTestsInClass(testsToRun)); - let d2 = vscode.commands.registerCommand( + let d5 = vscode.commands.registerCommand( 'dotnet.test.debug', (testMethod, fileName, testFrameworkName) => this._debugDotnetTest(testMethod, fileName, testFrameworkName)); @@ -165,7 +169,7 @@ export default class TestManager extends AbstractProvider { output.appendLine(e.Message); }); - await this._saveDirtyFiles() + this._saveDirtyFiles() .then(_ => this._recordRunRequest(testFrameworkName)) .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) .then(projectInfo => { @@ -193,24 +197,24 @@ export default class TestManager extends AbstractProvider { private async _runDotnetTestsInClass(testsToRun) { - let allResults : protocol.V2.DotNetTestResult[]; + let allResults: protocol.V2.DotNetTestResult[]; for (let [testMethod, fileName, testFrameworkName] of testsToRun) { const output = this._getOutputChannel(); output.show(); output.appendLine(`Running test ${testMethod}...`); output.appendLine(''); - + const listener = this._server.onTestMessage(e => { output.appendLine(e.Message); }); - + await this._saveDirtyFiles() .then(_ => this._recordRunRequest(testFrameworkName)) .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) .then(projectInfo => { let targetFrameworkVersion: string; - + if (projectInfo.DotNetProject) { targetFrameworkVersion = undefined; } @@ -220,19 +224,19 @@ export default class TestManager extends AbstractProvider { else { throw new Error('Expected project.json or .csproj project.'); } - + return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion); }) .then(results => { //pushing all the results to one result if (!allResults) { allResults = results; - } + } else { Array.prototype.push.apply(allResults, results); - } - } - ) + } + } + ) .then(() => listener.dispose()) .catch(reason => { listener.dispose(); From 93867798f7d9490c9f98bef0616622b2a8aa8f31 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Wed, 27 Dec 2017 18:16:34 -0800 Subject: [PATCH 03/20] Added code for debug all tests --- src/features/codeLensProvider.ts | 3 +++ src/features/dotnetTest.ts | 15 ++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 935a8e7777..07d673b19f 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -173,6 +173,9 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen bucket.push(new vscode.CodeLens( toRange(node.Location), { title: "run all test", command: 'dotnet.tests.run', arguments: argumentArray })); + bucket.push(new vscode.CodeLens( + toRange(node.Location), + { title: "debug all test", command: 'dotnet.tests.debug', arguments: argumentArray })); } } } diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index f62141419e..9df9d03458 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -41,8 +41,8 @@ export default class TestManager extends AbstractProvider { (...testsToRun) => this._runDotnetTestsInClass(testsToRun)); let d5 = vscode.commands.registerCommand( - 'dotnet.test.debug', - (testMethod, fileName, testFrameworkName) => this._debugDotnetTest(testMethod, fileName, testFrameworkName)); + 'dotnet.tests.debug', + (...testsToDebug) => this._debugDotnetTestsInClass(testsToDebug)); this._telemetryIntervalId = setInterval(() => this._reportTelemetry(), TelemetryReportingDelay); @@ -56,7 +56,7 @@ export default class TestManager extends AbstractProvider { } }); - this.addDisposables(d1, d2, d3, d4); + this.addDisposables(d1, d2, d3, d4, d5); } private _getOutputChannel(): vscode.OutputChannel { @@ -235,8 +235,7 @@ export default class TestManager extends AbstractProvider { else { Array.prototype.push.apply(allResults, results); } - } - ) + }) .then(() => listener.dispose()) .catch(reason => { listener.dispose(); @@ -373,6 +372,12 @@ export default class TestManager extends AbstractProvider { } }); } + + private async _debugDotnetTestsInClass(testsToDebug) { + for (let [testMethod, fileName, testFrameworkName] of testsToDebug) { + await this._debugDotnetTest(testMethod, fileName, testFrameworkName); + } + } } class DebugEventListener { From 70b126fc6c19d0368a42b7e6a468f32850bcaf49 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Thu, 4 Jan 2018 15:17:28 -0800 Subject: [PATCH 04/20] Code Cleaning --- src/features/dotnetTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 9df9d03458..5d30ba812d 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -158,7 +158,7 @@ export default class TestManager extends AbstractProvider { return Promise.resolve(); } - private async _runDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { + private _runDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { const output = this._getOutputChannel(); output.show(); From ee93887ccfa0261d61b26fad068f52c0bcc0a204 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Fri, 5 Jan 2018 18:39:13 -0800 Subject: [PATCH 05/20] Run all Tests running - Better logs required --- src/features/codeLensProvider.ts | 11 +++--- src/features/dotnetTest.ts | 67 ++++++++++++++++++++++++++------ src/omnisharp/protocol.ts | 7 ++++ src/omnisharp/utils.ts | 4 ++ 4 files changed, 72 insertions(+), 17 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 07d673b19f..53cf591624 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -148,8 +148,8 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen return; } - let argumentArray = new Array>(); - let newArguments; + let argumentArray = new Array(); + let frameworkname: string; for (let child of node.ChildNodes) { if (child.Kind == "MethodDeclaration") { let testFeature = child.Features.find(value => (value.Name == 'XunitTestMethod' || value.Name == 'NUnitTestMethod' || value.Name == 'MSTestMethod')); @@ -162,9 +162,8 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen else if (testFeature.Name == 'MSTestMethod') { testFrameworkName = 'mstest'; } - - newArguments = [testFeature.Data, fileName, testFrameworkName]; - argumentArray.push(newArguments); + frameworkname = testFrameworkName; + argumentArray.push(testFeature.Data); } } } @@ -172,7 +171,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen if (argumentArray.length) { bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "run all test", command: 'dotnet.tests.run', arguments: argumentArray })); + { title: "run all test", command: 'dotnet.tests.run', arguments: [fileName, frameworkname, argumentArray] })); bucket.push(new vscode.CodeLens( toRange(node.Location), { title: "debug all test", command: 'dotnet.tests.debug', arguments: argumentArray })); diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 5d30ba812d..606be8bc48 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -38,7 +38,7 @@ export default class TestManager extends AbstractProvider { let d4 = vscode.commands.registerCommand( 'dotnet.tests.run', - (...testsToRun) => this._runDotnetTestsInClass(testsToRun)); + (fileName, testFrameworkName,testsToRun) => this._runDotnetTestsInClass(fileName, testFrameworkName, testsToRun)); let d5 = vscode.commands.registerCommand( 'dotnet.tests.debug', @@ -125,7 +125,7 @@ export default class TestManager extends AbstractProvider { FileName: fileName, MethodName: testMethod, TestFrameworkName: testFrameworkName, - TargetFrameworkVersion: targetFrameworkVersion + TargetFrameworkVersion: targetFrameworkVersion, }; return serverUtils.runTest(this._server, request) @@ -195,19 +195,52 @@ export default class TestManager extends AbstractProvider { }); } - private async _runDotnetTestsInClass(testsToRun) { + private async _runDotnetTestsInClass(fileName: string, testFrameworkName: string, testsToRun) { - let allResults: protocol.V2.DotNetTestResult[]; - for (let [testMethod, fileName, testFrameworkName] of testsToRun) { - const output = this._getOutputChannel(); + let allResults: protocol.V2.DotNetTestResult[] = new Array(); + const output = this._getOutputChannel(); + output.show(); + const listener = this._server.onTestMessage(e => { + output.appendLine(e.Message); + }); + let methodsToRun: string[] = new Array(); + for (let testMethod of testsToRun) { + methodsToRun.push(testMethod); + } + await this._saveDirtyFiles() + .then(_ => this._recordRunRequest(testFrameworkName)) + .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) + .then(projectInfo => { + let targetFrameworkVersion: string; - output.show(); - output.appendLine(`Running test ${testMethod}...`); - output.appendLine(''); + if (projectInfo.DotNetProject) { + targetFrameworkVersion = undefined; + } + else if (projectInfo.MsBuildProject) { + targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; + } + else { + throw new Error('Expected project.json or .csproj project.'); + } - const listener = this._server.onTestMessage(e => { - output.appendLine(e.Message); + return this._runTestsInClass(fileName, testFrameworkName, targetFrameworkVersion, methodsToRun); + }).then(responses => { + responses.forEach(response => { + this._reportResults(response.Results); + Array.prototype.push.apply(allResults, response.Results); + }); + }).then(() => listener.dispose()) + .catch(reason => { + listener.dispose(); + vscode.window.showErrorMessage(`Failed to run test because ${reason}.`); }); + await this._reportResults(allResults); + } + + /* for (let [testMethod, fileName, testFrameworkName] of testsToRun) { + methodsToRun.push(testMethod); + output.appendLine(`Running test ${testMethod}...`); + output.appendLine(''); await this._saveDirtyFiles() .then(_ => this._recordRunRequest(testFrameworkName)) @@ -235,6 +268,7 @@ export default class TestManager extends AbstractProvider { else { Array.prototype.push.apply(allResults, results); } + this._reportResults(results); }) .then(() => listener.dispose()) .catch(reason => { @@ -243,6 +277,17 @@ export default class TestManager extends AbstractProvider { }); } await this._reportResults(allResults); + }*/ + + private _runTestsInClass(fileName: string, testFrameworkName: string, targetFrameworkVersion: string, methodsToRun: string[]): Promise { + const request: protocol.V2.RunTestsInClassRequest = { + FileName: fileName, + TestFrameworkName: testFrameworkName, + TargetFrameworkVersion: targetFrameworkVersion, + MethodNamesInClass: methodsToRun + }; + + return serverUtils.runTestsInClass(this._server, request); } private _createLaunchConfiguration(program: string, args: string, cwd: string, debuggerEventsPipeName: string) { diff --git a/src/omnisharp/protocol.ts b/src/omnisharp/protocol.ts index 0532112bc7..2aea709e13 100644 --- a/src/omnisharp/protocol.ts +++ b/src/omnisharp/protocol.ts @@ -437,6 +437,7 @@ export namespace V2 { export const RunCodeAction = '/v2/runcodeaction'; export const GetTestStartInfo = '/v2/getteststartinfo'; export const RunTest = '/v2/runtest'; + export const RunAllTestsInClass = "/v2/runtestsinclass"; export const DebugTestGetStartInfo = '/v2/debugtest/getstartinfo'; export const DebugTestLaunch = '/v2/debugtest/launch'; export const DebugTestStop = '/v2/debugtest/stop'; @@ -559,6 +560,12 @@ export namespace V2 { TargetFrameworkVersion: string; } + export interface RunTestsInClassRequest extends Request { + TestFrameworkName: string; + TargetFrameworkVersion: string; + MethodNamesInClass: string[]; + } + export module TestOutcomes { export const None = 'none'; export const Passed = 'passed'; diff --git a/src/omnisharp/utils.ts b/src/omnisharp/utils.ts index 6ae0391d0e..607000dbb2 100644 --- a/src/omnisharp/utils.ts +++ b/src/omnisharp/utils.ts @@ -93,6 +93,10 @@ export function runTest(server: OmniSharpServer, request: protocol.V2.RunTestReq return server.makeRequest(protocol.V2.Requests.RunTest, request); } +export function runTestsInClass(server: OmniSharpServer, request: protocol.V2.RunTestsInClassRequest) { + return server.makeRequest(protocol.V2.Requests.RunAllTestsInClass, request); +} + export function debugTestGetStartInfo(server: OmniSharpServer, request: protocol.V2.DebugTestGetStartInfoRequest) { return server.makeRequest(protocol.V2.Requests.DebugTestGetStartInfo, request); } From f7b5eb8db88a1b21c5313e809db098439802b35f Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Mon, 8 Jan 2018 11:21:39 -0800 Subject: [PATCH 06/20] Run Tests running, all output shown at the end of all the tests --- src/features/codeLensProvider.ts | 31 +++++++-------- src/features/dotnetTest.ts | 65 +++++--------------------------- 2 files changed, 25 insertions(+), 71 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 53cf591624..bd76e557ee 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -148,33 +148,34 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen return; } - let argumentArray = new Array(); - let frameworkname: string; + let testMethodsInClass = new Array(); + let testFrameworkName: string = null; for (let child of node.ChildNodes) { if (child.Kind == "MethodDeclaration") { let testFeature = child.Features.find(value => (value.Name == 'XunitTestMethod' || value.Name == 'NUnitTestMethod' || value.Name == 'MSTestMethod')); if (testFeature) { // this test method has a test feature - let testFrameworkName = 'xunit'; - if (testFeature.Name == 'NUnitTestMethod') { - testFrameworkName = 'nunit'; - } - else if (testFeature.Name == 'MSTestMethod') { - testFrameworkName = 'mstest'; - } - frameworkname = testFrameworkName; - argumentArray.push(testFeature.Data); + if (testFrameworkName == null) { + testFrameworkName = 'xunit'; + if (testFeature.Name == 'NUnitTestMethod') { + testFrameworkName = 'nunit'; + } + else if (testFeature.Name == 'MSTestMethod') { + testFrameworkName = 'mstest'; + } + } + testMethodsInClass.push(testFeature.Data); } } } - //console.log(typeof (newArguments)); - if (argumentArray.length) { + + if (testMethodsInClass.length) { bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "run all test", command: 'dotnet.tests.run', arguments: [fileName, frameworkname, argumentArray] })); + { title: "run all test", command: 'dotnet.classTests.run', arguments: [fileName, testFrameworkName, testMethodsInClass] })); bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "debug all test", command: 'dotnet.tests.debug', arguments: argumentArray })); + { title: "debug all test", command: 'dotnet.classTests.debug', arguments: [fileName, testFrameworkName, testMethodsInClass] })); } } } diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 606be8bc48..80c7b0b67b 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -37,12 +37,12 @@ export default class TestManager extends AbstractProvider { (testMethod, fileName, testFrameworkName) => this._debugDotnetTest(testMethod, fileName, testFrameworkName)); let d4 = vscode.commands.registerCommand( - 'dotnet.tests.run', - (fileName, testFrameworkName,testsToRun) => this._runDotnetTestsInClass(fileName, testFrameworkName, testsToRun)); + 'dotnet.classTests.run', + (fileName, testFrameworkName, methodsInClass) => this._runDotnetTestsInClass(fileName, testFrameworkName, methodsInClass)); let d5 = vscode.commands.registerCommand( - 'dotnet.tests.debug', - (...testsToDebug) => this._debugDotnetTestsInClass(testsToDebug)); + 'dotnet.classTests.debug', + (fileName, testFrameworkName, methodsInClass) => this._debugDotnetTestsInClass(fileName, testFrameworkName, methodsInClass)); this._telemetryIntervalId = setInterval(() => this._reportTelemetry(), TelemetryReportingDelay); @@ -195,18 +195,14 @@ export default class TestManager extends AbstractProvider { }); } - private async _runDotnetTestsInClass(fileName: string, testFrameworkName: string, testsToRun) { - + private async _runDotnetTestsInClass(fileName: string, testFrameworkName: string, methodsToRun: string[]) { let allResults: protocol.V2.DotNetTestResult[] = new Array(); const output = this._getOutputChannel(); output.show(); const listener = this._server.onTestMessage(e => { output.appendLine(e.Message); }); - let methodsToRun: string[] = new Array(); - for (let testMethod of testsToRun) { - methodsToRun.push(testMethod); - } + await this._saveDirtyFiles() .then(_ => this._recordRunRequest(testFrameworkName)) .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) @@ -226,58 +222,15 @@ export default class TestManager extends AbstractProvider { return this._runTestsInClass(fileName, testFrameworkName, targetFrameworkVersion, methodsToRun); }).then(responses => { responses.forEach(response => { - this._reportResults(response.Results); Array.prototype.push.apply(allResults, response.Results); }); }).then(() => listener.dispose()) .catch(reason => { listener.dispose(); - vscode.window.showErrorMessage(`Failed to run test because ${reason}.`); + vscode.window.showErrorMessage(`Could not run tests`); }); await this._reportResults(allResults); } - - /* for (let [testMethod, fileName, testFrameworkName] of testsToRun) { - methodsToRun.push(testMethod); - output.appendLine(`Running test ${testMethod}...`); - output.appendLine(''); - - await this._saveDirtyFiles() - .then(_ => this._recordRunRequest(testFrameworkName)) - .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) - .then(projectInfo => { - let targetFrameworkVersion: string; - - if (projectInfo.DotNetProject) { - targetFrameworkVersion = undefined; - } - else if (projectInfo.MsBuildProject) { - targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; - } - else { - throw new Error('Expected project.json or .csproj project.'); - } - - return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion); - }) - .then(results => { - //pushing all the results to one result - if (!allResults) { - allResults = results; - } - else { - Array.prototype.push.apply(allResults, results); - } - this._reportResults(results); - }) - .then(() => listener.dispose()) - .catch(reason => { - listener.dispose(); - vscode.window.showErrorMessage(`Failed to run test because ${reason}.`); - }); - } - await this._reportResults(allResults); - }*/ private _runTestsInClass(fileName: string, testFrameworkName: string, targetFrameworkVersion: string, methodsToRun: string[]): Promise { const request: protocol.V2.RunTestsInClassRequest = { @@ -418,8 +371,8 @@ export default class TestManager extends AbstractProvider { }); } - private async _debugDotnetTestsInClass(testsToDebug) { - for (let [testMethod, fileName, testFrameworkName] of testsToDebug) { + private async _debugDotnetTestsInClass(fileName: string, testFrameworkName: string, methodsToRun: string[]) { + for (let testMethod of methodsToRun) { await this._debugDotnetTest(testMethod, fileName, testFrameworkName); } } From 8645f424c1ec373910a07934e29b85b4cb044489 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Mon, 8 Jan 2018 11:54:37 -0800 Subject: [PATCH 07/20] Renamed variable to methodsInClass --- src/features/dotnetTest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 80c7b0b67b..5de49fc0b9 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -195,7 +195,7 @@ export default class TestManager extends AbstractProvider { }); } - private async _runDotnetTestsInClass(fileName: string, testFrameworkName: string, methodsToRun: string[]) { + private async _runDotnetTestsInClass(fileName: string, testFrameworkName: string, methodsInClass: string[]) { let allResults: protocol.V2.DotNetTestResult[] = new Array(); const output = this._getOutputChannel(); output.show(); @@ -219,7 +219,7 @@ export default class TestManager extends AbstractProvider { throw new Error('Expected project.json or .csproj project.'); } - return this._runTestsInClass(fileName, testFrameworkName, targetFrameworkVersion, methodsToRun); + return this._runTestsInClass(fileName, testFrameworkName, targetFrameworkVersion, methodsInClass); }).then(responses => { responses.forEach(response => { Array.prototype.push.apply(allResults, response.Results); From 45792a541e93f229e82135fc6b67c767b23240ba Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Mon, 8 Jan 2018 15:56:31 -0800 Subject: [PATCH 08/20] Changes for Debug All Tests --- src/features/dotnetTest.ts | 97 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 4 deletions(-) diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 5de49fc0b9..708fdd92d0 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -18,6 +18,7 @@ import AbstractProvider from './abstractProvider'; const TelemetryReportingDelay = 2 * 60 * 1000; // two minutes export default class TestManager extends AbstractProvider { + private _channel: vscode.OutputChannel; private _runCounts: { [testFrameworkName: string]: number }; @@ -326,7 +327,7 @@ export default class TestManager extends AbstractProvider { } } - private _debugDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { + private async _debugDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { // We support to styles of 'dotnet test' for debugging: The legacy 'project.json' testing, and the newer csproj support // using VS Test. These require a different level of communication. let debugType: string; @@ -339,7 +340,7 @@ export default class TestManager extends AbstractProvider { output.appendLine(`Debugging method '${testMethod}'...`); output.appendLine(''); - return this._saveDirtyFiles() + return await this._saveDirtyFiles() .then(_ => this._recordDebugRequest(testFrameworkName)) .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) .then(projectInfo => { @@ -372,10 +373,98 @@ export default class TestManager extends AbstractProvider { } private async _debugDotnetTestsInClass(fileName: string, testFrameworkName: string, methodsToRun: string[]) { - for (let testMethod of methodsToRun) { - await this._debugDotnetTest(testMethod, fileName, testFrameworkName); + let debugType: string; + let debugEventListener: DebugEventListener = null; + let targetFrameworkVersion: string; + + const output = this._getOutputChannel(); + + return await this._saveDirtyFiles() + .then(_ => this._recordDebugRequest(testFrameworkName)) + .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) + .then(projectInfo => { + if (projectInfo.DotNetProject) { + debugType = 'legacy'; + targetFrameworkVersion = ''; + return Promise.resolve(); + } + else if (projectInfo.MsBuildProject) { + debugType = 'vstest'; + targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; + debugEventListener = new DebugEventListener(fileName, this._server, output); + return debugEventListener.start(); + } + else { + throw new Error('Expected project.json or .csproj project.'); + } + }) + .then(() => this._getLaunchConfigurationForClass(debugType, fileName, methodsToRun, testFrameworkName, targetFrameworkVersion, debugEventListener)) + .then(config => { + const workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(fileName)); + return vscode.debug.startDebugging(workspaceFolder, config); + }) + .catch(reason => { + vscode.window.showErrorMessage(`Failed to start debugger: ${reason}`); + if (debugEventListener != null) { + debugEventListener.close(); + } + }); + } + + private _getLaunchConfigurationForClass(debugType: string, fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + switch (debugType) { + case 'legacy': + return this._getLaunchConfigurationForLegacyClass(fileName, methodsToRun, testFrameworkName, targetFrameworkVersion); + case 'vstest': + return this._getLaunchConfigurationForVSTestClass(fileName, methodsToRun, testFrameworkName, targetFrameworkVersion, debugEventListener); + + default: + throw new Error(`Unexpected debug type: ${debugType}`); } } + + private _getLaunchConfigurationForVSTestClass(fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + const output = this._getOutputChannel(); + + const listener = this._server.onTestMessage(e => { + output.appendLine(e.Message); + }); + + const request: protocol.V2.DebugTestGetStartInfoRequestInClass = { + FileName: fileName, + MethodsInClass: methodsToRun, + TestFrameworkName: testFrameworkName, + TargetFrameworkVersion: targetFrameworkVersion + }; + + return serverUtils.debugTestGetStartInfo(this._server, request) + .then(response => { + listener.dispose(); + return this._createLaunchConfiguration(response.FileName, response.Arguments, response.WorkingDirectory, debugEventListener.pipePath()); + }); + } + + private _getLaunchConfigurationForLegacyClass(fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string): Promise { + const output = this._getOutputChannel(); + + // Listen for test messages while getting start info. + const listener = this._server.onTestMessage(e => { + output.appendLine(e.Message); + }); + + const request: protocol.V2.GetTestStartInfoRequestInClass = { + FileName: fileName, + MethodsInClass: methodsToRun, + TestFrameworkName: testFrameworkName, + TargetFrameworkVersion: targetFrameworkVersion + }; + + return serverUtils.getTestStartInfo(this._server, request) + .then(response => { + listener.dispose(); + return this._createLaunchConfiguration(response.Executable, response.Argument, response.WorkingDirectory, null); + }); + } } class DebugEventListener { From c30ee754fd084023c38d5e5e7281598accf1ff1e Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Tue, 9 Jan 2018 14:30:01 -0800 Subject: [PATCH 09/20] Changes for debug tests request --- src/features/dotnetTest.ts | 16 +++++++++------- src/omnisharp/protocol.ts | 7 +++++++ src/omnisharp/utils.ts | 4 ++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 708fdd92d0..1c267ec7e7 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -430,17 +430,19 @@ export default class TestManager extends AbstractProvider { output.appendLine(e.Message); }); - const request: protocol.V2.DebugTestGetStartInfoRequestInClass = { + const request: protocol.V2.DebugTestClassGetStartInfoRequest = { FileName: fileName, MethodsInClass: methodsToRun, TestFrameworkName: testFrameworkName, TargetFrameworkVersion: targetFrameworkVersion }; - return serverUtils.debugTestGetStartInfo(this._server, request) - .then(response => { - listener.dispose(); - return this._createLaunchConfiguration(response.FileName, response.Arguments, response.WorkingDirectory, debugEventListener.pipePath()); + return serverUtils.debugTestClassGetStartInfo(this._server, request) + .then(responses => { + responses.forEach(response => { + listener.dispose(); + return this._createLaunchConfiguration(response.FileName, response.Arguments, response.WorkingDirectory, debugEventListener.pipePath()); + }); }); } @@ -452,9 +454,9 @@ export default class TestManager extends AbstractProvider { output.appendLine(e.Message); }); - const request: protocol.V2.GetTestStartInfoRequestInClass = { + const request: protocol.V2.GetTestStartInfoRequest = { FileName: fileName, - MethodsInClass: methodsToRun, + MethodName: methodsToRun[0], TestFrameworkName: testFrameworkName, TargetFrameworkVersion: targetFrameworkVersion }; diff --git a/src/omnisharp/protocol.ts b/src/omnisharp/protocol.ts index 2aea709e13..7b8d58141a 100644 --- a/src/omnisharp/protocol.ts +++ b/src/omnisharp/protocol.ts @@ -439,6 +439,7 @@ export namespace V2 { export const RunTest = '/v2/runtest'; export const RunAllTestsInClass = "/v2/runtestsinclass"; export const DebugTestGetStartInfo = '/v2/debugtest/getstartinfo'; + export const DebugTestsInClassGetStartInfo = '/v2/debugtestsinclass/getstartinfo'; export const DebugTestLaunch = '/v2/debugtest/launch'; export const DebugTestStop = '/v2/debugtest/stop'; } @@ -522,6 +523,12 @@ export namespace V2 { TargetFrameworkVersion: string; } + export interface DebugTestClassGetStartInfoRequest extends Request { + MethodsInClass: string[]; + TestFrameworkName: string; + TargetFrameworkVersion: string; + } + export interface DebugTestGetStartInfoResponse { FileName: string; Arguments: string; diff --git a/src/omnisharp/utils.ts b/src/omnisharp/utils.ts index 607000dbb2..7967f1ed05 100644 --- a/src/omnisharp/utils.ts +++ b/src/omnisharp/utils.ts @@ -101,6 +101,10 @@ export function debugTestGetStartInfo(server: OmniSharpServer, request: protocol return server.makeRequest(protocol.V2.Requests.DebugTestGetStartInfo, request); } +export function debugTestClassGetStartInfo(server: OmniSharpServer, request: protocol.V2.DebugTestClassGetStartInfoRequest) { + return server.makeRequest(protocol.V2.Requests.DebugTestsInClassGetStartInfo, request); +} + export function debugTestLaunch(server: OmniSharpServer, request: protocol.V2.DebugTestLaunchRequest) { return server.makeRequest(protocol.V2.Requests.DebugTestLaunch, request); } From 75c9d644c24c69a1ac9dbe28ef09d7480f09cf60 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Wed, 10 Jan 2018 14:17:19 -0800 Subject: [PATCH 10/20] Debug All Tests running --- src/features/dotnetTest.ts | 54 ++++++++++++++++++++------------------ src/omnisharp/utils.ts | 2 +- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 1c267ec7e7..2319fb9bf9 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -18,7 +18,7 @@ import AbstractProvider from './abstractProvider'; const TelemetryReportingDelay = 2 * 60 * 1000; // two minutes export default class TestManager extends AbstractProvider { - + private _channel: vscode.OutputChannel; private _runCounts: { [testFrameworkName: string]: number }; @@ -159,7 +159,28 @@ export default class TestManager extends AbstractProvider { return Promise.resolve(); } - private _runDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { + private async helper(fileName: string, testFrameworkName: string) { + + await this._saveDirtyFiles(); + this._recordRunRequest(testFrameworkName); + let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); + + let targetFrameworkVersion: string; + + if (projectInfo.DotNetProject) { + targetFrameworkVersion = undefined; + } + else if (projectInfo.MsBuildProject) { + targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; + } + else { + throw new Error('Expected project.json or .csproj project.'); + } + + return targetFrameworkVersion; + } + + private async _runDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { const output = this._getOutputChannel(); output.show(); @@ -170,24 +191,9 @@ export default class TestManager extends AbstractProvider { output.appendLine(e.Message); }); - this._saveDirtyFiles() - .then(_ => this._recordRunRequest(testFrameworkName)) - .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) - .then(projectInfo => { - let targetFrameworkVersion: string; - - if (projectInfo.DotNetProject) { - targetFrameworkVersion = undefined; - } - else if (projectInfo.MsBuildProject) { - targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; - } - else { - throw new Error('Expected project.json or .csproj project.'); - } - - return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion); - }) + let targetFrameworkVersion = await this.helper(fileName, testFrameworkName); + + return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion) .then(results => this._reportResults(results)) .then(() => listener.dispose()) .catch(reason => { @@ -438,11 +444,9 @@ export default class TestManager extends AbstractProvider { }; return serverUtils.debugTestClassGetStartInfo(this._server, request) - .then(responses => { - responses.forEach(response => { - listener.dispose(); - return this._createLaunchConfiguration(response.FileName, response.Arguments, response.WorkingDirectory, debugEventListener.pipePath()); - }); + .then(response => { + listener.dispose(); + return this._createLaunchConfiguration(response.FileName, response.Arguments, response.WorkingDirectory, debugEventListener.pipePath()); }); } diff --git a/src/omnisharp/utils.ts b/src/omnisharp/utils.ts index 7967f1ed05..a4c7649398 100644 --- a/src/omnisharp/utils.ts +++ b/src/omnisharp/utils.ts @@ -102,7 +102,7 @@ export function debugTestGetStartInfo(server: OmniSharpServer, request: protocol } export function debugTestClassGetStartInfo(server: OmniSharpServer, request: protocol.V2.DebugTestClassGetStartInfoRequest) { - return server.makeRequest(protocol.V2.Requests.DebugTestsInClassGetStartInfo, request); + return server.makeRequest(protocol.V2.Requests.DebugTestsInClassGetStartInfo, request); } export function debugTestLaunch(server: OmniSharpServer, request: protocol.V2.DebugTestLaunchRequest) { From 2f33327fed01bf7e12906509cb301fcc1d52446a Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Fri, 12 Jan 2018 16:38:52 -0800 Subject: [PATCH 11/20] Added common helpers for single test and all test functions --- src/features/codeLensProvider.ts | 4 +- src/features/dotnetTest.ts | 152 ++++++++++--------------------- 2 files changed, 52 insertions(+), 104 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index bd76e557ee..124a75ab8e 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -172,10 +172,10 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen if (testMethodsInClass.length) { bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "run all test", command: 'dotnet.classTests.run', arguments: [fileName, testFrameworkName, testMethodsInClass] })); + { title: "run all test", command: 'dotnet.classTests.run', arguments: [testMethodsInClass, fileName, testFrameworkName] })); bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "debug all test", command: 'dotnet.classTests.debug', arguments: [fileName, testFrameworkName, testMethodsInClass] })); + { title: "debug all test", command: 'dotnet.classTests.debug', arguments: [testMethodsInClass, fileName, testFrameworkName] })); } } } diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 2319fb9bf9..03c7ae0cc8 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -14,6 +14,7 @@ import * as os from 'os'; import * as path from 'path'; import TelemetryReporter from 'vscode-extension-telemetry'; import AbstractProvider from './abstractProvider'; +import { outputFileSync } from 'fs-extra'; const TelemetryReportingDelay = 2 * 60 * 1000; // two minutes @@ -39,11 +40,11 @@ export default class TestManager extends AbstractProvider { let d4 = vscode.commands.registerCommand( 'dotnet.classTests.run', - (fileName, testFrameworkName, methodsInClass) => this._runDotnetTestsInClass(fileName, testFrameworkName, methodsInClass)); + (methodsInClass, fileName, testFrameworkName) => this._runDotnetTestsInClass(methodsInClass, fileName, testFrameworkName,)); let d5 = vscode.commands.registerCommand( 'dotnet.classTests.debug', - (fileName, testFrameworkName, methodsInClass) => this._debugDotnetTestsInClass(fileName, testFrameworkName, methodsInClass)); + ( methodsInClass, fileName, testFrameworkName) => this._debugDotnetTestsInClass(methodsInClass, fileName, testFrameworkName)); this._telemetryIntervalId = setInterval(() => this._reportTelemetry(), TelemetryReportingDelay); @@ -159,7 +160,7 @@ export default class TestManager extends AbstractProvider { return Promise.resolve(); } - private async helper(fileName: string, testFrameworkName: string) { + private async _recordRunAndGetFrameworkVersion(fileName: string, testFrameworkName: string) { await this._saveDirtyFiles(); this._recordRunRequest(testFrameworkName); @@ -191,8 +192,8 @@ export default class TestManager extends AbstractProvider { output.appendLine(e.Message); }); - let targetFrameworkVersion = await this.helper(fileName, testFrameworkName); - + let targetFrameworkVersion = await this._recordRunAndGetFrameworkVersion(fileName, testFrameworkName); + return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion) .then(results => this._reportResults(results)) .then(() => listener.dispose()) @@ -202,41 +203,30 @@ export default class TestManager extends AbstractProvider { }); } - private async _runDotnetTestsInClass(fileName: string, testFrameworkName: string, methodsInClass: string[]) { + private async _runDotnetTestsInClass(methodsInClass: string[], fileName: string, testFrameworkName: string) { let allResults: protocol.V2.DotNetTestResult[] = new Array(); const output = this._getOutputChannel(); + output.show(); const listener = this._server.onTestMessage(e => { output.appendLine(e.Message); }); - await this._saveDirtyFiles() - .then(_ => this._recordRunRequest(testFrameworkName)) - .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) - .then(projectInfo => { - let targetFrameworkVersion: string; + let targetFrameworkVersion = await this._recordRunAndGetFrameworkVersion(fileName, testFrameworkName); - if (projectInfo.DotNetProject) { - targetFrameworkVersion = undefined; - } - else if (projectInfo.MsBuildProject) { - targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; - } - else { - throw new Error('Expected project.json or .csproj project.'); - } - - return this._runTestsInClass(fileName, testFrameworkName, targetFrameworkVersion, methodsInClass); - }).then(responses => { + return this._runTestsInClass(fileName, testFrameworkName, targetFrameworkVersion, methodsInClass) + .then(responses => { responses.forEach(response => { Array.prototype.push.apply(allResults, response.Results); }); - }).then(() => listener.dispose()) + }).then(async () => { + listener.dispose(); + await this._reportResults(allResults); + }) .catch(reason => { listener.dispose(); vscode.window.showErrorMessage(`Could not run tests`); }); - await this._reportResults(allResults); } private _runTestsInClass(fileName: string, testFrameworkName: string, targetFrameworkVersion: string, methodsToRun: string[]): Promise { @@ -333,39 +323,44 @@ export default class TestManager extends AbstractProvider { } } - private async _debugDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { - // We support to styles of 'dotnet test' for debugging: The legacy 'project.json' testing, and the newer csproj support - // using VS Test. These require a different level of communication. + private async _recordDebugAndGetDebugValues(fileName: string, testFrameworkName: string, output: vscode.OutputChannel) { + await this._saveDirtyFiles(); + this._recordDebugRequest(testFrameworkName); + let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); + let debugType: string; let debugEventListener: DebugEventListener = null; let targetFrameworkVersion: string; + if (projectInfo.DotNetProject) { + debugType = 'legacy'; + targetFrameworkVersion = ''; + } + else if (projectInfo.MsBuildProject) { + debugType = 'vstest'; + targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; + debugEventListener = new DebugEventListener(fileName, this._server, output); + debugEventListener.start(); + } + else { + throw new Error('Expected project.json or .csproj project.'); + } + + return { debugType, debugEventListener, targetFrameworkVersion }; + } + private async _debugDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { + // We support to styles of 'dotnet test' for debugging: The legacy 'project.json' testing, and the newer csproj support + // using VS Test. These require a different level of communication. + const output = this._getOutputChannel(); output.show(); output.appendLine(`Debugging method '${testMethod}'...`); output.appendLine(''); - return await this._saveDirtyFiles() - .then(_ => this._recordDebugRequest(testFrameworkName)) - .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) - .then(projectInfo => { - if (projectInfo.DotNetProject) { - debugType = 'legacy'; - targetFrameworkVersion = ''; - return Promise.resolve(); - } - else if (projectInfo.MsBuildProject) { - debugType = 'vstest'; - targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; - debugEventListener = new DebugEventListener(fileName, this._server, output); - return debugEventListener.start(); - } - else { - throw new Error('Expected project.json or .csproj project.'); - } - }) - .then(() => this._getLaunchConfiguration(debugType, fileName, testMethod, testFrameworkName, targetFrameworkVersion, debugEventListener)) + let { debugType, debugEventListener, targetFrameworkVersion } = await this._recordDebugAndGetDebugValues(fileName, testFrameworkName, output); + + return this._getLaunchConfiguration(debugType, fileName, testMethod, testFrameworkName, targetFrameworkVersion, debugEventListener) .then(config => { const workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(fileName)); return vscode.debug.startDebugging(workspaceFolder, config); @@ -378,33 +373,13 @@ export default class TestManager extends AbstractProvider { }); } - private async _debugDotnetTestsInClass(fileName: string, testFrameworkName: string, methodsToRun: string[]) { - let debugType: string; - let debugEventListener: DebugEventListener = null; - let targetFrameworkVersion: string; + private async _debugDotnetTestsInClass(methodsToRun: string[], fileName: string, testFrameworkName: string) { const output = this._getOutputChannel(); - return await this._saveDirtyFiles() - .then(_ => this._recordDebugRequest(testFrameworkName)) - .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) - .then(projectInfo => { - if (projectInfo.DotNetProject) { - debugType = 'legacy'; - targetFrameworkVersion = ''; - return Promise.resolve(); - } - else if (projectInfo.MsBuildProject) { - debugType = 'vstest'; - targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; - debugEventListener = new DebugEventListener(fileName, this._server, output); - return debugEventListener.start(); - } - else { - throw new Error('Expected project.json or .csproj project.'); - } - }) - .then(() => this._getLaunchConfigurationForClass(debugType, fileName, methodsToRun, testFrameworkName, targetFrameworkVersion, debugEventListener)) + let { debugType, debugEventListener, targetFrameworkVersion } = await this._recordDebugAndGetDebugValues(fileName, testFrameworkName, output); + + return await this._getLaunchConfigurationForClass(debugType, fileName, methodsToRun, testFrameworkName, targetFrameworkVersion, debugEventListener) .then(config => { const workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(fileName)); return vscode.debug.startDebugging(workspaceFolder, config); @@ -418,15 +393,10 @@ export default class TestManager extends AbstractProvider { } private _getLaunchConfigurationForClass(debugType: string, fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { - switch (debugType) { - case 'legacy': - return this._getLaunchConfigurationForLegacyClass(fileName, methodsToRun, testFrameworkName, targetFrameworkVersion); - case 'vstest': - return this._getLaunchConfigurationForVSTestClass(fileName, methodsToRun, testFrameworkName, targetFrameworkVersion, debugEventListener); - - default: - throw new Error(`Unexpected debug type: ${debugType}`); + if (debugType == 'vstest') { + return this._getLaunchConfigurationForVSTestClass(fileName, methodsToRun, testFrameworkName, targetFrameworkVersion, debugEventListener); } + throw new Error(`Unexpected debug type: ${debugType}`); } private _getLaunchConfigurationForVSTestClass(fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { @@ -449,28 +419,6 @@ export default class TestManager extends AbstractProvider { return this._createLaunchConfiguration(response.FileName, response.Arguments, response.WorkingDirectory, debugEventListener.pipePath()); }); } - - private _getLaunchConfigurationForLegacyClass(fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string): Promise { - const output = this._getOutputChannel(); - - // Listen for test messages while getting start info. - const listener = this._server.onTestMessage(e => { - output.appendLine(e.Message); - }); - - const request: protocol.V2.GetTestStartInfoRequest = { - FileName: fileName, - MethodName: methodsToRun[0], - TestFrameworkName: testFrameworkName, - TargetFrameworkVersion: targetFrameworkVersion - }; - - return serverUtils.getTestStartInfo(this._server, request) - .then(response => { - listener.dispose(); - return this._createLaunchConfiguration(response.Executable, response.Argument, response.WorkingDirectory, null); - }); - } } class DebugEventListener { From ba21a1d8810b92b12947c387ce9fd5c938217eea Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Fri, 12 Jan 2018 17:11:00 -0800 Subject: [PATCH 12/20] Improved logs for Run All Tests --- src/features/dotnetTest.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 03c7ae0cc8..cbd4f54848 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -40,11 +40,11 @@ export default class TestManager extends AbstractProvider { let d4 = vscode.commands.registerCommand( 'dotnet.classTests.run', - (methodsInClass, fileName, testFrameworkName) => this._runDotnetTestsInClass(methodsInClass, fileName, testFrameworkName,)); + (methodsInClass, fileName, testFrameworkName) => this._runDotnetTestsInClass(methodsInClass, fileName, testFrameworkName, )); let d5 = vscode.commands.registerCommand( 'dotnet.classTests.debug', - ( methodsInClass, fileName, testFrameworkName) => this._debugDotnetTestsInClass(methodsInClass, fileName, testFrameworkName)); + (methodsInClass, fileName, testFrameworkName) => this._debugDotnetTestsInClass(methodsInClass, fileName, testFrameworkName)); this._telemetryIntervalId = setInterval(() => this._reportTelemetry(), TelemetryReportingDelay); @@ -134,11 +134,15 @@ export default class TestManager extends AbstractProvider { .then(response => response.Results); } - private _reportResults(results: protocol.V2.DotNetTestResult[]): Promise { + private _reportResults(results: protocol.V2.DotNetTestResult[], printEachResult: boolean): Promise { const totalTests = results.length; + const output = this._getOutputChannel(); let totalPassed = 0, totalFailed = 0, totalSkipped = 0; for (let result of results) { + if (printEachResult) { + output.appendLine(`${result.MethodName}: ${result.Outcome}`); + } switch (result.Outcome) { case protocol.V2.TestOutcomes.Failed: totalFailed += 1; @@ -152,7 +156,6 @@ export default class TestManager extends AbstractProvider { } } - const output = this._getOutputChannel(); output.appendLine(''); output.appendLine(`Total tests: ${totalTests}. Passed: ${totalPassed}. Failed: ${totalFailed}. Skipped: ${totalSkipped}`); output.appendLine(''); @@ -195,7 +198,7 @@ export default class TestManager extends AbstractProvider { let targetFrameworkVersion = await this._recordRunAndGetFrameworkVersion(fileName, testFrameworkName); return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion) - .then(results => this._reportResults(results)) + .then(results => this._reportResults(results, false)) .then(() => listener.dispose()) .catch(reason => { listener.dispose(); @@ -221,7 +224,7 @@ export default class TestManager extends AbstractProvider { }); }).then(async () => { listener.dispose(); - await this._reportResults(allResults); + await this._reportResults(allResults, true); }) .catch(reason => { listener.dispose(); @@ -348,6 +351,7 @@ export default class TestManager extends AbstractProvider { return { debugType, debugEventListener, targetFrameworkVersion }; } + private async _debugDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { // We support to styles of 'dotnet test' for debugging: The legacy 'project.json' testing, and the newer csproj support // using VS Test. These require a different level of communication. From 5a796b71bdaf0d592646918abb095110f077dd2b Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Fri, 19 Jan 2018 17:08:35 -0800 Subject: [PATCH 13/20] Changes to get only 1 response for a set of methods --- src/features/dotnetTest.ts | 34 ++++++++++++++-------------------- src/omnisharp/protocol.ts | 2 +- src/omnisharp/utils.ts | 2 +- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index cbd4f54848..7cb46365e9 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -134,15 +134,14 @@ export default class TestManager extends AbstractProvider { .then(response => response.Results); } - private _reportResults(results: protocol.V2.DotNetTestResult[], printEachResult: boolean): Promise { + private _reportResults(results: protocol.V2.DotNetTestResult[]): Promise { const totalTests = results.length; const output = this._getOutputChannel(); let totalPassed = 0, totalFailed = 0, totalSkipped = 0; for (let result of results) { - if (printEachResult) { - output.appendLine(`${result.MethodName}: ${result.Outcome}`); - } + output.appendLine(`${result.MethodName}: ${result.Outcome}`); + switch (result.Outcome) { case protocol.V2.TestOutcomes.Failed: totalFailed += 1; @@ -198,7 +197,7 @@ export default class TestManager extends AbstractProvider { let targetFrameworkVersion = await this._recordRunAndGetFrameworkVersion(fileName, testFrameworkName); return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion) - .then(results => this._reportResults(results, false)) + .then(results => this._reportResults(results)) .then(() => listener.dispose()) .catch(reason => { listener.dispose(); @@ -218,29 +217,24 @@ export default class TestManager extends AbstractProvider { let targetFrameworkVersion = await this._recordRunAndGetFrameworkVersion(fileName, testFrameworkName); return this._runTestsInClass(fileName, testFrameworkName, targetFrameworkVersion, methodsInClass) - .then(responses => { - responses.forEach(response => { - Array.prototype.push.apply(allResults, response.Results); - }); - }).then(async () => { - listener.dispose(); - await this._reportResults(allResults, true); - }) - .catch(reason => { - listener.dispose(); - vscode.window.showErrorMessage(`Could not run tests`); - }); + .then(results => this._reportResults(results)) + .then(() => listener.dispose()) + .catch(reason => { + listener.dispose(); + vscode.window.showErrorMessage(`Failed to run tests because ${reason}.`); + }); } - private _runTestsInClass(fileName: string, testFrameworkName: string, targetFrameworkVersion: string, methodsToRun: string[]): Promise { + private _runTestsInClass(fileName: string, testFrameworkName: string, targetFrameworkVersion: string, methodsToRun: string[]): Promise { const request: protocol.V2.RunTestsInClassRequest = { FileName: fileName, TestFrameworkName: testFrameworkName, TargetFrameworkVersion: targetFrameworkVersion, - MethodNamesInClass: methodsToRun + MethodNames: methodsToRun }; - return serverUtils.runTestsInClass(this._server, request); + return serverUtils.runTestsInClass(this._server, request) + .then(response => response.Results); } private _createLaunchConfiguration(program: string, args: string, cwd: string, debuggerEventsPipeName: string) { diff --git a/src/omnisharp/protocol.ts b/src/omnisharp/protocol.ts index 4bca0319c1..563c786949 100644 --- a/src/omnisharp/protocol.ts +++ b/src/omnisharp/protocol.ts @@ -584,9 +584,9 @@ export namespace V2 { } export interface RunTestsInClassRequest extends Request { + MethodNames: string[]; TestFrameworkName: string; TargetFrameworkVersion: string; - MethodNamesInClass: string[]; } export module TestOutcomes { diff --git a/src/omnisharp/utils.ts b/src/omnisharp/utils.ts index a4c7649398..27e329e914 100644 --- a/src/omnisharp/utils.ts +++ b/src/omnisharp/utils.ts @@ -94,7 +94,7 @@ export function runTest(server: OmniSharpServer, request: protocol.V2.RunTestReq } export function runTestsInClass(server: OmniSharpServer, request: protocol.V2.RunTestsInClassRequest) { - return server.makeRequest(protocol.V2.Requests.RunAllTestsInClass, request); + return server.makeRequest(protocol.V2.Requests.RunAllTestsInClass, request); } export function debugTestGetStartInfo(server: OmniSharpServer, request: protocol.V2.DebugTestGetStartInfoRequest) { From 2eab3f2ba1fb0c32911140e7d97b425775252da4 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Fri, 19 Jan 2018 18:08:45 -0800 Subject: [PATCH 14/20] Extracted a common helper to get the test feature --- src/features/codeLensProvider.ts | 64 +++++++++++++++++--------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 124a75ab8e..3c9352cc36 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -118,20 +118,13 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } if (node.Kind == "ClassDeclaration" && node.ChildNodes.length > 0) { - this._updateCodeLensForTestClass(bucket, fileName, node); + return this._updateCodeLensForTestClass(bucket, fileName, node); } - let testFeature = node.Features.find(value => (value.Name == 'XunitTestMethod' || value.Name == 'NUnitTestMethod' || value.Name == 'MSTestMethod')); + let featureAndFramework = this._getTestFeatureAndFramework(node); + let testFeature = featureAndFramework.Feature; + let testFrameworkName = featureAndFramework.Framework; if (testFeature) { - // this test method has a test feature - let testFrameworkName = 'xunit'; - if (testFeature.Name == 'NUnitTestMethod') { - testFrameworkName = 'nunit'; - } - else if (testFeature.Name == 'MSTestMethod') { - testFrameworkName = 'mstest'; - } - bucket.push(new vscode.CodeLens( toRange(node.Location), { title: "run test", command: 'dotnet.test.run', arguments: [testFeature.Data, fileName, testFrameworkName] })); @@ -143,39 +136,50 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } private _updateCodeLensForTestClass(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { - //if the class doesnot contain any method then return + // if the class doesnot contain any method then return if (!node.ChildNodes.find(value => (value.Kind == "MethodDeclaration"))) { return; } - let testMethodsInClass = new Array(); + let testMethods = new Array(); let testFrameworkName: string = null; for (let child of node.ChildNodes) { - if (child.Kind == "MethodDeclaration") { - let testFeature = child.Features.find(value => (value.Name == 'XunitTestMethod' || value.Name == 'NUnitTestMethod' || value.Name == 'MSTestMethod')); - if (testFeature) { - // this test method has a test feature - if (testFrameworkName == null) { - testFrameworkName = 'xunit'; - if (testFeature.Name == 'NUnitTestMethod') { - testFrameworkName = 'nunit'; - } - else if (testFeature.Name == 'MSTestMethod') { - testFrameworkName = 'mstest'; - } - } - testMethodsInClass.push(testFeature.Data); + let featureAndFramework = this._getTestFeatureAndFramework(child); + let testFeature = featureAndFramework.Feature; + if (testFeature) { + // this test method has a test feature + if (!testFrameworkName) { + testFrameworkName = featureAndFramework.Framework; } + + testMethods.push(testFeature.Data); } } - if (testMethodsInClass.length) { + if (testMethods.length) { bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "run all test", command: 'dotnet.classTests.run', arguments: [testMethodsInClass, fileName, testFrameworkName] })); + { title: "run all tests", command: 'dotnet.classTests.run', arguments: [testMethods, fileName, testFrameworkName] })); bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "debug all test", command: 'dotnet.classTests.debug', arguments: [testMethodsInClass, fileName, testFrameworkName] })); + { title: "debug all tests", command: 'dotnet.classTests.debug', arguments: [testMethods, fileName, testFrameworkName] })); + } + } + + private _getTestFeatureAndFramework(node: protocol.Node) { + let testFeature = node.Features.find(value => (value.Name == 'XunitTestMethod' || value.Name == 'NUnitTestMethod' || value.Name == 'MSTestMethod')); + if (testFeature) { + let testFrameworkName = 'xunit'; + if (testFeature.Name == 'NUnitTestMethod') { + testFrameworkName = 'nunit'; + } + else if (testFeature.Name == 'MSTestMethod') { + testFrameworkName = 'mstest'; + } + + return { Feature: testFeature, Framework: testFrameworkName }; } + + return { Feature: null, Framework: null }; } } From c1eed7879deb3e526aa8b4d489e563d2a4bb6573 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Mon, 22 Jan 2018 16:32:02 -0800 Subject: [PATCH 15/20] Resolved review comments --- src/features/codeLensProvider.ts | 17 +++++++---------- src/features/dotnetTest.ts | 15 +++++++-------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 3c9352cc36..a01047b102 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -121,9 +121,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen return this._updateCodeLensForTestClass(bucket, fileName, node); } - let featureAndFramework = this._getTestFeatureAndFramework(node); - let testFeature = featureAndFramework.Feature; - let testFrameworkName = featureAndFramework.Framework; + let [testFeature, testFrameworkName] = this._getTestFeatureAndFramework(node); if (testFeature) { bucket.push(new vscode.CodeLens( toRange(node.Location), @@ -144,19 +142,18 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen let testMethods = new Array(); let testFrameworkName: string = null; for (let child of node.ChildNodes) { - let featureAndFramework = this._getTestFeatureAndFramework(child); - let testFeature = featureAndFramework.Feature; + let [testFeature, frameworkName] = this._getTestFeatureAndFramework(node); if (testFeature) { // this test method has a test feature if (!testFrameworkName) { - testFrameworkName = featureAndFramework.Framework; + testFrameworkName = frameworkName; } testMethods.push(testFeature.Data); } } - if (testMethods.length) { + if (testMethods.length > 0) { bucket.push(new vscode.CodeLens( toRange(node.Location), { title: "run all tests", command: 'dotnet.classTests.run', arguments: [testMethods, fileName, testFrameworkName] })); @@ -166,7 +163,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } } - private _getTestFeatureAndFramework(node: protocol.Node) { + private _getTestFeatureAndFramework(node: protocol.Node): [protocol.SyntaxFeature, string] { let testFeature = node.Features.find(value => (value.Name == 'XunitTestMethod' || value.Name == 'NUnitTestMethod' || value.Name == 'MSTestMethod')); if (testFeature) { let testFrameworkName = 'xunit'; @@ -177,9 +174,9 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen testFrameworkName = 'mstest'; } - return { Feature: testFeature, Framework: testFrameworkName }; + return [ testFeature, testFrameworkName ]; } - return { Feature: null, Framework: null }; + return [null, null]; } } diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 7cb46365e9..5fdefc8f05 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -206,7 +206,6 @@ export default class TestManager extends AbstractProvider { } private async _runDotnetTestsInClass(methodsInClass: string[], fileName: string, testFrameworkName: string) { - let allResults: protocol.V2.DotNetTestResult[] = new Array(); const output = this._getOutputChannel(); output.show(); @@ -217,12 +216,12 @@ export default class TestManager extends AbstractProvider { let targetFrameworkVersion = await this._recordRunAndGetFrameworkVersion(fileName, testFrameworkName); return this._runTestsInClass(fileName, testFrameworkName, targetFrameworkVersion, methodsInClass) - .then(results => this._reportResults(results)) - .then(() => listener.dispose()) - .catch(reason => { - listener.dispose(); - vscode.window.showErrorMessage(`Failed to run tests because ${reason}.`); - }); + .then(results => this._reportResults(results)) + .then(() => listener.dispose()) + .catch(reason => { + listener.dispose(); + vscode.window.showErrorMessage(`Failed to run tests because ${reason}.`); + }); } private _runTestsInClass(fileName: string, testFrameworkName: string, targetFrameworkVersion: string, methodsToRun: string[]): Promise { @@ -234,7 +233,7 @@ export default class TestManager extends AbstractProvider { }; return serverUtils.runTestsInClass(this._server, request) - .then(response => response.Results); + .then(response => response.Results); } private _createLaunchConfiguration(program: string, args: string, cwd: string, debuggerEventsPipeName: string) { From d8ddfb62b9829ecbc033abfa89a4253b4ca47f2a Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Mon, 22 Jan 2018 17:24:39 -0800 Subject: [PATCH 16/20] Changes to not show this change for legacy projects --- src/features/codeLensProvider.ts | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index a01047b102..76dba84ea3 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -51,19 +51,19 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen 'ToString': true }; - provideCodeLenses(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.CodeLens[] | Thenable { + async provideCodeLenses(document: vscode.TextDocument, token: vscode.CancellationToken) { if (!this._options.showReferencesCodeLens && !this._options.showTestsCodeLens) { return []; } - return serverUtils.currentFileMembersAsTree(this._server, { FileName: document.fileName }, token).then(tree => { - let ret: vscode.CodeLens[] = []; - tree.TopLevelTypeDefinitions.forEach(node => this._convertQuickFix(ret, document.fileName, node)); - return ret; - }); + let tree = await serverUtils.currentFileMembersAsTree(this._server, { FileName: document.fileName }, token); + let ret: vscode.CodeLens[] = []; + tree.TopLevelTypeDefinitions.forEach(node => this._convertQuickFix(ret, document.fileName, node)); + return ret; } - private _convertQuickFix(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node): void { + + private async _convertQuickFix(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { if (node.Kind === 'MethodDeclaration' && OmniSharpCodeLensProvider.filteredSymbolNames[node.Location.Text]) { return; @@ -79,7 +79,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } if (this._options.showTestsCodeLens) { - this._updateCodeLensForTest(bucket, fileName, node); + await this._updateCodeLensForTest(bucket, fileName, node); } } @@ -111,14 +111,17 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } } - private _updateCodeLensForTest(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { + private async _updateCodeLensForTest(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node){ // backward compatible check: Features property doesn't present on older version OmniSharp if (node.Features === undefined) { return; } if (node.Kind == "ClassDeclaration" && node.ChildNodes.length > 0) { - return this._updateCodeLensForTestClass(bucket, fileName, node); + let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); + if (projectInfo.MsBuildProject) { + await this._updateCodeLensForTestClass(bucket, fileName, node); + } } let [testFeature, testFrameworkName] = this._getTestFeatureAndFramework(node); @@ -133,7 +136,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } } - private _updateCodeLensForTestClass(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { + private _updateCodeLensForTestClass(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node){ // if the class doesnot contain any method then return if (!node.ChildNodes.find(value => (value.Kind == "MethodDeclaration"))) { return; @@ -142,7 +145,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen let testMethods = new Array(); let testFrameworkName: string = null; for (let child of node.ChildNodes) { - let [testFeature, frameworkName] = this._getTestFeatureAndFramework(node); + let [testFeature, frameworkName] = this._getTestFeatureAndFramework(child); if (testFeature) { // this test method has a test feature if (!testFrameworkName) { @@ -174,7 +177,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen testFrameworkName = 'mstest'; } - return [ testFeature, testFrameworkName ]; + return [testFeature, testFrameworkName]; } return [null, null]; From 1ec2448dff7fa40bb3fd7bf9f0390a0309f444f0 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Tue, 23 Jan 2018 12:06:23 -0800 Subject: [PATCH 17/20] Renamed incorrect variable --- src/features/codeLensProvider.ts | 16 ++++++++-------- src/features/dotnetTest.ts | 6 +++--- src/omnisharp/protocol.ts | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 76dba84ea3..019deca9a0 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -63,7 +63,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } - private async _convertQuickFix(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { + private _convertQuickFix(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { if (node.Kind === 'MethodDeclaration' && OmniSharpCodeLensProvider.filteredSymbolNames[node.Location.Text]) { return; @@ -75,11 +75,11 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } for (let child of node.ChildNodes) { - this._convertQuickFix(bucket, fileName, child); + this._convertQuickFix(bucket, fileName, child); } if (this._options.showTestsCodeLens) { - await this._updateCodeLensForTest(bucket, fileName, node); + this._updateCodeLensForTest(bucket, fileName, node); } } @@ -111,16 +111,16 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } } - private async _updateCodeLensForTest(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node){ + private async _updateCodeLensForTest(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node){ // backward compatible check: Features property doesn't present on older version OmniSharp if (node.Features === undefined) { return; } - if (node.Kind == "ClassDeclaration" && node.ChildNodes.length > 0) { - let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); + if (node.Kind === "ClassDeclaration" && node.ChildNodes.length > 0) { + let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); if (projectInfo.MsBuildProject) { - await this._updateCodeLensForTestClass(bucket, fileName, node); + this._updateCodeLensForTestClass(bucket, fileName, node); } } @@ -138,7 +138,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen private _updateCodeLensForTestClass(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node){ // if the class doesnot contain any method then return - if (!node.ChildNodes.find(value => (value.Kind == "MethodDeclaration"))) { + if (!node.ChildNodes.find(value => (value.Kind === "MethodDeclaration"))) { return; } diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 5fdefc8f05..43daf15305 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -40,7 +40,7 @@ export default class TestManager extends AbstractProvider { let d4 = vscode.commands.registerCommand( 'dotnet.classTests.run', - (methodsInClass, fileName, testFrameworkName) => this._runDotnetTestsInClass(methodsInClass, fileName, testFrameworkName, )); + (methodsInClass, fileName, testFrameworkName) => this._runDotnetTestsInClass(methodsInClass, fileName, testFrameworkName)); let d5 = vscode.commands.registerCommand( 'dotnet.classTests.debug', @@ -127,7 +127,7 @@ export default class TestManager extends AbstractProvider { FileName: fileName, MethodName: testMethod, TestFrameworkName: testFrameworkName, - TargetFrameworkVersion: targetFrameworkVersion, + TargetFrameworkVersion: targetFrameworkVersion }; return serverUtils.runTest(this._server, request) @@ -405,7 +405,7 @@ export default class TestManager extends AbstractProvider { const request: protocol.V2.DebugTestClassGetStartInfoRequest = { FileName: fileName, - MethodsInClass: methodsToRun, + MethodNames: methodsToRun, TestFrameworkName: testFrameworkName, TargetFrameworkVersion: targetFrameworkVersion }; diff --git a/src/omnisharp/protocol.ts b/src/omnisharp/protocol.ts index 563c786949..d74875cfdb 100644 --- a/src/omnisharp/protocol.ts +++ b/src/omnisharp/protocol.ts @@ -540,7 +540,7 @@ export namespace V2 { } export interface DebugTestClassGetStartInfoRequest extends Request { - MethodsInClass: string[]; + MethodNames: string[]; TestFrameworkName: string; TargetFrameworkVersion: string; } From 128641da18d9d02767efa9f37353f49c4d72009c Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Tue, 23 Jan 2018 13:55:57 -0800 Subject: [PATCH 18/20] Removing foreach for proper order of execution --- src/features/codeLensProvider.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 019deca9a0..5c8068c73a 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -58,12 +58,16 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen let tree = await serverUtils.currentFileMembersAsTree(this._server, { FileName: document.fileName }, token); let ret: vscode.CodeLens[] = []; - tree.TopLevelTypeDefinitions.forEach(node => this._convertQuickFix(ret, document.fileName, node)); + + for (let node of tree.TopLevelTypeDefinitions) { + await this._convertQuickFix(ret, document.fileName, node); + } + return ret; } - private _convertQuickFix(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { + private async _convertQuickFix(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node): Promise { if (node.Kind === 'MethodDeclaration' && OmniSharpCodeLensProvider.filteredSymbolNames[node.Location.Text]) { return; @@ -75,11 +79,11 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } for (let child of node.ChildNodes) { - this._convertQuickFix(bucket, fileName, child); + this._convertQuickFix(bucket, fileName, child); } if (this._options.showTestsCodeLens) { - this._updateCodeLensForTest(bucket, fileName, node); + await this._updateCodeLensForTest(bucket, fileName, node); } } @@ -111,16 +115,16 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } } - private async _updateCodeLensForTest(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node){ + private async _updateCodeLensForTest(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node): Promise { // backward compatible check: Features property doesn't present on older version OmniSharp if (node.Features === undefined) { return; } if (node.Kind === "ClassDeclaration" && node.ChildNodes.length > 0) { - let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); + let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); if (projectInfo.MsBuildProject) { - this._updateCodeLensForTestClass(bucket, fileName, node); + this._updateCodeLensForTestClass(bucket, fileName, node); } } @@ -136,7 +140,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } } - private _updateCodeLensForTestClass(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node){ + private _updateCodeLensForTestClass(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { // if the class doesnot contain any method then return if (!node.ChildNodes.find(value => (value.Kind === "MethodDeclaration"))) { return; From f3d873e40c2e5b6c0ac812272734ec506ac85299 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Tue, 23 Jan 2018 14:21:52 -0800 Subject: [PATCH 19/20] Remove unnecessary import --- src/features/dotnetTest.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 43daf15305..7b0a53274a 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -14,12 +14,10 @@ import * as os from 'os'; import * as path from 'path'; import TelemetryReporter from 'vscode-extension-telemetry'; import AbstractProvider from './abstractProvider'; -import { outputFileSync } from 'fs-extra'; const TelemetryReportingDelay = 2 * 60 * 1000; // two minutes export default class TestManager extends AbstractProvider { - private _channel: vscode.OutputChannel; private _runCounts: { [testFrameworkName: string]: number }; @@ -141,7 +139,6 @@ export default class TestManager extends AbstractProvider { let totalPassed = 0, totalFailed = 0, totalSkipped = 0; for (let result of results) { output.appendLine(`${result.MethodName}: ${result.Outcome}`); - switch (result.Outcome) { case protocol.V2.TestOutcomes.Failed: totalFailed += 1; From 7ca15403f33eb1c56d10415e307f2de58c8434f1 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Wed, 24 Jan 2018 08:41:18 -0800 Subject: [PATCH 20/20] Do not show the festure for legacy projects --- src/features/codeLensProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 5c8068c73a..b20d4e8778 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -123,7 +123,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen if (node.Kind === "ClassDeclaration" && node.ChildNodes.length > 0) { let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); - if (projectInfo.MsBuildProject) { + if (!projectInfo.DotNetProject && projectInfo.MsBuildProject) { this._updateCodeLensForTestClass(bucket, fileName, node); } }