Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

Add support for gotests "https://github.com/cweill/gotests" #489

Merged
merged 1 commit into from
Oct 6, 2016
Merged
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
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ install:
- go get -u -v github.com/newhook/go-symbols
- go get -u -v golang.org/x/tools/cmd/guru
- go get -u -v github.com/alecthomas/gometalinter
- go get -u -v github.com/cweill/gotests/...
- GO15VENDOREXPERIMENT=1 gometalinter --install

script:
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This extension adds rich language support for the Go language to VS Code, includ
- Build-on-save (using `go build` and `go test`)
- Lint-on-save (using `golint` or `gometalinter`)
- Format (using `goreturns` or `goimports` or `gofmt`)
- Generate unit tests squeleton (using `gotests`)
- Add Imports (using `gopkgs`)
- [_partially implemented_] Debugging (using `delve`)

Expand Down Expand Up @@ -98,6 +99,9 @@ In addition to integrated editing features, the extension also provides several
* `Go: Run test at cursor` to run a test at the current cursor position in the active document
* `Go: Run tests in current package` to run all tests in the package containing the active document
* `Go: Run tests in current file` to run all tests in the current active document
* `Go: Generates unit tests (package)` Generates unit tests for the current package
* `Go: Generates unit tests (file)` Generates unit tests for the current file
* `Go: Generates unit tests (function)` Generates unit tests for the selected function in the current file

### _Optional_: Debugging

Expand Down Expand Up @@ -200,6 +204,7 @@ The extension uses the following tools, installed in the current GOPATH. If any
- gopkgs: `go get -u -v github.com/tpng/gopkgs`
- go-symbols: `go get -u -v github.com/newhook/go-symbols`
- guru: `go get -u -v golang.org/x/tools/cmd/guru`
- gotests: `go get -u -v github.com/cweill/gotests/...`

To install them just paste and run:
```bash
Expand All @@ -212,6 +217,7 @@ go get -u -v golang.org/x/tools/cmd/gorename
go get -u -v github.com/tpng/gopkgs
go get -u -v github.com/newhook/go-symbols
go get -u -v golang.org/x/tools/cmd/guru
go get -u -v github.com/cweill/gotests/...
```

And for debugging:
Expand Down
15 changes: 15 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,21 @@
"title": "Go: Test coverage in current package",
"description": "Displays test coverage in the current package."
},
{
"command": "go.test.generate.package",
"title": "Go: Generate unit tests for current package",
"description": "Generates unit tests for the current package"
},
{
"command": "go.test.generate.file",
"title": "Go: Generate unit tests for current file",
"description": "Generates unit tests for the current file"
},
{
"command": "go.test.generate.function",
"title": "Go: Generate unit tests for current function",
"description": "Generates unit tests for the selected function in the current file"
},
{
"command": "go.import.add",
"title": "Go: Add Import",
Expand Down
121 changes: 121 additions & 0 deletions src/goGenerateTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------*/

'use strict';

import cp = require('child_process');
import path = require('path');
import vscode = require('vscode');
import util = require('util');

import { getBinPath } from './goPath';
import { promptForMissingTool } from './goInstallTools';
import { GoDocumentSymbolProvider } from './goOutline';

export function generateTestCurrentPackage(): Thenable<boolean> {
let editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showInformationMessage('gotests: No editor selected');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You already have a message being shown in line 116. You don't need this message again. I'd actually suggest to remove the function testEditor altogether and replace
let editor = testEditor()
with
let editor = vscode.window.activeTextEditor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will do this change.

return;
}
let dir = path.dirname(editor.document.uri.fsPath);
let message = 'Unit tests generated for package:' + path.basename(dir);
return generateTests({dir: dir, msg: message });
}

export function generateTestCurrentFile(): Thenable<boolean> {
let editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showInformationMessage('gotests: No editor selected');
return;
}
let file = editor.document.uri.fsPath;
let message = 'Unit tests generated for file:' + path.basename(file);
return generateTests({dir: file, msg: message });
}

export function generateTestCurrentFunction(): Thenable<boolean> {
let editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showInformationMessage('gotests: No selected Editor');
return;
}
let file = editor.document.uri.fsPath;
getFunctions(editor.document).then(functions => {
let currentFunction: vscode.SymbolInformation;
for (let func of functions) {
let selection = editor.selection;
if (selection && func.location.range.contains(selection.start)) {
currentFunction = func;
break;
}
};
if (!currentFunction) {
vscode.window.setStatusBarMessage('No function found at cursor.', 5000);
return;
}
let message = 'Unit test generated for function: ' + currentFunction.name + ' in file:' + path.basename(file);
return generateTests({dir: file, msg: message, func: currentFunction.name});
}).then(null, err => {
console.error(err);
});
}

/**
* Input to goTests.
*/
interface Config {
/**
* The working directory for `gotests`.
*/
dir: string;
/**
* The Message that show up in case of success
*/
msg: string;
/**
* Specific function names to generate tests squeleton.
*/
func?: string;
}

function generateTests(conf: Config): Thenable<boolean> {
return new Promise<boolean>((resolve, reject) => {
let cmd = getBinPath('gotests');
let args;
if (conf.func) {
args = ['-w', '-only', conf.func, conf.dir];
} else {
args = ['-w', '-all', conf.dir];
}
cp.execFile(cmd, args, {}, (err, stdout, stderr) => {
try {
if (err && (<any>err).code === 'ENOENT') {
promptForMissingTool('gotests');
return resolve(false);
}
if (err) {
return reject('Cannot generate test due to errors: ' + stderr);
Copy link
Contributor

@ramya-rao-a ramya-rao-a Oct 5, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out, this was failing for me in Windows because I had Go 1.5 on my Windows machine. The error message in such cases is not helpful. We should probably check for the Go version first and not run gotests at all if it is not supported and show a meaningful message like Generating tests using gotests is not supported in Go 1.5.

#509 adds a function for checking the Go version. You can either wait for that PR to get merged or copy over the getGoVersion function from there

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I will wait your PR integration.

Copy link
Contributor

@ramya-rao-a ramya-rao-a Oct 6, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cedriclam my PR has been merged. Get latest from master, and you should have my changes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ramya-rao-a: rebase done; travis builds look fine now.

}
let message = 'gotests: ' + conf.msg;
vscode.window.showInformationMessage(message);
return resolve(true);
} catch (e) {
vscode.window.showInformationMessage(e.msg);
reject(e);
}
});
});
}

function getFunctions(doc: vscode.TextDocument): Thenable<vscode.SymbolInformation[]> {
let documentSymbolProvider = new GoDocumentSymbolProvider();
return documentSymbolProvider
.provideDocumentSymbols(doc, null)
.then(symbols =>
symbols.filter(sym =>
sym.kind === vscode.SymbolKind.Function)
);
}
1 change: 1 addition & 0 deletions src/goInstallTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function getTools(): { [key: string]: string } {
// golint is no longer supported in go1.5
if (goVersion && (goVersion.major > 1 || (goVersion.major === 1 && goVersion.minor > 5))) {
tools['golint'] = 'github.com/golang/lint/golint';
tools['gotests'] = 'github.com/cweill/gotests/...';
}
return tools;
}
Expand Down
13 changes: 13 additions & 0 deletions src/goMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { GO_MODE } from './goMode';
import { showHideStatus } from './goStatus';
import { coverageCurrentPackage, getCodeCoverage, removeCodeCoverage } from './goCover';
import { testAtCursor, testCurrentPackage, testCurrentFile, testPrevious } from './goTest';
import { generateTestCurrentPackage, generateTestCurrentFile, generateTestCurrentFunction } from './goGenerateTests';
import { addImport } from './goImport';
import { installAllTools } from './goInstallTools';

Expand Down Expand Up @@ -92,6 +93,18 @@ export function activate(ctx: vscode.ExtensionContext): void {
updateGoPathGoRootFromConfig();
}));

ctx.subscriptions.push(vscode.commands.registerCommand('go.test.generate.package', () => {
generateTestCurrentPackage();
}));

ctx.subscriptions.push(vscode.commands.registerCommand('go.test.generate.file', () => {
generateTestCurrentFile();
}));

ctx.subscriptions.push(vscode.commands.registerCommand('go.test.generate.function', () => {
generateTestCurrentFunction();
}));

vscode.languages.setLanguageConfiguration(GO_MODE.language, {
indentationRules: {
// ^(.*\*/)?\s*\}.*$
Expand Down
39 changes: 39 additions & 0 deletions test/go.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { testCurrentFile } from '../src/goTest';
import { getGoVersion } from '../src/goInstallTools';
import { documentSymbols } from '../src/goOutline';
import { listPackages } from '../src/goImport';
import { generateTestCurrentFile, generateTestCurrentPackage } from '../src/goGenerateTests';

suite('Go Extension Tests', () => {
let gopath = process.env['GOPATH'];
Expand Down Expand Up @@ -144,6 +145,44 @@ encountered.

});

test('Test Generate unit tests squeleton for file', (done) => {
getGoVersion().then(version => {
if (version.major === 1 && version.minor === 5) {
// gotests is not supported in Go 1.5, so skip the test
return Promise.resolve();
}

let uri = vscode.Uri.file(path.join(fixturePath, 'test.go'));
vscode.workspace.openTextDocument(uri).then(document => {
return vscode.window.showTextDocument(document).then(editor => {
return generateTestCurrentFile().then((result: boolean) => {
assert.equal(result, true);
return Promise.resolve();
});
});
});
}).then(() => done(), done);
});

test('Test Generate unit tests squeleton for package', (done) => {
getGoVersion().then(version => {
if (version.major === 1 && version.minor === 5) {
// gotests is not supported in Go 1.5, so skip the test
return Promise.resolve();
}

let uri = vscode.Uri.file(path.join(fixturePath, 'test.go'));
vscode.workspace.openTextDocument(uri).then(document => {
return vscode.window.showTextDocument(document).then(editor => {
return generateTestCurrentPackage().then((result: boolean) => {
assert.equal(result, true);
return Promise.resolve();
});
});
});
}).then(() => done(), done);
});

test('Gometalinter error checking', (done) => {
let config = Object.create(vscode.workspace.getConfiguration('go'), {
'lintTool': { value: 'gometalinter' }
Expand Down