I want to be able to run and debug unit tests within VS Code using the test explorer or code lens.
But in order to run my tests, I need to add this flag:
-ldflags "-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn"
Therefore, in my vscode settings.json file, I have added this json:
"go.testFlags": [
"-ldflags",
"\"-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn\""
]
Now when I click the Run Test button in test explorer or in the code lens, VS Code generates this command:
/opt/homebrew/bin/go test -timeout 30s -run ^TestCreateNamespace$ github.com/SomePath/SomeRepo/internal/models/v2 -ldflags "-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn"
but the test case fails with this error:
panic: proto: extension number 1042 is already registered on message google.protobuf.FileOptions
See https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict
And this is the exact error that I am expecting if I dont suply the -ldflags
in my go test command. But the surprising thing is that when I copy the exact same vs code generated test command mentioned above and run that in my terminal then the test case passes.
Along with running the tests from Vs Code, I would also like to be able to debug them by setting breakpoints and stepping through code.
Dev Environment: I am on an arm64 apple M1 Mac if that matters.
UPDATE: After fiddling around with the go.testFlags
values, I have found that:
run test
functionality:"go.testFlags": [
"-ldflags",
"-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn"
]
debug test
functionality:"go.testFlags": [
"-ldflags",
"'-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn'"
]
(Notice the extra single quotes in debug configuration).
Now I need to find a single configuration that works for both run test
as well as debug test
functionalities, Or somehow specify 2 different configs for run test
and debug test
in settings.json
file of vs code so that I can use both functionalities without making changes to the settings.json
file every-time. (This might be a delve thing I suspect)
I can't speak for VS Code, but when it comes to debugging tests that are a bit more complex to step through (e.g. godog cucumber-style tests) I usually compile the test binary like so:
go test -c -gcflags="all=-N -l"
You can replace go test -c
with go build
, so I don't see why you wouldn't be able to simply use
go test -c -ldflags "-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn" -gcflags="all=-N -l"
Then, you can start a dlv
session in headless mode for your editor to connect to. Let's say go test -c
generated a binary called "foo.test":
dlv exec ./foo.test --headless --listen=:2345 --log --api-version=2 -- -count=1 -- $(pwd)/some/path
where -count=1
is a placeholder for the flags you would normally pass to go test
, and -- $(pwd)/some/path
could be (in case you have cucumber style tests) a path to a .feature
file. You can now connect your editor to the dlv session and start debugging. Asking some of my colleagues how that works in VSCode, they said something about a command palette and running Debug: Open launch.json
, which should look something like this:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Test",
"type": "go",
"request": "attach",
"mode": "remote",
"port": 2345,
"host": "127.0.0.1",
"showLog":true,
"trace":"log"
}
]
}
Set the breakpoints, and you should be able to open the debug panel and run Debug test
.
In case anyone wonders, the flow for Vim is pretty much the same, except that there is no need for a json file. Using the vim-go
plugin, once the dlv session is running, you set your breakpoints (:GoDebugBreakpoint
), and connect to dlv: :GoDebugConnect 127.0.0.1:2345
.
From that point on, it's pretty much the same as any debug session :GoDebugContinue
, :GoDebugStep
, :GoDebugStepOut
, :GoDebugPrint varname
and so on)