Skip to content

Commit 0b30aaa

Browse files
authored
display errors and tests on discovery (#21629)
fixes #13301
1 parent 5ccb731 commit 0b30aaa

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

src/client/testing/testController/common/resultResolver.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,19 @@ export class PythonResultResolver implements ITestResultResolver {
6565
}
6666
errorNode.error = message;
6767
} else {
68-
// Remove the error node if necessary,
69-
// then parse and insert test data.
68+
// remove error node only if no errors exist.
7069
this.testController.items.delete(`DiscoveryError:${workspacePath}`);
70+
}
71+
if (rawTestData.tests) {
72+
// if any tests exist, they should be populated in the test tree, regardless of whether there were errors or not.
73+
// parse and insert test data.
7174

72-
if (rawTestData.tests) {
73-
// If the test root for this folder exists: Workspace refresh, update its children.
74-
// Otherwise, it is a freshly discovered workspace, and we need to create a new test root and populate the test tree.
75-
populateTestTree(this.testController, rawTestData.tests, undefined, this, token);
76-
} else {
77-
// Delete everything from the test controller.
78-
this.testController.items.replace([]);
79-
}
75+
// If the test root for this folder exists: Workspace refresh, update its children.
76+
// Otherwise, it is a freshly discovered workspace, and we need to create a new test root and populate the test tree.
77+
populateTestTree(this.testController, rawTestData.tests, undefined, this, token);
78+
} else {
79+
// Delete everything from the test controller.
80+
this.testController.items.replace([]);
8081
}
8182

8283
sendTelemetryEvent(EventName.UNITTEST_DISCOVERY_DONE, undefined, {

src/test/testing/testController/resultResolver.unit.test.ts

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,7 @@ suite('Result Resolver tests', () => {
101101
cancelationToken, // token
102102
);
103103
});
104-
// what about if the error node already exists: this.testController.items.get(`DiscoveryError:${workspacePath}`);
105-
test('resolveDiscovery should create error node on error with correct params', async () => {
104+
test('resolveDiscovery should create error node on error with correct params and no root node with tests in payload', async () => {
106105
// test specific constants used expected values
107106
testProvider = 'pytest';
108107
workspaceUri = Uri.file('/foo/bar');
@@ -136,6 +135,61 @@ suite('Result Resolver tests', () => {
136135
// header of createErrorTestItem is (options: ErrorTestItemOptions, testController: TestController, uri: Uri)
137136
sinon.assert.calledWithMatch(createErrorTestItemStub, sinon.match.any, sinon.match.any);
138137
});
138+
test('resolveDiscovery should create error and root node when error and tests exist on payload', async () => {
139+
// test specific constants used expected values
140+
testProvider = 'pytest';
141+
workspaceUri = Uri.file('/foo/bar');
142+
resultResolver = new ResultResolver.PythonResultResolver(testController, testProvider, workspaceUri);
143+
const errorMessage = 'error msg A';
144+
const expectedErrorMessage = `${defaultErrorMessage}\r\n ${errorMessage}`;
145+
146+
// create test result node
147+
const tests: DiscoveredTestNode = {
148+
path: 'path',
149+
name: 'name',
150+
type_: 'folder',
151+
id_: 'id',
152+
children: [],
153+
};
154+
// stub out return values of functions called in resolveDiscovery
155+
const payload: DiscoveredTestPayload = {
156+
cwd: workspaceUri.fsPath,
157+
status: 'error',
158+
error: [errorMessage],
159+
tests,
160+
};
161+
const errorTestItemOptions: testItemUtilities.ErrorTestItemOptions = {
162+
id: 'id',
163+
label: 'label',
164+
error: 'error',
165+
};
166+
167+
// stub out functionality of buildErrorNodeOptions and createErrorTestItem which are called in resolveDiscovery
168+
const buildErrorNodeOptionsStub = sinon.stub(util, 'buildErrorNodeOptions').returns(errorTestItemOptions);
169+
const createErrorTestItemStub = sinon.stub(testItemUtilities, 'createErrorTestItem').returns(blankTestItem);
170+
171+
// stub out functionality of populateTestTreeStub which is called in resolveDiscovery
172+
const populateTestTreeStub = sinon.stub(util, 'populateTestTree').returns();
173+
// call resolve discovery
174+
resultResolver.resolveDiscovery(payload, cancelationToken);
175+
176+
// assert the stub functions were called with the correct parameters
177+
178+
// builds an error node root
179+
sinon.assert.calledWithMatch(buildErrorNodeOptionsStub, workspaceUri, expectedErrorMessage, testProvider);
180+
// builds an error item
181+
sinon.assert.calledWithMatch(createErrorTestItemStub, sinon.match.any, sinon.match.any);
182+
183+
// also calls populateTestTree with the discovery test results
184+
sinon.assert.calledWithMatch(
185+
populateTestTreeStub,
186+
testController, // testController
187+
tests, // testTreeData
188+
undefined, // testRoot
189+
resultResolver, // resultResolver
190+
cancelationToken, // token
191+
);
192+
});
139193
});
140194
suite('Test execution result resolver', () => {
141195
let resultResolver: ResultResolver.PythonResultResolver;

0 commit comments

Comments
 (0)