Merge pull request #3413 from github/koesie10/fix-tests-with-warnings
Show test results for tests with warnings
This commit is contained in:
@@ -156,9 +156,17 @@ type ResolvedQueries = string[];
|
|||||||
type ResolvedTests = string[];
|
type ResolvedTests = string[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A compilation message for a test message (either an error or a warning)
|
* The severity of a compilation message for a test message.
|
||||||
*/
|
*/
|
||||||
interface CompilationMessage {
|
export enum CompilationMessageSeverity {
|
||||||
|
Error = "ERROR",
|
||||||
|
Warning = "WARNING",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A compilation message for a test message (either an error or a warning).
|
||||||
|
*/
|
||||||
|
export interface CompilationMessage {
|
||||||
/**
|
/**
|
||||||
* The text of the message
|
* The text of the message
|
||||||
*/
|
*/
|
||||||
@@ -170,7 +178,7 @@ interface CompilationMessage {
|
|||||||
/**
|
/**
|
||||||
* The severity of the message
|
* The severity of the message
|
||||||
*/
|
*/
|
||||||
severity: number;
|
severity: CompilationMessageSeverity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ import {
|
|||||||
} from "vscode";
|
} from "vscode";
|
||||||
import { DisposableObject } from "../common/disposable-object";
|
import { DisposableObject } from "../common/disposable-object";
|
||||||
import { QLTestDiscovery } from "./qltest-discovery";
|
import { QLTestDiscovery } from "./qltest-discovery";
|
||||||
import type { CodeQLCliServer } from "../codeql-cli/cli";
|
import type { CodeQLCliServer, CompilationMessage } from "../codeql-cli/cli";
|
||||||
|
import { CompilationMessageSeverity } from "../codeql-cli/cli";
|
||||||
import { getErrorMessage } from "../common/helpers-pure";
|
import { getErrorMessage } from "../common/helpers-pure";
|
||||||
import type { BaseLogger, LogOptions } from "../common/logging";
|
import type { BaseLogger, LogOptions } from "../common/logging";
|
||||||
import type { TestRunner } from "./test-runner";
|
import type { TestRunner } from "./test-runner";
|
||||||
@@ -66,6 +67,23 @@ function changeExtension(p: string, ext: string): string {
|
|||||||
return p.slice(0, -extname(p).length) + ext;
|
return p.slice(0, -extname(p).length) + ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function compilationMessageToTestMessage(
|
||||||
|
compilationMessage: CompilationMessage,
|
||||||
|
): TestMessage {
|
||||||
|
const location = new Location(
|
||||||
|
Uri.file(compilationMessage.position.fileName),
|
||||||
|
new Range(
|
||||||
|
compilationMessage.position.line - 1,
|
||||||
|
compilationMessage.position.column - 1,
|
||||||
|
compilationMessage.position.endLine - 1,
|
||||||
|
compilationMessage.position.endColumn - 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const testMessage = new TestMessage(compilationMessage.message);
|
||||||
|
testMessage.location = location;
|
||||||
|
return testMessage;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the complete text content of the specified file. If there is an error reading the file,
|
* Returns the complete text content of the specified file. If there is an error reading the file,
|
||||||
* an error message is added to `testMessages` and this function returns undefined.
|
* an error message is added to `testMessages` and this function returns undefined.
|
||||||
@@ -398,23 +416,15 @@ export class TestManager extends DisposableObject {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event.messages?.length > 0) {
|
const errorMessages = event.messages.filter(
|
||||||
|
(m) => m.severity === CompilationMessageSeverity.Error,
|
||||||
|
);
|
||||||
|
if (errorMessages.length > 0) {
|
||||||
// The test didn't make it far enough to produce results. Transform any error messages
|
// The test didn't make it far enough to produce results. Transform any error messages
|
||||||
// into `TestMessage`s and report the test as "errored".
|
// into `TestMessage`s and report the test as "errored".
|
||||||
const testMessages = event.messages.map((m) => {
|
const testMessages = event.messages.map(
|
||||||
const location = new Location(
|
compilationMessageToTestMessage,
|
||||||
Uri.file(m.position.fileName),
|
);
|
||||||
new Range(
|
|
||||||
m.position.line - 1,
|
|
||||||
m.position.column - 1,
|
|
||||||
m.position.endLine - 1,
|
|
||||||
m.position.endColumn - 1,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
const testMessage = new TestMessage(m.message);
|
|
||||||
testMessage.location = location;
|
|
||||||
return testMessage;
|
|
||||||
});
|
|
||||||
testRun.errored(testItem, testMessages, duration);
|
testRun.errored(testItem, testMessages, duration);
|
||||||
} else {
|
} else {
|
||||||
// Results didn't match expectations. Report the test as "failed".
|
// Results didn't match expectations. Report the test as "failed".
|
||||||
@@ -423,6 +433,12 @@ export class TestManager extends DisposableObject {
|
|||||||
// here. Any failed test needs at least one message.
|
// here. Any failed test needs at least one message.
|
||||||
testMessages.push(new TestMessage("Test failed"));
|
testMessages.push(new TestMessage("Test failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add any warnings produced by the test to the test messages.
|
||||||
|
testMessages.push(
|
||||||
|
...event.messages.map(compilationMessageToTestMessage),
|
||||||
|
);
|
||||||
|
|
||||||
testRun.failed(testItem, testMessages, duration);
|
testRun.failed(testItem, testMessages, duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { TestItem, TestItemCollection, TestRun } from "vscode";
|
import type { TestItem, TestItemCollection, TestRun } from "vscode";
|
||||||
import {
|
import {
|
||||||
CancellationTokenSource,
|
CancellationTokenSource,
|
||||||
|
Location,
|
||||||
Range,
|
Range,
|
||||||
TestRunRequest,
|
TestRunRequest,
|
||||||
Uri,
|
Uri,
|
||||||
@@ -75,6 +76,11 @@ describe("test-adapter", () => {
|
|||||||
id: `test ${mockTestsInfo.hPath}`,
|
id: `test ${mockTestsInfo.hPath}`,
|
||||||
uri: Uri.file(mockTestsInfo.hPath),
|
uri: Uri.file(mockTestsInfo.hPath),
|
||||||
} as TestItem,
|
} as TestItem,
|
||||||
|
{
|
||||||
|
children: { size: 0 } as TestItemCollection,
|
||||||
|
id: `test ${mockTestsInfo.kPath}`,
|
||||||
|
uri: Uri.file(mockTestsInfo.kPath),
|
||||||
|
} as TestItem,
|
||||||
];
|
];
|
||||||
const childElements: IdTestItemPair[] = childItems.map((childItem) => [
|
const childElements: IdTestItemPair[] = childItems.map((childItem) => [
|
||||||
childItem.id,
|
childItem.id,
|
||||||
@@ -87,7 +93,7 @@ describe("test-adapter", () => {
|
|||||||
id: `dir ${mockTestsInfo.testsPath}`,
|
id: `dir ${mockTestsInfo.testsPath}`,
|
||||||
uri: Uri.file(mockTestsInfo.testsPath),
|
uri: Uri.file(mockTestsInfo.testsPath),
|
||||||
children: {
|
children: {
|
||||||
size: 3,
|
size: 4,
|
||||||
[Symbol.iterator]: childIteratorFunc,
|
[Symbol.iterator]: childIteratorFunc,
|
||||||
} as TestItemCollection,
|
} as TestItemCollection,
|
||||||
} as TestItem;
|
} as TestItem;
|
||||||
@@ -95,7 +101,7 @@ describe("test-adapter", () => {
|
|||||||
const request = new TestRunRequest([rootItem]);
|
const request = new TestRunRequest([rootItem]);
|
||||||
await testManager.run(request, new CancellationTokenSource().token);
|
await testManager.run(request, new CancellationTokenSource().token);
|
||||||
|
|
||||||
expect(enqueuedSpy).toHaveBeenCalledTimes(3);
|
expect(enqueuedSpy).toHaveBeenCalledTimes(4);
|
||||||
expect(passedSpy).toHaveBeenCalledTimes(1);
|
expect(passedSpy).toHaveBeenCalledTimes(1);
|
||||||
expect(passedSpy).toHaveBeenCalledWith(childItems[0], 3000);
|
expect(passedSpy).toHaveBeenCalledWith(childItems[0], 3000);
|
||||||
expect(erroredSpy).toHaveBeenCalledTimes(1);
|
expect(erroredSpy).toHaveBeenCalledTimes(1);
|
||||||
@@ -112,6 +118,7 @@ describe("test-adapter", () => {
|
|||||||
],
|
],
|
||||||
4000,
|
4000,
|
||||||
);
|
);
|
||||||
|
expect(failedSpy).toHaveBeenCalledTimes(2);
|
||||||
expect(failedSpy).toHaveBeenCalledWith(
|
expect(failedSpy).toHaveBeenCalledWith(
|
||||||
childItems[2],
|
childItems[2],
|
||||||
[
|
[
|
||||||
@@ -121,7 +128,22 @@ describe("test-adapter", () => {
|
|||||||
],
|
],
|
||||||
11000,
|
11000,
|
||||||
);
|
);
|
||||||
expect(failedSpy).toHaveBeenCalledTimes(1);
|
expect(failedSpy).toHaveBeenCalledWith(
|
||||||
|
childItems[3],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
message: "Test failed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "abc",
|
||||||
|
location: new Location(
|
||||||
|
Uri.file(mockTestsInfo.kPath),
|
||||||
|
new Range(0, 0, 1, 1),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
15000,
|
||||||
|
);
|
||||||
expect(endSpy).toHaveBeenCalledTimes(1);
|
expect(endSpy).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export const mockTestsInfo = {
|
|||||||
dPath: Uri.parse("file:/ab/c/d.ql").fsPath,
|
dPath: Uri.parse("file:/ab/c/d.ql").fsPath,
|
||||||
gPath: Uri.parse("file:/ab/c/e/f/g.ql").fsPath,
|
gPath: Uri.parse("file:/ab/c/e/f/g.ql").fsPath,
|
||||||
hPath: Uri.parse("file:/ab/c/e/f/h.ql").fsPath,
|
hPath: Uri.parse("file:/ab/c/e/f/h.ql").fsPath,
|
||||||
|
kPath: Uri.parse("file:/ab/c/e/f/k.ql").fsPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,6 +90,28 @@ function mockRunTests(): jest.Mock<any, any> {
|
|||||||
evaluationMs: 6000,
|
evaluationMs: 6000,
|
||||||
messages: [],
|
messages: [],
|
||||||
});
|
});
|
||||||
|
yield Promise.resolve({
|
||||||
|
test: mockTestsInfo.kPath,
|
||||||
|
pass: false,
|
||||||
|
diff: ["jkh", "tuv"],
|
||||||
|
failureStage: "RESULT",
|
||||||
|
compilationMs: 7000,
|
||||||
|
evaluationMs: 8000,
|
||||||
|
// a warning in an otherwise successful test
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
position: {
|
||||||
|
fileName: mockTestsInfo.kPath,
|
||||||
|
line: 1,
|
||||||
|
column: 1,
|
||||||
|
endLine: 2,
|
||||||
|
endColumn: 2,
|
||||||
|
},
|
||||||
|
message: "abc",
|
||||||
|
severity: "WARNING",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
})(),
|
})(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ describe("test-runner", () => {
|
|||||||
eventHandlerSpy,
|
eventHandlerSpy,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(eventHandlerSpy).toHaveBeenCalledTimes(3);
|
expect(eventHandlerSpy).toHaveBeenCalledTimes(4);
|
||||||
|
|
||||||
expect(eventHandlerSpy).toHaveBeenNthCalledWith(1, {
|
expect(eventHandlerSpy).toHaveBeenNthCalledWith(1, {
|
||||||
test: mockTestsInfo.dPath,
|
test: mockTestsInfo.dPath,
|
||||||
@@ -133,6 +133,27 @@ describe("test-runner", () => {
|
|||||||
failureStage: "RESULT",
|
failureStage: "RESULT",
|
||||||
messages: [],
|
messages: [],
|
||||||
});
|
});
|
||||||
|
expect(eventHandlerSpy).toHaveBeenNthCalledWith(4, {
|
||||||
|
test: mockTestsInfo.kPath,
|
||||||
|
pass: false,
|
||||||
|
compilationMs: 7000,
|
||||||
|
evaluationMs: 8000,
|
||||||
|
diff: ["jkh", "tuv"],
|
||||||
|
failureStage: "RESULT",
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
position: {
|
||||||
|
fileName: mockTestsInfo.kPath,
|
||||||
|
line: 1,
|
||||||
|
column: 1,
|
||||||
|
endLine: 2,
|
||||||
|
endColumn: 2,
|
||||||
|
},
|
||||||
|
message: "abc",
|
||||||
|
severity: "WARNING",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should reregister testproj databases around test run", async () => {
|
it("should reregister testproj databases around test run", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user