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 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
16 changes: 14 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, findAllTestSuiteRuns } from './testUtils';
import { GoDocumentSymbolProvider } from './goOutline';
import { getCurrentGoPath } from './util';
import { GoBaseCodeLensProvider } from './goBaseCodelens';
Expand Down Expand Up @@ -94,10 +94,22 @@ export class GoRunTestCodeLensProvider extends GoBaseCodeLensProvider {

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

let args: string[] = [];
let instanceMethod = extractInstanceTestName(func.name);
if (instanceMethod) {
const testFns = findAllTestSuiteRuns(document, testFunctions);
if (testFns && testFns.length > 0) {
args = args.concat('-test.run', `^${testFns.map(t => t.name).join('|')}$`);
}
args = args.concat('-testify.m', `^${instanceMethod}$`);
} else {
args = args.concat('-test.run', `^${func.name}$`);
}

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
30 changes: 19 additions & 11 deletions src/goTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import path = require('path');
import vscode = require('vscode');
import os = require('os');
import { goTest, TestConfig, getTestFlags, getTestFunctions, getBenchmarkFunctions } from './testUtils';
import { goTest, TestConfig, getTestFlags, getTestFunctions, getBenchmarkFunctions, extractInstanceTestName, findAllTestSuiteRuns } from './testUtils';
import { getCoverage } from './goCover';

// lastTestConfig holds a reference to the last executed TestConfig which allows
Expand All @@ -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,22 @@ export function testAtCursor(goConfig: vscode.WorkspaceConfiguration, isBenchmar
return;
}

const testConfig = {
let testConfigFns = [testFunctionName];

if (!isBenchmark && extractInstanceTestName(testFunctionName)) {
// find test function with corresponding suite.Run
const testFns = findAllTestSuiteRuns(editor.document, testFunctions);
if (testFns) {
testConfigFns = testConfigFns.concat(testFns.map(t => t.name));
}
}

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

// Remember this config as the last executed test.
Expand Down Expand Up @@ -94,13 +103,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 +168,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 +211,5 @@ function makeCoverData(goConfig: vscode.WorkspaceConfiguration, confFlag: string
testFlags.push('-coverprofile=' + tmpCoverPath);
}

return {tmpCoverPath, testFlags};
return { tmpCoverPath, testFlags };
}
57 changes: 54 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,38 @@ 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 !== 3) {
return null;
}
return match[2];
}

/**
* Finds test methods containing "suite.Run()" call.
*
* @param doc Editor document
* @param allTests All test functions
*/
export function findAllTestSuiteRuns(doc: vscode.TextDocument, allTests: vscode.SymbolInformation[]): vscode.SymbolInformation[] {
// get non-instance test functions
const testFunctions = allTests.filter(t => !testSuiteMethodRegex.test(t.name));
// filter further to ones containing suite.Run()
return testFunctions.filter(t => doc.getText(t.location.range).includes('suite.Run('));
}

/**
* Returns all Benchmark functions in the given source file.
*
Expand Down Expand Up @@ -152,7 +181,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 +271,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 might skip the '-run' param when running only testify methods, which will result
// in running all the test methods, but one of them should call testify's `suite.Run(...)`
// which will result in the correct thing to happen
if (testFunctions.length > 0) {
params = params.concat(['-run', util.format('^%s$', testFunctions.join('|'))]);
}
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