未验证 提交 06be9f40 编写于 作者: C Connor Peet

testing: tests and speed improvements

上级 38804630
...@@ -2359,7 +2359,7 @@ declare module 'vscode' { ...@@ -2359,7 +2359,7 @@ declare module 'vscode' {
runnable?: boolean; runnable?: boolean;
/** /**
* Whether this test item can be debugged. * Whether this test item can be debugged. Defaults to `false` if not provided.
*/ */
debuggable?: boolean; debuggable?: boolean;
......
...@@ -17,7 +17,7 @@ import { ExtHostTestingResource, ExtHostTestingShape, MainContext, MainThreadTes ...@@ -17,7 +17,7 @@ import { ExtHostTestingResource, ExtHostTestingShape, MainContext, MainThreadTes
import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { TestItem } from 'vs/workbench/api/common/extHostTypeConverters'; import { TestItem } from 'vs/workbench/api/common/extHostTypeConverters';
import { Disposable } from 'vs/workbench/api/common/extHostTypes'; import { Disposable, RequiredTestItem } from 'vs/workbench/api/common/extHostTypes';
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { AbstractIncrementalTestCollection, EMPTY_TEST_RESULT, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, RunTestForProviderRequest, RunTestsResult, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import { AbstractIncrementalTestCollection, EMPTY_TEST_RESULT, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, RunTestForProviderRequest, RunTestsResult, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
import type * as vscode from 'vscode'; import type * as vscode from 'vscode';
...@@ -178,7 +178,7 @@ export class ExtHostTesting implements ExtHostTestingShape { ...@@ -178,7 +178,7 @@ export class ExtHostTesting implements ExtHostTestingShape {
} }
} }
const keyMap: { [K in keyof Omit<Required<vscode.TestItem>, 'children'>]: null } = { const keyMap: { [K in keyof Omit<RequiredTestItem, 'children'>]: null } = {
label: null, label: null,
location: null, location: null,
state: null, state: null,
...@@ -215,6 +215,9 @@ export interface OwnedCollectionTestItem extends InternalTestItem { ...@@ -215,6 +215,9 @@ export interface OwnedCollectionTestItem extends InternalTestItem {
previousEquals: (v: vscode.TestItem) => boolean; previousEquals: (v: vscode.TestItem) => boolean;
} }
/**
* @private
*/
export class OwnedTestCollection { export class OwnedTestCollection {
protected readonly testIdToInternal = new Map<string, OwnedCollectionTestItem>(); protected readonly testIdToInternal = new Map<string, OwnedCollectionTestItem>();
...@@ -542,11 +545,16 @@ export class MirroredTestCollection extends AbstractIncrementalTestCollection<Mi ...@@ -542,11 +545,16 @@ export class MirroredTestCollection extends AbstractIncrementalTestCollection<Mi
/** /**
* Translates the item IDs to TestItems for exposure to extensions. * Translates the item IDs to TestItems for exposure to extensions.
*/ */
public getAllAsTestItem(itemIds: ReadonlyArray<string>): vscode.TestItem[] { public getAllAsTestItem(itemIds: Iterable<string>): vscode.TestItem[] {
return itemIds.map(itemId => { let output: vscode.TestItem[] = [];
for (const itemId of itemIds) {
const item = this.items.get(itemId); const item = this.items.get(itemId);
return item && this.getPublicTestItem(item); if (item) {
}).filter(isDefined); output.push(this.getPublicTestItem(item));
}
}
return output;
} }
/** /**
...@@ -584,7 +592,7 @@ export class MirroredTestCollection extends AbstractIncrementalTestCollection<Mi ...@@ -584,7 +592,7 @@ export class MirroredTestCollection extends AbstractIncrementalTestCollection<Mi
*/ */
public getPublicTestItem(item: MirroredCollectionTestItem): vscode.TestItem { public getPublicTestItem(item: MirroredCollectionTestItem): vscode.TestItem {
if (!item.wrapped) { if (!item.wrapped) {
item.wrapped = createMirroredTestItem(item, this); item.wrapped = new ExtHostTestItem(item, this);
} }
return item.wrapped; return item.wrapped;
...@@ -597,29 +605,41 @@ const getMirroredItemId = (item: vscode.TestItem) => { ...@@ -597,29 +605,41 @@ const getMirroredItemId = (item: vscode.TestItem) => {
const MirroredItemId = Symbol('MirroredItemId'); const MirroredItemId = Symbol('MirroredItemId');
const createMirroredTestItem = (internal: MirroredCollectionTestItem, collection: MirroredTestCollection): vscode.TestItem => { class ExtHostTestItem implements vscode.TestItem, RequiredTestItem {
const obj = {}; readonly #internal: MirroredCollectionTestItem;
readonly #collection: MirroredTestCollection;
Object.defineProperty(obj, MirroredItemId, { public get label() { return this.#internal.revived.label; }
enumerable: false, public get description() { return this.#internal.revived.description; }
configurable: false, public get state() { return this.#internal.revived.state; }
value: internal.id, public get location() { return this.#internal.revived.location; }
}); public get runnable() { return this.#internal.revived.runnable ?? true; }
public get debuggable() { return this.#internal.revived.debuggable ?? false; }
public get children() {
return this.#collection.getAllAsTestItem(this.#internal.children);
}
Object.defineProperty(obj, 'children', { get [MirroredItemId]() { return this.#internal.id; }
enumerable: true,
configurable: false,
get: () => collection.getAllAsTestItem([...internal.children])
});
simpleProps.forEach(prop => Object.defineProperty(obj, prop, { constructor(internal: MirroredCollectionTestItem, collection: MirroredTestCollection) {
enumerable: true, this.#internal = internal;
configurable: false, this.#collection = collection;
get: () => internal.revived[prop], }
}));
return obj as any; public toJSON() {
}; const serialized: RequiredTestItem = {
label: this.label,
description: this.description,
state: this.state,
location: this.location,
runnable: this.runnable,
debuggable: this.debuggable,
children: this.children.map(c => (c as ExtHostTestItem).toJSON()),
};
return serialized;
}
}
interface IObserverData { interface IObserverData {
observers: number; observers: number;
......
...@@ -2940,4 +2940,15 @@ export class TestState { ...@@ -2940,4 +2940,15 @@ export class TestState {
} }
} }
type AllowedUndefined = 'description' | 'location';
/**
* Test item without any optional properties. Only some properties are
* permitted to be undefined, but they must still exist.
*/
export type RequiredTestItem = {
[K in keyof Required<vscode.TestItem>]: K extends AllowedUndefined ? vscode.TestItem[K] : Required<vscode.TestItem>[K]
};
//#endregion //#endregion
...@@ -19,8 +19,16 @@ const stubTest = (label: string): TestItem => ({ ...@@ -19,8 +19,16 @@ const stubTest = (label: string): TestItem => ({
description: '' description: ''
}); });
const simplify = (item: TestItem) => {
if ('toJSON' in item) {
item = (item as any).toJSON();
}
return { ...item, children: undefined };
};
const assertTreesEqual = (a: Readonly<TestItem>, b: Readonly<TestItem>) => { const assertTreesEqual = (a: Readonly<TestItem>, b: Readonly<TestItem>) => {
assert.deepStrictEqual({ ...a, children: undefined }, { ...b, children: undefined }); assert.deepStrictEqual(simplify(a), simplify(b));
const aChildren = (a.children ?? []).sort(); const aChildren = (a.children ?? []).sort();
const bChildren = (b.children ?? []).sort(); const bChildren = (b.children ?? []).sort();
...@@ -274,11 +282,29 @@ suite('ExtHost Testing', () => { ...@@ -274,11 +282,29 @@ suite('ExtHost Testing', () => {
single.onItemChange(tests, 'pid'); single.onItemChange(tests, 'pid');
m.apply(single.collectDiff()); m.apply(single.collectDiff());
assert.deepStrictEqual(m.changeEvent.commonChangeAncestor?.label, 'root'); assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'root');
assertTreeListEqual(m.changeEvent.added, [child]); assertTreeListEqual(m.changeEvent.added, [child]);
assertTreeListEqual(m.changeEvent.removed, []); assertTreeListEqual(m.changeEvent.removed, []);
assertTreeListEqual(m.changeEvent.updated, []); assertTreeListEqual(m.changeEvent.updated, []);
}); });
test('gets the common ancestor (1)', () => {
tests.children![0].children![0].label = 'za';
tests.children![0].children![1].label = 'zb';
single.onItemChange(tests, 'pid');
m.apply(single.collectDiff());
assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'a');
});
test('gets the common ancestor (2)', () => {
tests.children![0].children![0].label = 'za';
tests.children![1].label = 'ab';
single.onItemChange(tests, 'pid');
m.apply(single.collectDiff());
assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'root');
});
}); });
}); });
}); });
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册