Skip to content

Commit 502de0e

Browse files
committed
feat(goTest): implement compatibility for test suite sub-tests
- Recognizes test suite functions and their sub-tests - Fix propagation of the CodeLens arguments
1 parent 85d7f0c commit 502de0e

File tree

3 files changed

+52
-11
lines changed

3 files changed

+52
-11
lines changed

extension/src/goRunTestCodelens.ts

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,27 +109,44 @@ export class GoRunTestCodeLensProvider extends GoBaseCodeLensProvider {
109109
return codelens;
110110
}
111111

112-
const simpleRunRegex = /t.Run\("([^"]+)",/;
112+
// Captures receiver name and function name.
113+
// reason is: function name coming from f.name is not compatible with struct methods.
114+
const testSuiteRegex = /func \((.*?) .*?\) (Test.*?)\(/;
113115

114116
for (const f of testFunctions) {
115-
const functionName = f.name;
117+
let functionName = f.name;
118+
const line = document.lineAt(f.range.start.line);
119+
const testSuiteMatch = line.text.match(testSuiteRegex);
120+
if (testSuiteMatch) functionName = testSuiteMatch[2]
121+
var receiverName = testSuiteMatch ? testSuiteMatch[1] : 't';
116122

117123
codelens.push(
118124
new CodeLens(f.range, {
119125
title: 'run test',
120126
command: 'go.test.cursor',
121-
arguments: [{ functionName }]
127+
arguments: [{
128+
functionName: functionName,
129+
isTestSuite: !!testSuiteMatch
130+
}]
122131
}),
123132
new CodeLens(f.range, {
124133
title: 'debug test',
125134
command: 'go.debug.cursor',
126-
arguments: [{ functionName }]
135+
arguments: [{
136+
functionName: functionName,
137+
isTestSuite: !!testSuiteMatch
138+
}]
127139
})
128140
);
129141

142+
// Dynamic regex for capturing receiverName.Run("testName", ...)
143+
// receiver name is either t for normal test functions or the receiver of a test suite.
144+
// example: func (s *testSuite) TestFunc() // Returns 's'
145+
let testCaseRegex = new RegExp(receiverName + "\.Run\\(\"([^\"]+)\",");
146+
130147
for (let i = f.range.start.line; i < f.range.end.line; i++) {
131148
const line = document.lineAt(i);
132-
const simpleMatch = line.text.match(simpleRunRegex);
149+
const simpleMatch = line.text.match(testCaseRegex);
133150

134151
// BUG: this does not handle nested subtests. This should
135152
// be solved once codelens is handled by gopls and not by
@@ -141,12 +158,20 @@ export class GoRunTestCodeLensProvider extends GoBaseCodeLensProvider {
141158
new CodeLens(line.range, {
142159
title: 'run test',
143160
command: 'go.subtest.cursor',
144-
arguments: [{ functionName, subTestName }]
161+
arguments: [{
162+
functionName: functionName,
163+
subTestName: subTestName,
164+
isTestSuite: !!testSuiteMatch
165+
}]
145166
}),
146167
new CodeLens(line.range, {
147168
title: 'debug test',
148169
command: 'go.debug.subtest.cursor',
149-
arguments: [{ functionName, subTestName }]
170+
arguments: [{
171+
functionName: functionName,
172+
subTestName: subTestName,
173+
isTestSuite: !!testSuiteMatch
174+
}]
150175
})
151176
);
152177
}

extension/src/goTest.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ async function _subTestAtCursor(
117117
// We use functionName if it was provided as argument
118118
// Otherwise find any test function containing the cursor.
119119
const currentTestFunctions = args?.functionName
120-
? testFunctions.filter((func) => func.name === args.functionName)
120+
? testFunctions.filter((func) => func.name.endsWith(String(args.functionName)))
121121
: testFunctions.filter((func) => func.range.contains(editor.selection.start));
122122
const testFunctionName =
123123
args && args.functionName ? args.functionName : currentTestFunctions.map((el) => el.name)[0];
@@ -226,6 +226,10 @@ type TestAtCursor = {
226226
* Flags to be passed to `go test`.
227227
*/
228228
flags?: string[];
229+
/**
230+
* Whether it's a test suite.
231+
*/
232+
isTestSuite?: boolean;
229233
};
230234

231235
/**
@@ -252,6 +256,7 @@ async function runTestAtCursor(
252256
flags: getTestFlags(goConfig, args),
253257
functions: testConfigFns,
254258
isBenchmark: cmd === 'benchmark',
259+
isTestSuite: !!args?.isTestSuite,
255260
isMod,
256261
applyCodeCoverage: goConfig.get<boolean>('coverOnSingleTest')
257262
};
@@ -273,10 +278,10 @@ export function subTestAtCursor(cmd: SubTestAtCursorCmd): CommandFactory {
273278
* codelens provided by {@link GoRunTestCodeLensProvider}, args
274279
* specifies the function and subtest names.
275280
*/
276-
args?: [SubTestAtCursorArgs]
281+
args?:SubTestAtCursorArgs
277282
) => {
278283
try {
279-
return await _subTestAtCursor(goCtx, getGoConfig(), cmd, args?.[0]);
284+
return await _subTestAtCursor(goCtx, getGoConfig(), cmd, args);
280285
} catch (err) {
281286
if (err instanceof NotFoundError) {
282287
vscode.window.showInformationMessage(err.message);

extension/src/testUtils.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ export interface TestConfig {
8585
* Whether this is a benchmark.
8686
*/
8787
isBenchmark?: boolean;
88+
/**
89+
* Whether this is a test suite
90+
*/
91+
isTestSuite?: boolean;
8892
/**
8993
* Whether the tests are being run in a project that uses Go modules
9094
*/
@@ -736,7 +740,14 @@ function targetArgs(testconfig: TestConfig): Array<string> {
736740
// which will result in the correct thing to happen
737741
if (testFunctions.length > 0) {
738742
if (testFunctions.length === 1) {
739-
params = params.concat(['-run', util.format('^%s$', testFunctions[0])]);
743+
// If it's a test suite, it means the test function is not a root test function.
744+
// By prepending '/', the command will interpret and execute all child test functions
745+
// that matches the pattern of anyTestSuite/givenFunctionName/givenCaseName.
746+
if (testconfig.isTestSuite) {
747+
params = params.concat(['-run', util.format('/^%s$', testFunctions[0])]);
748+
} else {
749+
params = params.concat(['-run', util.format('^%s$', testFunctions[0])]);
750+
}
740751
} else {
741752
params = params.concat(['-run', util.format('^(%s)$', testFunctions.join('|'))]);
742753
}

0 commit comments

Comments
 (0)