From cdca42f692c8e541f1bc05f09521e88caff7fd13 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 28 Nov 2024 06:44:33 -0800 Subject: [PATCH] fix: add stack traces to test message for test error. (#545) - For thrown error scenarios provides the location of the error thrown inside the tested code with fully navigable trace. - For non throw error scenarios provides additional context on the failed assertion. Co-authored-by: ArthurHub <5463635+ArthurHub@users.noreply.github.com> --- samples/basic/src/add.ts | 10 ++++++++++ samples/basic/test/throw.test.ts | 12 ++++++++++++ src/runner/runner.ts | 13 +++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 samples/basic/test/throw.test.ts diff --git a/samples/basic/src/add.ts b/samples/basic/src/add.ts index b8848d78..a0e19156 100644 --- a/samples/basic/src/add.ts +++ b/samples/basic/src/add.ts @@ -1,3 +1,4 @@ + export function add(a: number, b: number) { return a + b } @@ -5,3 +6,12 @@ export function add(a: number, b: number) { export function sum(from: number, to: number) { return (from + to) * (to - from + 1) / 2 } + +export function addError(from: number, to: number) { + doSomething() + return add(from, to) +} + +function doSomething() { + throw new Error('Something went wrong'); +} diff --git a/samples/basic/test/throw.test.ts b/samples/basic/test/throw.test.ts new file mode 100644 index 00000000..73f8e547 --- /dev/null +++ b/samples/basic/test/throw.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from 'vitest'; +import { addError } from '../src/add'; + +describe('throw error', () => { + it('passes expecting an error to be thrown', () => { + expect(()=>addError(1, 1)).toThrow() + }) + + it('fails with error thrown', () => { + expect(addError(1, 1)).toBe(2) + }) +}) diff --git a/src/runner/runner.ts b/src/runner/runner.ts index 29dff9c4..51d997f1 100644 --- a/src/runner/runner.ts +++ b/src/runner/runner.ts @@ -507,6 +507,8 @@ function testMessageForTestError(testItem: vscode.TestItem, error: TestError | u else testMessage = new vscode.TestMessage(stripVTControlCharacters(error.message) ?? '') + testMessage.stackTrace = parseMessageStackFramesFromErrorStacks(error.stacks) + const location = parseLocationFromStacks(testItem, error.stacks ?? []) if (location) { const position = new vscode.Position(location.line - 1, location.column - 1) @@ -550,6 +552,17 @@ function parseLocationFromStacks(testItem: vscode.TestItem, stacks: ParsedStack[ log.verbose?.('Could not find a valid stack for', testItem.label, JSON.stringify(stacks, null, 2)) } +function parseMessageStackFramesFromErrorStacks(stacks: ParsedStack[] | undefined): vscode.TestMessageStackFrame[] | undefined { + if (!stacks || stacks.length === 0) + return undefined + + return stacks.map((stack) => { + const { sourceFilepath, line, column } = getSourceFilepathAndLocationFromStack(stack) + const sourceUri = sourceFilepath ? vscode.Uri.file(sourceFilepath) : undefined + return new vscode.TestMessageStackFrame(stack.method, sourceUri, new vscode.Position(line - 1, column - 1)) + }) +} + function getTestFiles(tests: readonly vscode.TestItem[]): string[] | SerializedTestSpecification[] { // if there is a folder, we can't limit the tests to a specific project const hasFolder = tests.some(test => getTestData(test) instanceof TestFolder)