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

Added support for tests using stretchr/testify #1707

Merged
merged 6 commits into from
Jun 20, 2018
Merged
Show file tree
Hide file tree
Changes from 3 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
7 changes: 5 additions & 2 deletions src/goRunTestCodelens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import vscode = require('vscode');
import path = require('path');
import { TextDocument, CancellationToken, CodeLens, Command } from 'vscode';
import { getTestFunctions, getBenchmarkFunctions, getTestFlags } from './testUtils';
import { getTestFunctions, getBenchmarkFunctions, getTestFlags, extractInstanceTestName } from './testUtils';
import { GoDocumentSymbolProvider } from './goOutline';
import { getCurrentGoPath } from './util';
import { GoBaseCodeLensProvider } from './goBaseCodelens';
Expand Down Expand Up @@ -94,10 +94,13 @@ export class GoRunTestCodeLensProvider extends GoBaseCodeLensProvider {

codelens.push(new CodeLens(func.location.range, runTestCmd));

let instanceMethod = extractInstanceTestName(func.name);
let args = !instanceMethod ? ['-test.run', `^${func.name}$`] : ['-testify.m', `^${instanceMethod}$`];

let debugTestCmd: Command = {
title: 'debug test',
command: 'go.debug.startSession',
arguments: [Object.assign({}, currentDebugConfig, { args: ['-test.run', '^' + func.name + '$'] })]
arguments: [Object.assign({}, currentDebugConfig, { args: args })]
};

codelens.push(new CodeLens(func.location.range, debugTestCmd));
Expand Down
16 changes: 7 additions & 9 deletions src/goTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function testAtCursor(goConfig: vscode.WorkspaceConfiguration, isBenchmar

const getFunctions = isBenchmark ? getBenchmarkFunctions : getTestFunctions;

const {tmpCoverPath, testFlags } = makeCoverData(goConfig, 'coverOnSingleTest', args);
const { tmpCoverPath, testFlags } = makeCoverData(goConfig, 'coverOnSingleTest', args);

editor.document.save().then(() => {
return getFunctions(editor.document, null).then(testFunctions => {
Expand All @@ -59,13 +59,12 @@ export function testAtCursor(goConfig: vscode.WorkspaceConfiguration, isBenchmar
return;
}

const testConfig = {
const testConfig: TestConfig = {
goConfig: goConfig,
dir: path.dirname(editor.document.fileName),
flags: testFlags,
functions: [testFunctionName],
isBenchmark: isBenchmark,
showTestCoverage: true
};

// Remember this config as the last executed test.
Expand Down Expand Up @@ -94,13 +93,12 @@ export function testCurrentPackage(goConfig: vscode.WorkspaceConfiguration, args
return;
}

const {tmpCoverPath, testFlags } = makeCoverData(goConfig, 'coverOnTestPackage', args);
const { tmpCoverPath, testFlags } = makeCoverData(goConfig, 'coverOnTestPackage', args);

const testConfig = {
const testConfig: TestConfig = {
goConfig: goConfig,
dir: path.dirname(editor.document.fileName),
flags: testFlags,
showTestCoverage: true
};
// Remember this config as the last executed test.
lastTestConfig = testConfig;
Expand Down Expand Up @@ -160,11 +158,11 @@ export function testCurrentFile(goConfig: vscode.WorkspaceConfiguration, args: s

return editor.document.save().then(() => {
return getTestFunctions(editor.document, null).then(testFunctions => {
const testConfig = {
const testConfig: TestConfig = {
goConfig: goConfig,
dir: path.dirname(editor.document.fileName),
flags: getTestFlags(goConfig, args),
functions: testFunctions.map(func => { return func.name; })
functions: testFunctions.map(sym => sym.name),
};
// Remember this config as the last executed test.
lastTestConfig = testConfig;
Expand Down Expand Up @@ -203,5 +201,5 @@ function makeCoverData(goConfig: vscode.WorkspaceConfiguration, confFlag: string
testFlags.push('-coverprofile=' + tmpCoverPath);
}

return {tmpCoverPath, testFlags};
return { tmpCoverPath, testFlags };
}
44 changes: 41 additions & 3 deletions src/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { getNonVendorPackages } from './goPackages';

let outputChannel = vscode.window.createOutputChannel('Go Tests');

const testSuiteMethodRegex = /^\([^)]+\)\.(Test.*)$/;

/**
* Input to goTest.
Expand Down Expand Up @@ -89,10 +90,25 @@ export function getTestFunctions(doc: vscode.TextDocument, token: vscode.Cancell
.then(symbols =>
symbols.filter(sym =>
sym.kind === vscode.SymbolKind.Function
&& (sym.name.startsWith('Test') || sym.name.startsWith('Example')))
&& (sym.name.startsWith('Test') || sym.name.startsWith('Example') || testSuiteMethodRegex.test(sym.name))
)
);
}

/**
* Extracts test method name of a suite test function.
* For example a symbol with name "(*testSuite).TestMethod" will return "TestMethod".
*
* @param symbolName Symbol Name to extract method name from.
*/
export function extractInstanceTestName(symbolName: string): string {
const match = symbolName.match(testSuiteMethodRegex);
if (!match || match.length !== 2) {
return null;
}
return match[1];
}

/**
* Returns all Benchmark functions in the given source file.
*
Expand Down Expand Up @@ -152,7 +168,7 @@ export function goTest(testconfig: TestConfig): Thenable<boolean> {

targetArgs(testconfig).then(targets => {
let outTargets = args.slice(0);
if (targets.length > 2) {
if (targets.length > 4) {
outTargets.push('<long arguments omitted>');
} else {
outTargets.push(...targets);
Expand Down Expand Up @@ -242,7 +258,29 @@ function expandFilePathInOutput(output: string, cwd: string): string {
*/
function targetArgs(testconfig: TestConfig): Thenable<Array<string>> {
if (testconfig.functions) {
return Promise.resolve([testconfig.isBenchmark ? '-bench' : '-run', util.format('^%s$', testconfig.functions.join('|'))]);
let params: string[] = [];
if (testconfig.isBenchmark) {
params = ['-bench', util.format('^%s$', testconfig.functions.join('|'))];
} else {
let testFunctions = testconfig.functions;
let testifyMethods = testFunctions.filter(fn => testSuiteMethodRegex.test(fn));
if (testifyMethods.length > 0) {
// filter out testify methods
testFunctions = testFunctions.filter(fn => !testSuiteMethodRegex.test(fn));
testifyMethods = testifyMethods.map(extractInstanceTestName);
}

// we'll skip the '-run' param when running only testify methods, which will result
// in running all the test methods, but that is necessary, cause one of them should
// call testify's `suite.Run(...)`
if (testFunctions.length > 0) {
params = params.concat(['-run', util.format('^%s$', testFunctions.join('|'))]);
Copy link
Contributor

Choose a reason for hiding this comment

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

We have to pass -run ^$ even if test.Functions array is empty. Otherwise all tests will be run

}
if (testifyMethods.length > 0) {
params = params.concat(['-testify.m', util.format('^%s$', testifyMethods.join('|'))]);
}
}
return Promise.resolve(params);
} else if (testconfig.includeSubDirectories && !testconfig.isBenchmark) {
return getGoVersion().then((ver: SemVersion) => {
if (ver && (ver.major > 1 || (ver.major === 1 && ver.minor >= 9))) {
Expand Down