Skip to content

Commit

Permalink
testing: update testing API with proposals (#207512)
Browse files Browse the repository at this point in the history
* wip

* testing: update testing API with proposals

This replaces the test provider with:

- An `addCoverage` method on the TestRun. The benefit of this is that
  test data can be provided gradually, even upserted, over a test run
	to provide more live results.
- A `loadDetailedCoverage` on the profile which loads coverage details.
  This is the "resolve" handler before.
- An additional onDidDispose event on the TestRun that extensions can
  use to clear allocated resources.

Note that the the `FileCoverage` instance given to `loadDetailedCoverage`
is the same instance provided to `addCoverage`, so it can be subclassed
to tag in additional detail. The `TestRun` instance is also the same, so
`WeakMap`s can be used for associating data with both.

Naming might change over the next week, but there were good feelings
about this structure the API call this morning.

This change has a backwards-compatibility shim, but extensions should
migrate over before our next stable release in ~3 weeks from today.

fyi @jdneo @eleanorjboyd

* avoid structuredClone
  • Loading branch information
connor4312 committed Mar 14, 2024
1 parent b9bca88 commit d64800f
Show file tree
Hide file tree
Showing 14 changed files with 291 additions and 263 deletions.
42 changes: 28 additions & 14 deletions src/vs/workbench/api/browser/mainThreadTesting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { VSBuffer } from 'vs/base/common/buffer';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Event } from 'vs/base/common/event';
import { Disposable, DisposableStore, IDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { ISettableObservable } from 'vs/base/common/observable';
import { ISettableObservable, transaction } from 'vs/base/common/observable';
import { WellDefinedPrefixTree } from 'vs/base/common/prefixTree';
import { URI } from 'vs/base/common/uri';
import { Range } from 'vs/editor/common/core/range';
Expand Down Expand Up @@ -58,10 +58,17 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh
}));

this._register(resultService.onResultsChanged(evt => {
const results = 'completed' in evt ? evt.completed : ('inserted' in evt ? evt.inserted : undefined);
const serialized = results?.toJSONWithMessages();
if (serialized) {
this.proxy.$publishTestResults([serialized]);
if ('completed' in evt) {
const serialized = evt.completed.toJSONWithMessages();
if (serialized) {
this.proxy.$publishTestResults([serialized]);
}
} else if ('removed' in evt) {
evt.removed.forEach(r => {
if (r instanceof LiveTestResult) {
this.proxy.$disposeRun(r.id);
}
});
}
}));
}
Expand Down Expand Up @@ -121,21 +128,28 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh
/**
* @inheritdoc
*/
$signalCoverageAvailable(runId: string, taskId: string, available: boolean): void {
$appendCoverage(runId: string, taskId: string, coverage: IFileCoverage.Serialized): void {
this.withLiveRun(runId, run => {
const task = run.tasks.find(t => t.id === taskId);
if (!task) {
return;
}

const fn = available ? ((token: CancellationToken) => TestCoverage.load(taskId, {
provideFileCoverage: async token => await this.proxy.$provideFileCoverage(runId, taskId, token)
.then(c => c.map(u => IFileCoverage.deserialize(this.uriIdentityService, u))),
resolveFileCoverage: (i, token) => this.proxy.$resolveFileCoverage(runId, taskId, i, token)
.then(d => d.map(CoverageDetails.deserialize)),
}, this.uriIdentityService, token)) : undefined;

(task.coverage as ISettableObservable<undefined | ((tkn: CancellationToken) => Promise<TestCoverage>)>).set(fn, undefined);
const deserialized = IFileCoverage.deserialize(this.uriIdentityService, coverage);

transaction(tx => {
let value = task.coverage.read(undefined);
if (!value) {
value = new TestCoverage(taskId, this.uriIdentityService, {
getCoverageDetails: (id, token) => this.proxy.$getCoverageDetails(id, token)
.then(r => r.map(CoverageDetails.deserialize)),
});
value.append(deserialized, tx);
(task.coverage as ISettableObservable<TestCoverage>).set(value, tx);
} else {
value.append(deserialized, tx);
}
});
});
}

Expand Down
13 changes: 5 additions & 8 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2681,13 +2681,10 @@ export interface ExtHostTestingShape {
$publishTestResults(results: ISerializedTestResults[]): void;
/** Expands a test item's children, by the given number of levels. */
$expandTest(testId: string, levels: number): Promise<void>;
/** Requests file coverage for a test run. Errors if not available. */
$provideFileCoverage(runId: string, taskId: string, token: CancellationToken): Promise<IFileCoverage.Serialized[]>;
/**
* Requests coverage details for the file index in coverage data for the run.
* Requires file coverage to have been previously requested via $provideFileCoverage.
*/
$resolveFileCoverage(runId: string, taskId: string, fileIndex: number, token: CancellationToken): Promise<CoverageDetails.Serialized[]>;
/** Requests coverage details for a test run. Errors if not available. */
$getCoverageDetails(coverageId: string, token: CancellationToken): Promise<CoverageDetails.Serialized[]>;
/** Disposes resources associated with a test run. */
$disposeRun(runId: string): void;
/** Configures a test run config. */
$configureRunProfile(controllerId: string, configId: number): void;
/** Asks the controller to refresh its tests */
Expand Down Expand Up @@ -2758,7 +2755,7 @@ export interface MainThreadTestingShape {
/** Appends raw output to the test run.. */
$appendOutputToRun(runId: string, taskId: string, output: VSBuffer, location?: ILocationDto, testId?: string): void;
/** Triggered when coverage is added to test results. */
$signalCoverageAvailable(runId: string, taskId: string, available: boolean): void;
$appendCoverage(runId: string, taskId: string, coverage: IFileCoverage.Serialized): void;
/** Signals a task in a test run started. */
$startedTestRunTask(runId: string, task: ITestRunTask): void;
/** Signals a task in a test run ended. */
Expand Down
Loading

0 comments on commit d64800f

Please sign in to comment.