Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

src/goTest: Add command Test Function At Cursor or Test Previous #1509

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ List all the Go tools being used by this extension along with their locations.

Runs a unit test at the cursor.

### `Go: Test Function At Cursor or Test Previous`

Runs a unit test at the cursor if one is found, otherwise re-runs the last executed test.

### `Go: Subtest At Cursor`

Runs a sub test at the cursor.
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@
"title": "Go: Test Function At Cursor",
"description": "Runs a unit test at the cursor."
},
{
"command": "go.test.cursorOrPrevious",
"title": "Go: Test Function At Cursor or Test Previous",
"description": "Runs a unit test at the cursor if one is found, otherwise re-runs the last executed test."
},
{
"command": "go.subtest.cursor",
"title": "Go: Subtest At Cursor",
Expand Down
8 changes: 8 additions & 0 deletions src/goMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import {
debugPrevious,
subTestAtCursor,
testAtCursor,
testAtCursorOrPrevious,
testCurrentFile,
testCurrentPackage,
testPrevious,
Expand Down Expand Up @@ -316,6 +317,13 @@ If you would like additional configuration for diagnostics from gopls, please se
})
);

ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.cursorOrPrevious', (args) => {
const goConfig = getGoConfig();
testAtCursorOrPrevious(goConfig, 'test', args);
})
);

ctx.subscriptions.push(
vscode.commands.registerCommand('go.subtest.cursor', (args) => {
const goConfig = getGoConfig();
Expand Down
88 changes: 53 additions & 35 deletions src/goTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,50 +31,68 @@ let lastDebugWorkspaceFolder: vscode.WorkspaceFolder;

export type TestAtCursorCmd = 'debug' | 'test' | 'benchmark';

/**
* Executes the unit test at the primary cursor using `go test`. Output
* is sent to the 'Go' channel.
* @param goConfig Configuration for the Go extension.
* @param cmd Whether the command is test , benchmark or debug.
* @param args
*/
export function testAtCursor(goConfig: vscode.WorkspaceConfiguration, cmd: TestAtCursorCmd, args: any) {
class NotFoundError extends Error {}

async function _testAtCursor(goConfig: vscode.WorkspaceConfiguration, cmd: TestAtCursorCmd, args: any) {
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showInformationMessage('No editor is active.');
return;
throw new NotFoundError('No editor is active.');
}
if (!editor.document.fileName.endsWith('_test.go')) {
vscode.window.showInformationMessage('No tests found. Current file is not a test file.');
return;
throw new NotFoundError('No tests found. Current file is not a test file.');
}

const getFunctions = cmd === 'benchmark' ? getBenchmarkFunctions : getTestFunctions;
const testFunctions = await getFunctions(editor.document, null);
// We use functionName if it was provided as argument
// Otherwise find any test function containing the cursor.
const testFunctionName =
args && args.functionName
? args.functionName
: testFunctions.filter((func) => func.range.contains(editor.selection.start)).map((el) => el.name)[0];
if (!testFunctionName) {
throw new NotFoundError('No test function found at cursor.');
}

editor.document.save().then(async () => {
try {
const testFunctions = await getFunctions(editor.document, null);
// We use functionName if it was provided as argument
// Otherwise find any test function containing the cursor.
const testFunctionName =
args && args.functionName
? args.functionName
: testFunctions
.filter((func) => func.range.contains(editor.selection.start))
.map((el) => el.name)[0];
if (!testFunctionName) {
vscode.window.showInformationMessage('No test function found at cursor.');
return;
}
await editor.document.save();

if (cmd === 'debug') {
await debugTestAtCursor(editor, testFunctionName, testFunctions, goConfig);
} else if (cmd === 'benchmark' || cmd === 'test') {
await runTestAtCursor(editor, testFunctionName, testFunctions, goConfig, cmd, args);
} else {
throw new Error('Unsupported command.');
}
} catch (err) {
if (cmd === 'debug') {
return debugTestAtCursor(editor, testFunctionName, testFunctions, goConfig);
} else if (cmd === 'benchmark' || cmd === 'test') {
return runTestAtCursor(editor, testFunctionName, testFunctions, goConfig, cmd, args);
} else {
throw new Error(`Unsupported command: ${cmd}`);
}
}

/**
* Executes the unit test at the primary cursor using `go test`. Output
* is sent to the 'Go' channel.
* @param goConfig Configuration for the Go extension.
* @param cmd Whether the command is test, benchmark, or debug.
* @param args
*/
export function testAtCursor(goConfig: vscode.WorkspaceConfiguration, cmd: TestAtCursorCmd, args: any) {
_testAtCursor(goConfig, cmd, args).catch((err) => {
if (err instanceof NotFoundError) {
vscode.window.showInformationMessage(err.message);
} else {
console.error(err);
}
});
}

/**
* Executes the unit test at the primary cursor if found, otherwise re-runs the previous test.
* @param goConfig Configuration for the Go extension.
* @param cmd Whether the command is test, benchmark, or debug.
* @param args
*/
export function testAtCursorOrPrevious(goConfig: vscode.WorkspaceConfiguration, cmd: TestAtCursorCmd, args: any) {
_testAtCursor(goConfig, cmd, args).catch((err) => {
if (err instanceof NotFoundError) {
testPrevious();
} else {
console.error(err);
}
});
Expand Down