Skip to content

Commit a0a662c

Browse files
authored
testing: add configuration to show all test messages. (microsoft#185197)
* Add configuration to show all test messages. Introduce `testing.showAllMessages` configuration, which defaults to true. When false, only the first message is shown, and the rest are ignored. When true, the most recent message for each line is shown from all past test runs. * Change from Map -> Set.
1 parent f945c1f commit a0a662c

File tree

2 files changed

+55
-43
lines changed

2 files changed

+55
-43
lines changed

src/vs/workbench/contrib/testing/browser/testingDecorations.ts

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import { DefaultGutterClickAction, TestingConfigKeys, getTestingConfiguration }
4444
import { Testing, labelForTestInState } from 'vs/workbench/contrib/testing/common/constants';
4545
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
4646
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
47-
import { LiveTestResult } from 'vs/workbench/contrib/testing/common/testResult';
47+
import { ITestResult, LiveTestResult } from 'vs/workbench/contrib/testing/common/testResult';
4848
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
4949
import { ITestService, getContextForTestItem, testsInFile } from 'vs/workbench/contrib/testing/common/testService';
5050
import { IRichLocation, ITestMessage, ITestRunProfile, IncrementalTestCollectionItem, InternalTestItem, TestDiffOpType, TestMessageType, TestResultItem, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testTypes';
@@ -318,47 +318,11 @@ export class TestingDecorationService extends Disposable implements ITestingDeco
318318
}
319319
}
320320

321-
const lastResult = this.results.results[0];
322-
if (this.testService.showInlineOutput.value && lastResult instanceof LiveTestResult) {
323-
for (const task of lastResult.tasks) {
324-
for (const m of task.otherMessages) {
325-
if (!this.invalidatedMessages.has(m) && m.location?.uri.toString() === uriStr) {
326-
const decoration = lastDecorations.getMessage(m) || this.instantiationService.createInstance(TestMessageDecoration, m, undefined, model);
327-
newDecorations.addMessage(decoration);
328-
}
329-
}
330-
}
331-
332-
const messageLines = new Map</* line number */ number, /* last test message */ ITestMessage>();
333-
for (const test of lastResult.tests) {
334-
for (let taskId = 0; taskId < test.tasks.length; taskId++) {
335-
const state = test.tasks[taskId];
336-
for (let i = 0; i < state.messages.length; i++) {
337-
const m = state.messages[i];
338-
if (this.invalidatedMessages.has(m) || m.location?.uri.toString() !== uriStr) {
339-
continue;
340-
}
341-
342-
// Only add one message per line number. Overlapping messages
343-
// don't appear well, and the peek will show all of them (#134129)
344-
const line = m.location.range.startLineNumber;
345-
if (messageLines.has(line)) {
346-
newDecorations.removeMessage(messageLines.get(line)!);
347-
}
348-
349-
const decoration = lastDecorations.getMessage(m) || this.instantiationService.createInstance(TestMessageDecoration, m, buildTestUri({
350-
type: TestUriType.ResultActualOutput,
351-
messageIndex: i,
352-
taskIndex: taskId,
353-
resultId: lastResult.id,
354-
testExtId: test.item.extId,
355-
}), model);
356-
357-
newDecorations.addMessage(decoration);
358-
messageLines.set(line, decoration.testMessage);
359-
}
360-
}
361-
}
321+
const messageLines = new Set<number>();
322+
if (getTestingConfiguration(this.configurationService, TestingConfigKeys.ShowAllMessages)) {
323+
this.results.results.forEach(lastResult => this.applyDecorationsFromResult(lastResult, messageLines, uriStr, lastDecorations, model, newDecorations));
324+
} else {
325+
this.applyDecorationsFromResult(this.results.results[0], messageLines, uriStr, lastDecorations, model, newDecorations);
362326
}
363327

364328
const saveFromRemoval = new Set<string>();
@@ -387,6 +351,47 @@ export class TestingDecorationService extends Disposable implements ITestingDeco
387351

388352
return newDecorations || lastDecorations;
389353
}
354+
355+
private applyDecorationsFromResult(lastResult: ITestResult, messageLines: Set<Number>, uriStr: string, lastDecorations: CachedDecorations, model: ITextModel, newDecorations: CachedDecorations) {
356+
if (this.testService.showInlineOutput.value && lastResult instanceof LiveTestResult) {
357+
for (const task of lastResult.tasks) {
358+
for (const m of task.otherMessages) {
359+
if (!this.invalidatedMessages.has(m) && m.location?.uri.toString() === uriStr) {
360+
const decoration = lastDecorations.getMessage(m) || this.instantiationService.createInstance(TestMessageDecoration, m, undefined, model);
361+
newDecorations.addMessage(decoration);
362+
}
363+
}
364+
}
365+
366+
for (const test of lastResult.tests) {
367+
for (let taskId = 0; taskId < test.tasks.length; taskId++) {
368+
const state = test.tasks[taskId];
369+
for (let i = 0; i < state.messages.length; i++) {
370+
const m = state.messages[i];
371+
if (this.invalidatedMessages.has(m) || m.location?.uri.toString() !== uriStr) {
372+
continue;
373+
}
374+
375+
// Only add one message per line number. Overlapping messages
376+
// don't appear well, and the peek will show all of them (#134129)
377+
const line = m.location.range.startLineNumber;
378+
if (!messageLines.has(line)) {
379+
const decoration = lastDecorations.getMessage(m) || this.instantiationService.createInstance(TestMessageDecoration, m, buildTestUri({
380+
type: TestUriType.ResultActualOutput,
381+
messageIndex: i,
382+
taskIndex: taskId,
383+
resultId: lastResult.id,
384+
testExtId: test.item.extId,
385+
}), model);
386+
387+
newDecorations.addMessage(decoration);
388+
messageLines.add(line);
389+
}
390+
}
391+
}
392+
}
393+
}
394+
}
390395
}
391396

392397
export class TestingDecorations extends Disposable implements IEditorContribution {

src/vs/workbench/contrib/testing/common/configuration.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ export const enum TestingConfigKeys {
1717
GutterEnabled = 'testing.gutterEnabled',
1818
SaveBeforeTest = 'testing.saveBeforeTest',
1919
AlwaysRevealTestOnStateChange = 'testing.alwaysRevealTestOnStateChange',
20-
CountBadge = 'testing.countBadge'
20+
CountBadge = 'testing.countBadge',
21+
ShowAllMessages = 'testing.showAllMessages',
2122
}
2223

2324
export const enum AutoOpenTesting {
@@ -71,6 +72,11 @@ export const testingConfiguration: IConfigurationNode = {
7172
localize('testing.automaticallyOpenPeekView.never', "Never automatically open."),
7273
],
7374
},
75+
[TestingConfigKeys.ShowAllMessages]: {
76+
description: localize('testing.showAllMessages', "Controls whether to show messages from all test runs."),
77+
type: 'boolean',
78+
default: true,
79+
},
7480
[TestingConfigKeys.AutoOpenPeekViewDuringContinuousRun]: {
7581
description: localize('testing.automaticallyOpenPeekViewDuringContinuousRun', "Controls whether to automatically open the Peek view during continuous run mode."),
7682
type: 'boolean',
@@ -154,6 +160,7 @@ export interface ITestingConfiguration {
154160
[TestingConfigKeys.SaveBeforeTest]: boolean;
155161
[TestingConfigKeys.OpenTesting]: AutoOpenTesting;
156162
[TestingConfigKeys.AlwaysRevealTestOnStateChange]: boolean;
163+
[TestingConfigKeys.ShowAllMessages]: boolean;
157164
}
158165

159166
export const getTestingConfiguration = <K extends TestingConfigKeys>(config: IConfigurationService, key: K) => config.getValue<ITestingConfiguration[K]>(key);

0 commit comments

Comments
 (0)