Skip to content

Commit 6db942e

Browse files
committed
fix #678
1 parent 0f1ad82 commit 6db942e

4 files changed

Lines changed: 60 additions & 15 deletions

File tree

src/client/unittests/codeLenses/main.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import * as vscode from 'vscode';
22
import * as constants from '../../common/constants';
33

4-
import {TestFileCodeLensProvider} from './testFiles';
4+
import { TestFileCodeLensProvider } from './testFiles';
55

6-
export function activateCodeLenses(): vscode.Disposable {
6+
export function activateCodeLenses(onDidChange: vscode.EventEmitter<void>): vscode.Disposable {
77
const disposables: vscode.Disposable[] = [];
8-
disposables.push(vscode.languages.registerCodeLensProvider(constants.PythonLanguage, new TestFileCodeLensProvider()));
8+
disposables.push(vscode.languages.registerCodeLensProvider(constants.PythonLanguage, new TestFileCodeLensProvider(onDidChange)));
99

1010
return {
1111
dispose: function () {

src/client/unittests/codeLenses/testFiles.ts

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import * as vscode from 'vscode';
44
import { CodeLensProvider, TextDocument, CancellationToken, CodeLens, SymbolInformation } from 'vscode';
5-
import { TestFile, TestsToRun, TestSuite, TestFunction } from '../common/contracts';
5+
import { TestFile, TestsToRun, TestSuite, TestFunction, TestStatus } from '../common/contracts';
66
import * as constants from '../../common/constants';
77
import { getDiscoveredTests } from '../common/testUtils';
88

@@ -17,6 +17,13 @@ interface FunctionsAndSuites {
1717
}
1818

1919
export class TestFileCodeLensProvider implements CodeLensProvider {
20+
constructor(private _onDidChange: vscode.EventEmitter<void>) {
21+
}
22+
23+
get onDidChangeCodeLenses(): vscode.Event<void> {
24+
return this._onDidChange.event;
25+
}
26+
2027
public provideCodeLenses(document: TextDocument, token: CancellationToken): Thenable<CodeLens[]> {
2128
let testItems = getDiscoveredTests();
2229
if (!testItems || testItems.testFiles.length === 0 || testItems.testFunctions.length === 0) {
@@ -96,12 +103,12 @@ function getCodeLens(fileName: string, allFuncsAndSuites: FunctionsAndSuites,
96103
}
97104
return [
98105
new CodeLens(range, {
99-
title: constants.Text.CodeLensRunUnitTest,
106+
title: getTestStatusIcon(cls.status) + constants.Text.CodeLensRunUnitTest,
100107
command: constants.Commands.Tests_Run,
101108
arguments: [<TestsToRun>{ testSuite: [cls] }]
102109
}),
103110
new CodeLens(range, {
104-
title: constants.Text.CodeLensDebugUnitTest,
111+
title: getTestStatusIcon(cls.status) + constants.Text.CodeLensDebugUnitTest,
105112
command: constants.Commands.Tests_Debug,
106113
arguments: [<TestsToRun>{ testSuite: [cls] }]
107114
})
@@ -112,19 +119,54 @@ function getCodeLens(fileName: string, allFuncsAndSuites: FunctionsAndSuites,
112119
return null;
113120
}
114121

122+
function getTestStatusIcon(status: TestStatus): string {
123+
switch (status) {
124+
case TestStatus.Pass: {
125+
return '✔ ';
126+
}
127+
case TestStatus.Error:
128+
case TestStatus.Fail: {
129+
return '✘ ';
130+
}
131+
case TestStatus.Skipped: {
132+
return '⃠ ';
133+
}
134+
default: {
135+
return '';
136+
}
137+
}
138+
}
139+
140+
function getTestStatusIcons(fns: TestFunction[]): string {
141+
let statuses: string[] = [];
142+
let count = fns.filter(fn => fn.status === TestStatus.Pass).length;
143+
if (count > 0) {
144+
statuses.push(`✔ ${count}`);
145+
}
146+
count = fns.filter(fn => fn.status === TestStatus.Error || fn.status === TestStatus.Fail).length;
147+
if (count > 0) {
148+
statuses.push(`✘ ${count}`);
149+
}
150+
count = fns.filter(fn => fn.status === TestStatus.Skipped).length;
151+
if (count > 0) {
152+
statuses.push(`⃠ ${count}`);
153+
}
154+
155+
return statuses.join(' ');
156+
}
115157
function getFunctionCodeLens(filePath: string, functionsAndSuites: FunctionsAndSuites,
116158
symbolName: string, range: vscode.Range): vscode.CodeLens[] {
117159

118160
const fn = functionsAndSuites.functions.find(fn => fn.name === symbolName);
119161
if (fn) {
120162
return [
121163
new CodeLens(range, {
122-
title: constants.Text.CodeLensRunUnitTest,
164+
title: getTestStatusIcon(fn.status) + constants.Text.CodeLensRunUnitTest,
123165
command: constants.Commands.Tests_Run,
124166
arguments: [<TestsToRun>{ testFunction: [fn] }]
125167
}),
126168
new CodeLens(range, {
127-
title: constants.Text.CodeLensDebugUnitTest,
169+
title: getTestStatusIcon(fn.status) + constants.Text.CodeLensDebugUnitTest,
128170
command: constants.Commands.Tests_Debug,
129171
arguments: [<TestsToRun>{ testFunction: [fn] }]
130172
})
@@ -155,12 +197,12 @@ function getFunctionCodeLens(filePath: string, functionsAndSuites: FunctionsAndS
155197
// Find all flattened functions
156198
return [
157199
new CodeLens(range, {
158-
title: constants.Text.CodeLensRunUnitTest + ' (Multiple)',
200+
title: getTestStatusIcons(functions) + constants.Text.CodeLensRunUnitTest + ' (Multiple)',
159201
command: constants.Commands.Tests_Picker_UI,
160202
arguments: [filePath, functions]
161203
}),
162204
new CodeLens(range, {
163-
title: constants.Text.CodeLensDebugUnitTest + ' (Multiple)',
205+
title: getTestStatusIcons(functions) + constants.Text.CodeLensDebugUnitTest + ' (Multiple)',
164206
command: constants.Commands.Tests_Picker_UI_Debug,
165207
arguments: [filePath, functions]
166208
})

src/client/unittests/display/main.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { isNotInstalledError, createDeferred } from '../../common/helpers';
77

88
export class TestResultDisplay {
99
private statusBar: vscode.StatusBarItem;
10-
constructor(private outputChannel: vscode.OutputChannel) {
10+
constructor(private outputChannel: vscode.OutputChannel, private onDidChange: vscode.EventEmitter<any> = null) {
1111
this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
1212
}
1313
public dispose() {
@@ -62,7 +62,9 @@ export class TestResultDisplay {
6262
this.statusBar.text = statusText.length === 0 ? 'No Tests Ran' : statusText.join(' ');
6363
this.statusBar.color = foreColor;
6464
this.statusBar.command = constants.Commands.Tests_View_UI;
65-
65+
if (this.onDidChange) {
66+
this.onDidChange.fire();
67+
}
6668
if (statusText.length === 0 && !debug) {
6769
vscode.window.showWarningMessage('No tests ran, please check the configuration settings for the tests.');
6870
}

src/client/unittests/main.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ let nosetestManager: nosetests.TestManager;
2121
let testResultDisplay: TestResultDisplay;
2222
let testDisplay: TestDisplay;
2323
let outChannel: vscode.OutputChannel;
24+
let onDidChange: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
2425

2526
export function activate(context: vscode.ExtensionContext, outputChannel: vscode.OutputChannel) {
2627
context.subscriptions.push({ dispose: dispose });
@@ -37,7 +38,7 @@ export function activate(context: vscode.ExtensionContext, outputChannel: vscode
3738
}
3839

3940
settings.addListener('change', onConfigChanged);
40-
context.subscriptions.push(activateCodeLenses());
41+
context.subscriptions.push(activateCodeLenses(onDidChange));
4142
}
4243
function dispose() {
4344
if (pyTestManager) {
@@ -185,7 +186,7 @@ function discoverTests(ignoreCache?: boolean) {
185186
}
186187

187188
if (testManager && (testManager.status !== TestStatus.Discovering && testManager.status !== TestStatus.Running)) {
188-
testResultDisplay = testResultDisplay ? testResultDisplay : new TestResultDisplay(outChannel);
189+
testResultDisplay = testResultDisplay ? testResultDisplay : new TestResultDisplay(outChannel, onDidChange);
189190
return testResultDisplay.DisplayDiscoverStatus(testManager.discoverTests(ignoreCache));
190191
}
191192
else {
@@ -235,7 +236,7 @@ function runTestsImpl(arg?: vscode.Uri | TestsToRun | boolean | FlattenedTestFun
235236
// lastRanTests = testsToRun;
236237
let runInfo = identifyTestType(vscode.workspace.rootPath, arg);
237238

238-
testResultDisplay = testResultDisplay ? testResultDisplay : new TestResultDisplay(outChannel);
239+
testResultDisplay = testResultDisplay ? testResultDisplay : new TestResultDisplay(outChannel, onDidChange);
239240

240241
let runPromise = testManager.runTest(runInfo, debug).catch(reason => {
241242
if (reason !== CANCELLATION_REASON) {

0 commit comments

Comments
 (0)