Skip to content

extension: Test Suite Fails to Parse Subtests Correctly #3725

New issue

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

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

Already on GitHub? Sign in to your account

Open
caioreix opened this issue Mar 19, 2025 · 7 comments
Open

extension: Test Suite Fails to Parse Subtests Correctly #3725

caioreix opened this issue Mar 19, 2025 · 7 comments
Labels
WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@caioreix
Copy link

Describe the bug

When the code len of a subtest suite is called, it ends up causing an incorrect parse of the function, thus not properly generating the test command. It results in something like:
go test -timeout 30s -coverprofile=/tmp/vscode-xxx/go-code-cover -run ^\(\*testSuite\)\.TestSuite_Example$/^Success$ test

The expected output would be something like:
go test -timeout 30s -coverprofile=/tmp/vscode-xxx/go-code-cover -run ^TestSuite$ -m ^(TestSuite_Example$/^Success)$ test

This is happening due to escaping both the function name and the subtest name in this line:

export function escapeSubTestName(testFuncName: string, subTestName: string): string {
return `${testFuncName}/${subTestName}`
.replace(/\s/g, '_')
.split('/')
.map((part) => escapeRegExp(part), '')
.join('$/^');
}

Escaping only the second part would already solve the problem:
https://github.com/caioreix/vscode-go/blob/6061299ff2b1526292a9e1aeff77bf77b3f88f67/extension/src/subTestUtils.ts#L17-L25

Steps to reproduce the behavior:

To reproduce it, you can use the snippet below and click on the codelens 'run test' corresponding to the Success or Fail subtest (I used testify to make visualization easier, but the behavior is the same for any test suite):

package main

import (
	"testing"

	"github.com/stretchr/testify/suite"
)

type testSuite struct {
	suite.Suite
}

func TestSuite(t *testing.T) {
	suite.Run(t, new(testSuite))
}

func (t *testSuite) TestSuite_Example() {
	t.Run("Success", func() {})

	t.Run("Fail", func() {})
}
@gopherbot gopherbot added this to the Untriaged milestone Mar 19, 2025
@jba jba modified the milestones: Untriaged, v0.48.0 Mar 20, 2025
@h9jiang
Copy link
Member

h9jiang commented Mar 20, 2025

Hi @caioreix

I can confirm the sub test "Success" can not be correctly triggered using the code lenses provided. It end up using

Running tool: go test -timeout 30s -run ^\(\*testSuite2\)\.TestSuite_Example$/^Success$ module1

I was able to use the code lenses to trigger test for TestSuite_Example.

Running tool: go test -timeout 30s -run ^TestSuite$ -testify.m ^(TestSuite_Example)$ module1

But I can not run test using the command you provided (it passes but it actually does not run any test)

go test -v -timeout 30s -run ^TestSuite$ -m ^(TestSuite_Example$/^Success)$ module1
=== RUN   TestSuite
    suite.go:234: warning: no tests to run
--- PASS: TestSuite (0.00s)
PASS

Am I constructing the command wrong?

In addition, testify test framework has best-effort support, the team doesn't have the resources to work on it but we'll accept cls.

@h9jiang
Copy link
Member

h9jiang commented Mar 20, 2025

cc @firelizzard18

@caioreix
Copy link
Author

hello @h9jiang!

But I can not run test using the command you provided (it passes but it actually does not run any test)

No, the command itself is correct, but it still doesn’t work because testify doesn’t support subtests. The idea would be to first fix this incorrect interaction from vscode-go. After that, I’m thinking about opening a proposal for implementation in the testify repository, filtering this flag and ignoring the other subtests (I've already made a small POC of the implementation, but I haven't finished it yet.). I used this format ^(METHOD$/^TEST_NAME)$ just to follow the standard from go test, but it’s something we can discuss further to see if there are better options.

@firelizzard18
Copy link
Contributor

firelizzard18 commented Mar 21, 2025

it still doesn’t work because testify doesn’t support subtests

@caioreix Are you using an older version of testify? Newer versions do use subtests and don't require the -m/-testify.m flag. vscode-go's legacy test support does have support for that flag but I don't plan on adding it to the test explorer implementation (vscode-go's or Go Companion's). go test -v -run '^TestSuite$/^TestSuite_Example$/^Success$' will run that specific subtest - I tested locally with your example. Go's parsing of the -run flag changed in CL 343883 (released in 1.18?) but I don't think that's relevant since it's about alternations, e.g. (A|B).

That being said, I'm not sure that the legacy test support or either explorer implementation builds the flag correctly. Go Companion may because that was written after CL 343883.

@h9jiang
Copy link
Member

h9jiang commented Mar 21, 2025

Hi @firelizzard18

Thank you so much for your input here. I'm not familiar with testify framework but I'm glad to see that testify no longer require -m / -testify.m in newer versions. You are right, the -run '^TestSuite$/^TestSuite_Example$/^Success$' successfully triggers the subtest without any issues.

If this works, I don't think we really need to introduce -testify.m flag in vscode-go's testing framework or Go Companion test explorer to avoid over-complicate this. Upon checking the source of vscode-go, I find this place have special handling for testify. Also some other place where vscode-go can be aware of this is a testify test.

the legacy test support or either explorer implementation builds the flag correctly.

Current test support build testify test correctly but does not build testify subtest correctly. The testify test is build using the special handling testify.m mentioned above.

We can make some changes in current vscode-go's test to cleanup those testify related special handling and make this testify subtest work but I wonder if this is something worth doing. Consider the Go Companion is under-development and it works for testify subtest, it might not worth changing the existing vscode-go since it's going to be replaced by Go Companion.

Temporarily move it from v0.48.0 milestone to backlog.

@h9jiang h9jiang added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Mar 21, 2025
@h9jiang h9jiang modified the milestones: v0.48.0, vscode-go/backlog Mar 21, 2025
@caioreix
Copy link
Author

Since the testing part will be replaced by Go Companion, I don't see a problem leaving this implementation for when the migration happens. However, while testing with Go Companion, I noticed that tests written with testify are not recognized by the Test Explorer at the moment. Only functions in the format TestX(t *testing.T) are picked up. Methods like (t *testSuite) TestSuite_Example() as well as their subtests do not appear in the Lens.

@firelizzard18
Copy link
Contributor

However, while testing with Go Companion, I noticed that tests written with testify are not recognized by the Test Explorer at the moment.

Correct; Go Companion eliminates JavaScript based test discovery in favor of using gopls, and that's a new feature (for gopls) which doesn't have support for frameworks like testify. That is something I'd like to add but my main focus for now is supporting table-driven tests.

That being said, they should appear once you execute the test. Granted, those test items are "dynamic" subtests and thus don't have a location (because go test doesn't tell me where the t.Run call happens) among other limitations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

5 participants