-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9c277d5
commit e3049ef
Showing
12 changed files
with
1,512 additions
and
875 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
.tests | ||
site |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
dependencies: | ||
- go.dev | ||
- python |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
--- | ||
icon: material/cog | ||
--- | ||
|
||
# Configuration | ||
|
||
## Options | ||
|
||
!!! tip "Recipes" | ||
|
||
See [the recipes](recipes.md) for usage examples of the below options. | ||
|
||
### `runner` | ||
|
||
Default value: `"go"` | ||
|
||
This option defines the test execution runner, which by default is set to `"go"` | ||
and will use `go test` to write test output to stdout. | ||
|
||
!!! warning "Windows, Ubuntu Snaps" | ||
|
||
If you are on Windows or using Ubuntu snaps, you might want to set the runner | ||
to `"gotestsum"` and/or enable the [`sanitize_output`](#sanitize_output) option. See | ||
[this issue comment](https://github.com/fredrikaverpil/neotest-golang/issues/193#issuecomment-2362845806) | ||
for more details and continue reading. | ||
|
||
To improve reliability, you can choose to set | ||
[`gotestsum`](https://github.com/gotestyourself/gotestsum) as the test runner. | ||
This tool allows the adapter to write test command output directly to a JSON | ||
file without having to go through stdout. | ||
|
||
Using `gotestsum` offers the following benefits: | ||
|
||
- On certain platforms (such as Windows) or in certain terminals, there's a risk | ||
of ANSI codes or other characters being seemingly randomly inserted into the | ||
JSON test output. This can corrupt the data and cause problems with test | ||
output JSON decoding. Enabling `gotestsum` eliminates these issues, as the | ||
test output is then written directly to file. | ||
- When you "attach" (in the Neotest summary window) to a running test, you'll | ||
see clean `go test` output instead of having to navigate through | ||
difficult-to-read JSON, as `gotestsum` is configured to _also_ output non-JSON | ||
test execution to stdout. | ||
|
||
Gotestsum calls `go test` behind the scenes, so your `go_test_args` | ||
configuration remains valid and will still apply. | ||
|
||
??? example "Configure neotest-golang to use `gotestsum` as test runner" | ||
|
||
Make the `gotestsum` command available via e.g. | ||
[mason.nvim](https://github.com/williamboman/mason.nvim) or by running the | ||
following in your shell: | ||
|
||
```bash | ||
go install gotest.tools/gotestsum@latest | ||
``` | ||
|
||
Then add the required configuration: | ||
|
||
```lua | ||
local config = { -- Specify configuration | ||
runner = "gotestsum" | ||
} | ||
require("neotest").setup({ | ||
adapters = { | ||
require("neotest-golang")(config), -- Apply configuration | ||
}, | ||
}) | ||
``` | ||
|
||
### `go_test_args` | ||
|
||
Default value: `{ "-v", "-race", "-count=1" }` | ||
|
||
Arguments to pass into `go test`. See `go help test`, `go help testflag`, | ||
`go help build` for possible arguments. | ||
|
||
The `-json` flag is mandatory and is always appended to `go test` automatically. | ||
|
||
The value can also be passed in as a function. | ||
|
||
!!! warning "CGO" | ||
|
||
The `-race` flag (in `go_test_args`) requires CGO to be enabled | ||
(`CGO_ENABLED=1` is the default) and a C compiler (such as GCC) to be | ||
installed. However, since Go 1.20, this is not a requirement on macOS. I have | ||
included the `-race` argument as default, as it provides good production | ||
defaults. See [this issue](https://github.com/golang/go/issues/9918) for more | ||
details. | ||
|
||
### `gotestsum_args` | ||
|
||
Default value: `{ "--format=standard-verbose" }` | ||
|
||
Arguments to pass into `gotestsum`. Will only be applicable if | ||
`runner = "gotestsum"`. | ||
|
||
The value can also be passed in as a function. | ||
|
||
### `go_list_args` | ||
|
||
Default value: `{}` | ||
|
||
Arguments to pass into `go list`. The main purpose of `go list` is to internally | ||
translate between filepaths and Go package import paths. | ||
|
||
A mandatory query is passed into the `-f` flag and is always appended | ||
automatically, so that the necessary fields can be extracted. | ||
|
||
The value can also be passed in as a function. | ||
|
||
### `dap_mode` | ||
|
||
Default value: `"dap-go"` | ||
|
||
This option toggles between relying on | ||
[leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go) so supply the delve | ||
DAP configuration, or whether you wish to bring your own DAP configuration. | ||
|
||
Set to `"manual"` for manual configuration. | ||
|
||
The value can also be passed in as a function. | ||
|
||
### `dap_go_opts` | ||
|
||
Default value: `{}` | ||
|
||
If using `dap_mode = "dap-go"`, you can supply dap-go with custom options. | ||
|
||
The value can also be passed in as a function. | ||
|
||
### `dap_manual_config` | ||
|
||
Default value: `{}` | ||
|
||
The configuration to apply if `dap_mode == "manual"`. | ||
|
||
The value can also be passed in as a function. | ||
|
||
### `testify_enabled` | ||
|
||
Default value: `false` | ||
|
||
Enable support for [testify](https://github.com/stretchr/testify) suites. | ||
|
||
!!! warning "Not enabled by default" | ||
|
||
This feature comes with some caveats and nuances, which is why it is not enabled | ||
by default. I advise you to only enable this if you need it. | ||
|
||
There are some real shenaningans going on behind the scenes to make this work. | ||
😅 First, an in-memory lookup of "receiver type-to-suite test function" will be | ||
created of all Go test files in your project. Then, the generated Neotest node | ||
tree is modified by mutating private attributes and merging of nodes to avoid | ||
duplicates. I'm personally a bit afraid of the maintenance burden of this | ||
feature... 🙈 | ||
|
||
!!! note "Subtests not supported" | ||
|
||
Right now, nested tests and table tests are not supported. All of this can be | ||
remedied at any time by extending the treesitter queries. Feel free to dig in | ||
and open a PR! | ||
|
||
### `colorize_test_output` | ||
|
||
Default value: `true` | ||
|
||
Enable output color for `SUCCESS`, `FAIL`, and `SKIP` tests. | ||
|
||
### `warn_test_name_dupes` | ||
|
||
Default value: `true` | ||
|
||
Warn about duplicate test names within the same Go package. | ||
|
||
### `warn_test_not_executed` | ||
|
||
Default value: `true` | ||
|
||
Warn if test was not executed. | ||
|
||
### `log_level` | ||
|
||
Default value: `"vim.log.levels.WARN"` | ||
|
||
The `neotest-golang.log` log-level. | ||
|
||
### `sanitize_output` | ||
|
||
Default value: `false` | ||
|
||
Filter control characters and non-printable characters from test output. | ||
Requires the [uga-rosa/utf8.nvim](https://github.com/uga-rosa/utf8.nvim) | ||
library. | ||
|
||
When tests write non-printable characters to stdout/stderr, they can cause | ||
various issues like failing to write output to disk or UI rendering problems. | ||
The `sanitize_output` option helps clean up such output by preserving UTF-8 and | ||
replacing control characters with the Unicode replacement character (�). | ||
|
||
This is particularly useful when: | ||
|
||
- Tests write bytes to stdout/stderr. | ||
- Test output contains terminal control sequences. | ||
- Test output includes non-printable characters. | ||
|
||
The sanitization preserves all regular printable characters including tabs, | ||
newlines, and carriage returns. | ||
|
||
??? example "Example config" | ||
|
||
```diff | ||
return { | ||
{ | ||
"nvim-neotest/neotest", | ||
dependencies = { | ||
"nvim-neotest/nvim-nio", | ||
"nvim-lua/plenary.nvim", | ||
"antoinemadec/FixCursorHold.nvim", | ||
"nvim-treesitter/nvim-treesitter", | ||
- "fredrikaverpil/neotest-golang", -- Installation | ||
+ { | ||
+ "fredrikaverpil/neotest-golang", -- Installation | ||
+ dependencies = { | ||
+ "uga-rosa/utf8.nvim", -- Additional dependency required | ||
+ }, | ||
+ }, | ||
}, | ||
config = function() | ||
require("neotest").setup({ | ||
adapters = { | ||
- require("neotest-golang"), -- Registration | ||
+ require("neotest-golang")({ sanitize_output = true }), -- Registration | ||
}, | ||
}) | ||
end, | ||
}, | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
--- | ||
icon: material/heart-multiple-outline | ||
--- | ||
|
||
# 🙏 PRs are welcome | ||
|
||
Improvement suggestion PRs to this repo are very much welcome, and I encourage | ||
you to begin by reading the below paragraph on the adapter design and engage in | ||
the [discussions](https://github.com/fredrikaverpil/neotest-golang/discussions) | ||
in case the change is not trivial. | ||
|
||
You can run tests, formatting and linting locally with `make all`. Install | ||
dependencies with `make install`. Have a look at the `Makefile` for more | ||
details. You can also use the neotest-plenary and neotest-golang adapters to run | ||
the tests of this repo within Neovim. | ||
|
||
### AST and tree-sitter | ||
|
||
To figure out new tree-sitter queries (for detecting tests), the following | ||
commands are available in Neovim to aid you: | ||
|
||
- `:Inspect` to show the highlight groups under the cursor. | ||
- `:InspectTree` to show the parsed syntax tree (formerly known as | ||
"TSPlayground"). | ||
- `:EditQuery` to open the Live Query Editor (Nvim 0.10+). | ||
|
||
For example, open up a Go test file and then execute `:InspectTree`. A new | ||
window will appear which shows what the tree-sitter query syntax representation | ||
looks like for the Go test file. | ||
|
||
Again, from the Go test file, execute `:EditQuery` to open up the query editor | ||
in a separate window. In the editor, you can now start creating your syntax | ||
query and play around. You can paste in queries from | ||
[`query.lua`](https://github.com/fredrikaverpil/neotest-golang/blob/main/lua/neotest-golang/query.lua) | ||
in the editor, to see how the query behaves and highlights parts of your Go test | ||
file. | ||
|
||
## General design of the adapter | ||
|
||
### Treesitter queries detect tests | ||
|
||
Neotest leverages treesitter AST-parsing of source code to detect tests. This | ||
adapter supplies queries so to figure out what is considered a test. | ||
|
||
From the result of these queries, a Neotest "position" tree is built (can be | ||
visualized through the "Neotest summary"). Each position in the tree represents | ||
either a `dir`, `file` or `test` type. Neotest also has a notion of a | ||
`namespace` position type, but this is ignored by default by this adapter (but | ||
leveraged to supply testify support). | ||
|
||
### Generating valid `go test` commands | ||
|
||
The `dir`, `file` and `test` tree position types cannot be directly translated | ||
over to Go so to produce a valid `go test` command. Go primarily cares about a | ||
Go package's import path, test name regexp filters and the current working | ||
directory. | ||
|
||
For example, these are all valid `go test` command: | ||
|
||
```bash | ||
# run all tests, recursing sub-packages, in the current working directory. | ||
go test ./... | ||
|
||
# run all tests in a given package 'x', by specifying the full import path | ||
go test github.com/fredrikaverpil/neotest-golang/x | ||
|
||
# run all tests in a given package 'x', recursing sub-packages | ||
go test github.com/fredrikaverpil/neotest-golang/x/... | ||
|
||
# run _some_ tests in a given package, based on a regexp filter | ||
go test github.com/fredrikaverpil/neotest-golang -run "^(^TestFoo$|^TestBar$)$" | ||
``` | ||
|
||
> [!NOTE] | ||
> | ||
> All the above commands must be run somewhere beneath the location of the | ||
> `go.mod` file specifying the _module_ name, which in this example is | ||
> `github.com/fredrikaverpil/neotest-golang`. | ||
I figured out that by executing `go list -json ./...` in the `go.mod` root | ||
location, the output provides valuable information about test files/folders and | ||
their corresponding Go package's import path. This data is key to being able to | ||
take the Neotest/treesitter position type and generate a valid `go test` command | ||
for it. In essence, this approach is what makes neotest-golang so robust. | ||
|
||
### Output processing | ||
|
||
Neotest captures the stdout from the test execution command and writes it to | ||
disk as a temporary file. The adapter is responsible for reading the file(s) and | ||
reporting back status and output to the Neotest tree (and specifically the | ||
position in the tree which was executed). It is therefore crucial for outputting | ||
structured data, which in this case is done with `go test -json`. | ||
|
||
One challenge here is that Go build errors are not part of the strucutured JSON | ||
output (although captured in the stdout) and needs to be looked for in other | ||
ways. | ||
|
||
Another challenge is to properly populate statuses and errors into the | ||
corresponding Neotest tree position. This becomes increasingly difficult when | ||
you consider running tests in a recursive manner (e.g. `go test -json ./...`). | ||
|
||
Errors are recorded and populated, per position type, along with its | ||
corresponding buffer's line number. Neotest can then show the errors inline as | ||
diagnostics. | ||
|
||
I've taken an approach with this adapter where I record test outcome for each | ||
Neotest position type and populate it onto each of them, when applicable. | ||
|
||
On some systems and terminals, there are great issues with the `go test` output. | ||
I've therefore made it possible to make the adapter rely on output saved | ||
directly to disk without going through stdout, by leveraging `gotestsum`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
--- | ||
icon: material/information | ||
--- | ||
|
||
--8<-- "README.md" | ||
|
||
--- | ||
|
||
??? question "Why a second Neotest adapter for Go? 🤔" | ||
|
||
While using [neotest-go](https://github.com/nvim-neotest/neotest-go) I stumbled | ||
upon many problems which seemed difficult to solve in that codebase. | ||
|
||
I have full respect for the time and efforts put in by the developer(s) of | ||
neotest-go. I do not aim in any way to diminish their needs or efforts. However, | ||
I wanted to see if I could fix these issues by diving into the 🕳️🐇 of Neotest | ||
and building my own adapter. Below is a list of neotest-go issues which are not | ||
present in neotest-golang (this project): | ||
|
||
| Neotest-go issue | URL | | ||
| ------------------------------------------------------- | --------------------------------------------------------------------- | | ||
| Support for Testify framework | [neotest-go#6](https://github.com/nvim-neotest/neotest-go/issues/6) | | ||
| DAP support | [neotest-go#12](https://github.com/nvim-neotest/neotest-go/issues/12) | | ||
| Test Output in JSON, making it difficult to read | [neotest-go#52](https://github.com/nvim-neotest/neotest-go/issues/52) | | ||
| Support for Nested Subtests | [neotest-go#74](https://github.com/nvim-neotest/neotest-go/issues/74) | | ||
| Diagnostics for table tests on the line of failure | [neotest-go#75](https://github.com/nvim-neotest/neotest-go/issues/75) | | ||
| "Run nearest" runs all tests | [neotest-go#83](https://github.com/nvim-neotest/neotest-go/issues/83) | | ||
| Table tests not recognized when defined inside for-loop | [neotest-go#86](https://github.com/nvim-neotest/neotest-go/issues/86) | | ||
| Running test suite doesn't work | [neotest-go#89](https://github.com/nvim-neotest/neotest-go/issues/89) | | ||
|
||
A comparison in number of GitHub stars between the projects: | ||
|
||
[![Star History Chart](https://api.star-history.com/svg?repos=fredrikaverpil/neotest-golang,nvim-neotest/neotest-go&type=Date)](https://star-history.com/#fredrikaverpil/neotest-golang&nvim-neotest/neotest-go&Date) |
Oops, something went wrong.